2
respostas

Exceção não tratada no método SalvarAgendamento

// AgendamentoViewModel.cs
private void SalvarAgendamentoBD() {
            using (var conexao = DependencyService.Get<ISQLite>().PegarConexao()) {
                AgendamentoDAO dao = new AgendamentoDAO(conexao);
                dao.SalvarAgendamento(new Agendamento(Nome, Fone, Email, Modelo, Preco));
            }
        }

// SQLiteAndroid.cs
public SQLiteConnection PegarConexao() {
            var caminhoBD = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, nomeArquivoBD); 
            return new SQLite.SQLiteConnection(caminhoBD);
        }

segue abaixo as exceções:

Unhandled Exception: SQLite.SQLiteException: <Timeout exceeded getting exception details> ocorreu

Unhandled Exception: SQLite.SQLiteException: Could not open database file: /storage/emulated/0/Agendamento.db3 (CannotOpen) ocorreu

segue abaixo log:

06-09 19:16:27.888 E/mono    (16840): Unhandled Exception:
06-09 19:16:27.888 E/mono    (16840): SQLite.SQLiteException: Could not open database file: /storage/emulated/0/Agendamento.db3 (CannotOpen)
06-09 19:16:27.888 E/mono    (16840):   at SQLite.SQLiteConnection..ctor (System.String databasePath, SQLite.SQLiteOpenFlags openFlags, System.Boolean storeDateTimeAsTicks, System.Object key) [0x00082] in <eaa146ee868043e287f5507c8701ad9e>:0 
06-09 19:16:27.888 E/mono    (16840):   at SQLite.SQLiteConnection..ctor (System.String databasePath, System.Boolean storeDateTimeAsTicks, System.Object key) [0x00000] in <eaa146ee868043e287f5507c8701ad9e>:0 
06-09 19:16:27.888 E/mono    (16840):   at TestDrive.Droid.SQLiteAndroid.PegarConexao () [0x00016] in C:\Users\gustavo\source\repos\modulo3\TestDrive\TestDrive.Droid\SQLiteAndroid.cs:26 
06-09 19:16:27.888 E/mono    (16840):   at TestDrive.ViewModels.AgendamentoViewModel.SalvarAgendamentoBD () [0x00001] in C:\Users\gustavo\source\repos\modulo3\TestDrive\TestDrive.Aula3\ViewModels\AgendamentoViewModel.cs:126 
06-09 19:16:27.888 E/mono    (16840):   at TestDrive.ViewModels.AgendamentoViewModel+<SalvarAgendamento>d__31.MoveNext () [0x0018b] in C:\Users\gustavo\source\repos\modulo3\TestDrive\TestDrive.Aula3\ViewModels\AgendamentoViewModel.cs:117 
06-09 19:16:27.888 E/mono    (16840): --- End of stack trace from previous location where exception was thrown ---
06-09 19:16:27.888 E/mono    (16840):   at (wrapper dynamic-method) System.Object.27(intptr,intptr)
06-09 19:16:27.888 E/mono    (16840):   at (wrapper native-to-managed) System.Object.27(intptr,intptr)
06-09 19:16:27.889 E/mono-rt (16840): [ERROR] FATAL UNHANDLED EXCEPTION: SQLite.SQLiteException: Could not open database file: /storage/emulated/0/Agendamento.db3 (CannotOpen)
06-09 19:16:27.889 E/mono-rt (16840):   at SQLite.SQLiteConnection..ctor (System.String databasePath, SQLite.SQLiteOpenFlags openFlags, System.Boolean storeDateTimeAsTicks, System.Object key) [0x00082] in <eaa146ee868043e287f5507c8701ad9e>:0 
06-09 19:16:27.889 E/mono-rt (16840):   at SQLite.SQLiteConnection..ctor (System.String databasePath, System.Boolean storeDateTimeAsTicks, System.Object key) [0x00000] in <eaa146ee868043e287f5507c8701ad9e>:0 
06-09 19:16:27.889 E/mono-rt (16840):   at TestDrive.Droid.SQLiteAndroid.PegarConexao () [0x00016] in C:\Users\gustavo\source\repos\modulo3\TestDrive\TestDrive.Droid\SQLiteAndroid.cs:26 
06-09 19:16:27.889 E/mono-rt (16840):   at TestDrive.ViewModels.AgendamentoViewModel.SalvarAgendamentoBD () [0x00001] in C:\Users\gustavo\source\repos\modulo3\TestDrive\TestDrive.Aula3\ViewModels\AgendamentoViewModel.cs:126 
06-09 19:16:27.889 E/mono-rt (16840):   at TestDrive.ViewModels.AgendamentoViewModel+<SalvarAgendamento>d__31.MoveNext () [0x0018b] in C:\Users\gustavo\source\repos\modulo3\TestDrive\TestDrive.Aula3\ViewModels\AgendamentoViewModel.cs:117 
06-09 19:16:27.889 E/mono-rt (16840): --- End of stack trace from previous location where exception was thrown ---
06-09 19:16:27.889 E/mono-rt (16840):   at (wrapper dynamic-method) System.Object.27(intptr,intptr)
06-09 19:16:27.889 E/mono-rt (16840):   at (wrapper native-to-managed) System.Object.27(intptr,intptr)
06-09 19:16:27.898 D/        (16840): HostConnection::get() New Host Connection established 0x8dad6940, tid 16840
2 respostas

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.

A classe MainPage.xaml.cs seria qual no projeto do curso? Não consegui identificar.