How handle storage permissions?

I use the Sqlite plugin in my app.

On first launch after installation the app (Android only) asks for storage permissions, while my app tries to open the db in the background. This causes the app to crash on first launch, because it doesn’t have the permission to access the file system yet.

What’s the typical/recommended way to deal with this?

Which SQLite plugin? Seems like a bug in the plugin. Most plugins would need to check for those permissions before continuing.

In addition to @max’s (excellent) question, the following piques my curiosity:

Can you provide the code that does this? I’m wondering if you’re trying to interact with native things before the platform is ready.

It’s the @capacitor-community/sqlite, latest stable version 2.4.0

The first connection and query takes place in App.vue:

<template>
  <div id="q-app">
    <router-view />
  </div>
</template>

<script>
import {mapActions} from 'vuex';
import db from 'app/src/db/db'

export default {
  name: 'App',
  methods: {
    ...mapActions('globals', ['handleAuthStateChanged', 'loadSettings'])
  },
  async created() {
    await db.open();
    await this.loadSettings(); //loads settings from the db
    this.handleAuthStateChanged();
  }
}
</script>

Note that it’s based on Quasar, as Vue wasn’t supported yet in Ionic when I started working on the app 8-9 months ago. But as you probably know, Quasar uses Capacitor for the mobile apps.

The app is available in the Play store, I can send you and @max a signed .apk if you wish to try it for yourselves.

I assume you’ve seen the docs for this plugin here:

(scroll down starting from here: https://github.com/capacitor-community/sqlite#usage)

You’ll want to call and wait for the response to requestPermissions before opening your db.

I had honestly missed that piece of info, I used started using the plugin while it was still in beta (or alpha maybe), and I can’t remember ever seeing that until now.

However, adding the line await CapacitorSQLite.requestPermissions() makes no difference, it behaves exactly the same as without that line of code: it pops up the dialog for the storage permissions briefly, and then the app crashes in the background while the dialog is still open. Even if you quickly grant access the app still crashes.

The logs show that requestPermissions() is invoked (see screenshot), but it doesn’t appear to the halt the execution.

Logs

The current code is as follows:

<template>
  <div id="q-app">
    <router-view />
  </div>
</template>

<script>
import { Plugins } from '@capacitor/core';
import {mapActions} from 'vuex';
import db from 'app/src/db/db'
const { CapacitorSQLite } = Plugins;

export default {
  name: 'App',
  methods: {
    ...mapActions('globals', ['handleAuthStateChanged', 'loadSettings'])
  },
  async created() {
    try {
      console.log('0')
      await CapacitorSQLite.requestPermissions();
      console.log('1')
      await db.open();
      console.log('2')
      await this.loadSettings();
      this.handleAuthStateChanged();
    }
    catch(e) {
      console.log(e);
      Plugins.App.exitApp();
    }
  },
}
</script>

Note that it doesn’t log 1 nor 2.

In the above, you’re running query from somewhere else before the permissions have been accepted. Remove all of that other code to isolate this first.

You were right, of course. I did execute a db call in another file. Sorry for that.

I commented out that piece of code for now. The app doesn’t crash now, but it doesn’t execute any code after requestPermissions() even if I grant storage permissions.
The logs (after granting storage permission):

Logs

On subsequent runs it behaves the same way (i.e. it skips everything after requestPermissions()), sans the permission dialog.

If I deny storage permissions, an exception is thrown and the catch() clause executes, as expected:

Logs

Is all of this expected, or am I missing something?

The solution is the use the latest version 2.4.2-8.
requestPermission for Android wasn’t yet implemented in the stable version 2.4.0, hence it not working.