Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

SQLiteException

Ao executar a aplicação recebo o seguinte erro

SQLite.SQLiteException: Could not open database file: /storage/emulated/0/scheduling.db3 (CannotOpen)

Todas as permissões estão corretas no Android Manifest. Aqui esta minha classe:

[assembly: Xamarin.Forms.Dependency(typeof(SQLiteAndroid))]
namespace TestDrive.Droid
{
    class SQLiteAndroid : IStorageble
    {
        private const string fileNameDB = "scheduling.db3";

        public SQLiteConnection getConnection()
        {
            var pathDB= Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, fileNameDB);

            return new SQLiteConnection(pathDB);
        }
    }
}
3 respostas
solução!

Provavelmente, o problema ocorre porque mudou o Fluxograma da verificação de permissão de tempo de execução a partir da versão Marshmallow do Android.

A partir do Marshmallow, as aplicações precisam:

  • Verificar se as permissões já foram explicitamente concedidas pelo usuário
  • Mostrar mensagem ao usuário
  • Exibir motivo da permissão
  • Requisitar a permissão ao Android SDK
  • Caso usuário concedeu permissão, chamar a funcionalidade

O fluxo pode ser visualizado nesta figura:

Figura 1: Fluxograma da verificação de permissão de tempo de execução

A partir do seu projeto, implementei as modificações necessárias para interagir com o usuário e requisitar a permissão Permission.Storage, que abrange acesso a armazenamento externo (necessário para o armazenamento do arquivo "scheduling.db3", que é o arquivo do banco de dados o SQLite).

Você precisa seguir os passos abaixo para que funcione também no seu ambiente:

1) No projeto SQLiteOreo.Mobile.csproj, instalar a última versão do pacote NuGet Plugin.Permissions:

https://www.nuget.org/packages/Plugin.Permissions/

PM> Install-Package Plugin.Permissions

2) No Arquivo MainPage.xaml.cs:

  • Adicionar o método OnAppearing():
protected override async void OnAppearing()
{
    base.OnAppearing();

    var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
    if (status != PermissionStatus.Granted)
    {
        if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Storage))
        {
            await DisplayAlert("Acesso a Armazenamento Externo", "É preciso dar permissão para Armazenamento Externo", "OK");
        }

        var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Storage);
        status = results[Permission.Storage];
    }

    if (status == PermissionStatus.Granted)
    {
        var conexao = new BancoDadosDB();
    }
    else if (status != PermissionStatus.Unknown)
    {
        await DisplayAlert("Armazenamento Externo Negado", "Não é possível continuar", "OK");
    }
}

3) No Arquivo MainPage.xaml.cs:

Remover a linha var conexao = new BancoDadosDB();:

public MainPage()
{
    InitializeComponent();
    //var conexao = new BancoDadosDB(); // MOVIDA PARA O MÉTODO OnAppearing()
}

4) No projeto SQLiteOreo.Mobile.Android.csproj, instalar a última versão do pacote NuGet Plugin.Permissions:

https://www.nuget.org/packages/Plugin.Permissions/

PM> Install-Package Plugin.Permissions

5) Na classe BancoDeDadosAndroid, definir o caminho do banco de dados para o ExternalStorageDirectory:

    public class BancoDadosAndroid : ISQLite
    {
        private const string fileNameDB = "scheduling.db3";

        public SQLiteConnection getConnection()
        {
            var pathDB = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, fileNameDB);
            return new SQLiteConnection(pathDB);
        }
    }

6) Na classe MainActivity, adicionar a referência a Plugin.Permissions:

using Plugin.Permissions;

7) Na classe MainActivity, adicionar a linha Plugin.CurrentActivity.CrossCurrentActivity.Current.Init(this, bundle);:

protected override void OnCreate(Bundle bundle)
{
    TabLayoutResource = Resource.Layout.Tabbar;
    ToolbarResource = Resource.Layout.Toolbar;

    base.OnCreate(bundle);

    global::Xamarin.Forms.Forms.Init(this, bundle);
    Plugin.CurrentActivity.CrossCurrentActivity.Current.Init(this, bundle);
    LoadApplication(new App());
}

8) Na classe MainActivity, adicionar o método OnRequestPermissionsResult():

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
    PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

Por favor, veja se o procedimento é adequado para sua solução, e nos avise sobre o resultado.

Obrigado.

Funcionou perfeitamente, professor. Grato!

Excelente, Renan! Um abraço!