react-native-sqlite-storage: Android 11 Open database failed. Could not open database on some Android devices

Hi,

Some of our users have reported an issue related to the SQLite lib. After updating their phone’s OS( Color OS) to 11(Android 11), SQLite operation is broken. In debug mode I see below error:

OPEN database: StorageExtension.db failed, aborting any pending transactions and following if trying to call any transaction:

error: openDatabase {"dblocation": "nosync", "location": "default", "name": "StorageExtension.db"} [[Error: Could not open database]]

I have verified the app and plugin work fine on Color OS 7 and 10, but broken on 11.

Expected Behavior

DB connection is as usual and DB can be opened.

Current Behavior

Opening DB failed

Possible Solution

Related to Android 11?

Steps to Reproduce (for bugs)

Example code im using:

`

SQLite.enablePromise(true); SQLite.DEBUG(true);

const init = async () => { await SQLite.echoTest(); db = await SQLite.openDatabase({ name: DATABASE_NAME, location: ‘default’, }); await createTables(db); }; `

Note that this code works fine on older Color OS and other Android phone like Samsung and Huawei

Your Environment

  • React Native SQLite Storage Version used: “5.0.0”
  • React Native version used: “0.63.3”
  • Operating System and version (simulator or device): Oppo Color OS 11, Android 11
  • IDE used: Android Studio 3.5

Debug logs

image

As shown above, the db was created but at /data/data/<package_path>/databases/

I have also tried the solution to create pre-populated DB but with no luck: https://medium.com/infinitbility/react-native-sqlite-storage-422503634dd2

Any idea why this is happening? We also have users on OnePlus and Pixel reporting the same problem.

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Comments: 59 (5 by maintainers)

Most upvoted comments

I am running into an identical problem.

Related to this and PR #492 … curiously enough … I removed the custom SQLite build and used the device’s SQLite and I got it to work with my existing code.

i.e. I removed this from the react-native.config.js and it worked.

    "react-native-sqlite-storage": {
      platforms: {
        android: {
          sourceDir:
            "../node_modules/react-native-sqlite-storage/platforms/android-native",
          packageImportPath: "import io.liteglue.SQLitePluginPackage;",
          packageInstance: "new SQLitePluginPackage()"
        }
      }
    }

If your target SDK is 29, it runs fine on Android 11, but since Google forces all app updates to target 30 or above, this is no longer an option. We have 4 month left to do the update.

@himu243 so removing those lines means it will interface with the system level SQLite system instead of the one packaged in this project, which I assume resolves the disk permission issue by sidestepping it.

One problem with this approach is if your app supports older versions of android, you might be missing some key SQLite features that your system depends on. For example in my own testing, earlier versions didn’t have “on conflict” support.

Due to maintainer inactivity to accept PRs I’ve created another package based on this package with new android native libraries for API 30 available to use: https://www.npmjs.com/package/react-native-sqlite-storage-api30 https://github.com/Ehsan0Hejazi/react-native-sqlite-storage-api30 npm i react-native-sqlite-storage-api30

Can you tell us what are the changes you have done here so we can have an idea? thanks in advance

I have added new android native libraries patches which is under /platforms/android-native/libs other parts are remained the same,

so now you can switch your android target API to 30 and there will be no bugs and errors

I tried your library there is an error when im trying to build an apk

Due to maintainer inactivity to accept PRs I’ve created another package based on this package with new android native libraries for API 30 available to use:

https://www.npmjs.com/package/react-native-sqlite-storage-api30 https://github.com/Ehsan0Hejazi/react-native-sqlite-storage-api30

npm i react-native-sqlite-storage-api30

We have just created a PR that solves this issue (PR here). We’ve patched and updated the previously added native libraries.

I assume it has to do with the drivers for SQLite but I’m not 100% sure

@KarenMuller

Why A Persistent Android Database Is Never Going To Happen

Its because the ‘spotty-faced kids who can’t get a date’ at Google ‘developed’ a system and are petrified of allowing users to do anything useful on it. As Ken Olsen (and I paraphrase here) once opined ‘here on the East Coast we develop computers, out on the West Cost they just build toys’ and that’s the nub of it.

Android 11 closed all the loopholes that Android 10 allowed so ALL of us grown-up developers at the mercy of Google who now ship every new tablet, phone and device with Android 11 or Android 12 or whatever; one thing for certain is – they are never going to go backwards. So if one develops an application - and targets a particular Android version – one is going to come unstuck one day. Google will ‘pull the rug out from under your feet; because the ‘spotties’ have never written – or can ever know how to write – a proper commercial or scientific operating system. They don’t know how, and they can’t learn how, to do it and they don’t WANT to know how to do it.

I have spent the last week-end reading all the docs and trying hundreds of different test and it boils down to this: when one builds an Android app, one is casting it in concrete, because even if one finds an external directory AND one manages to create a database inside it … that database is inextricably linked – glued if you will – to the application that created it i.e. it only allows access to itself by its creator application and EVEN if one deletes the application (leaving the db behind) and downloads EXACTLY the same application (without any changes whatsoever) then that app cannot open the db - created by a previous incarnation of itself - in any shape or form whatsoever. Even if the db resides in an ‘external’ or so-called ‘public’ directory; in fact even if it resides in ANY directory ANYWHERE within one’s particular version of Android. Yes, one could do this on Android 10 if one marked the app with READ_EXTERNAL_STORAGE and/or WRITE_EXTERNAL_STORAGE, but now on Android 11 even if one marks one’s app with MANAGE_EXTERNAL_STORAGE you still can’t access a db created by another app OR a previous version of one’s own app.

And even if ANY of the above were possible, one would fall foul of the policy at Google instigated by the ‘spotties’ which says ‘anything we don’t like or approve of, you won’t be able to upload to the Play Store’ so go take a hike, Mr Old Fogey Developer.

So there you have it; Google simply don’t want proper, grown-up, commercial apps running on Android.

The fault lies with me, then. I foolishly thought that an Android device was a computer, when in fact it is a toy, and that is purely down to my own incorrect perception of what I was dealing with.

So how does one achieve database persistence? The answer is to use one’s back end servers which hold data persistently e.g. in either a MySQL, SQL Server or Oracle or other such database; lets call this our remote SERVER db. Here goes:

  1. Download your app to Android

  2. Has your app already created its own LOCAL db? No => create a LOCAL db Yes => do nothing i.e. carry on

  3. Does this LOCAL db have any tables? No => create all the LOCAL db tables you need Yes => do nothing i.e. carry on

  4. Do the tables in this LOCAL db have data? No => download these data records from your remote SERVER db, insert them into your LOCAL db, and then into your app Yes => load this LOCAL db data into your app.

Away you go … your app has all the data (yippee!) it needs and it runs

  1. Do you have to perform Inserts, Updates and Deletes? No => do nothing i.e. carry on Yes => send them all to the remote SERVER first Was this send successful? No => try again a limited number of times Yes => update the LOCAL db with whatever you sent to your remote SERVER

…and thus you keep your LOCAL db in step with your remote SERVER and vice versa.

Downsides? Of course. You are doing more networking and updating than necessary because you are keeping TWO databases in synch and that involves more programming, more heartache and more pain. Upsides? Plenty. You are no longer dependant on Google or any Android version or the spotty-faced kids because even at Android 999 (my God, I hope I’m well dead by then) … it should still allow you to create a LOCAL db which is all you need. Even if you update of delete your app (!!) then you can start from Step 1 above and you are back in business. Steps 2 and 3 are trivial and take nanoseconds. Step 4 means for 99% of the time you don’t have to re-populate your LOCAL db because it will always be in synch with your remote SERVER db - provided of course, that you have ensured Step 5 has worked properly for any Inserts, Updates and Deletes.

So, its not perfect by any means, but you are going to get the best of both worlds, i.e. your app can target Android devices (and there are 4 billion of them(!) so they can’t be ignored – much as I would like to), reasonably fast LOCAL db access, some networking overhead and persistent - albeit remote - SERVER db storage. But to my simple mind the most important facet of all … non-reliance on ANY Android version and therefore non-reliance on Google’s spotty-faced kids BUT with the ability to stuff your app into their PlayStore (says it all, doesn’t it?) without the aforementioned ‘spotties’ bitching about it.

I have spent the last 12 years fighting Windows/Visual Studio/Winforms/WPF/UWP and Xamarin AND now MAUI … I’m certainly not going to spend the next 15 years fighting Google!

@andpor @rubenmaas Hi. We had this issue reproducing on Galaxy S20 5G and Galaxy S10 and has been resolved with the new binaries. Hope the information can help.

Hi everyone, any progress on this? Do we still need to test anything? Can we help?

So, as of today (November 2021) targeting API 30 is now a requirement of distributing apps to the Google Play Store. So there’s no workaround for this anymore if you need to use the ‘android-native’ library.