Home » Android » android – Firebase Database crash SQLiteDatabaseLockedException

android – Firebase Database crash SQLiteDatabaseLockedException

Posted by: admin May 14, 2020 Leave a comment

Questions:

I’m getting this crash on few devices, but only on Android 4.

I’m on Firebase Android SDK 10.2.1 11.0.2. Deferring updating to the latest version because it forces update of Google Play Services as well, and many users continue to remain on older GPS versions.

Is anybody else seeing this problem?

Update: This was working earlier. Crashes started after I upgraded from Firebase SDK 9.4.0 to 10.2.1, and compileSdkVersion 23 to 25. Crash only happens on Android 4.4 (Kitkat 19)

Updated Exception:

Fatal Exception: java.lang.RuntimeException
       at com.google.android.gms.internal.mz.run(Unknown Source)
       at android.os.Handler.handleCallback(Handler.java:808)
       at android.os.Handler.dispatchMessage(Handler.java:103)
       at android.os.Looper.loop(Looper.java:193)
       at android.app.ActivityThread.main(ActivityThread.java:5292)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:515)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
       at dalvik.system.NativeStart.main(NativeStart.java)
Caused by o.kD: Failed to gain exclusive lock to Firebase Database's offline persistence. This generally means you are using Firebase Database from multiple processes in your app. Keep in mind that multi-process Android apps execute the code in your Application class in all processes, so you may need to avoid initializing FirebaseDatabase in your Application class. If you are intentionally using Firebase Database from multiple processes, you can only enable offline persistence (i.e. call setPersistenceEnabled(true)) in one of them.
       at com.google.android.gms.internal.nb.zzN(Unknown Source)
       at com.google.android.gms.internal.nb.(Unknown Source)
       at com.google.android.gms.internal.mx.zza(Unknown Source)
       at com.google.android.gms.internal.qd.zzgQ(Unknown Source)
       at com.google.android.gms.internal.qu.zzHg(Unknown Source)
       at com.google.android.gms.internal.qu.zza(Unknown Source)
       at com.google.android.gms.internal.qv.run(Unknown Source)
       at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
       at java.util.concurrent.FutureTask.run(FutureTask.java:237)
       at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
       at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
       at java.lang.Thread.run(Thread.java:841)
Caused by android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode
       at android.database.sqlite.SQLiteConnection.nativePrepareStatement(SQLiteConnection.java)
       at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:893)
       at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:638)
       at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:320)
       at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:294)
       at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215)
       at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
       at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
       at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
       at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
       at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:829)
       at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:814)
       at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:709)
       at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:1039)
       at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:256)
       at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
       at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
       at com.google.android.gms.internal.nb.zzN(Unknown Source)
       at com.google.android.gms.internal.nb.(Unknown Source)
       at com.google.android.gms.internal.mx.zza(Unknown Source)
       at com.google.android.gms.internal.qd.zzgQ(Unknown Source)
       at com.google.android.gms.internal.qu.zzHg(Unknown Source)
       at com.google.android.gms.internal.qu.zza(Unknown Source)
       at com.google.android.gms.internal.qv.run(Unknown Source)
       at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
       at java.util.concurrent.FutureTask.run(FutureTask.java:237)
       at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
       at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
       at java.lang.Thread.run(Thread.java:841)

I do have multiple processes in the app, but using the following code to abort Application.onCreate for sub processes.

@Override
public void onCreate() {
    super.onCreate();

    if (FirebaseApp.getApps(this).isEmpty()) {
        // No firebase apps; we are in a non-main process
        return;
    }

    // Firebase init and other custom logic
    FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}
How to&Answers:

There is no SQLiteDatabaseLockedException in Firebase. This SQLiteDatabaseLockedException is thrown when you are using a SQLite database with Android and the database engine is unable to acquire a database lock that is needs to do its job.

If the statement is a [COMMIT] or occurs outside of an explicit transaction, then you can retry the statement. If the statement is not a [COMMIT] and occurs within a explicit transaction then you should rollback the transaction before continuing.

Edit: With the new edit of your detailed stack trace, i see what the error is. The error is occuring when you are setting setPersistenceEnabled(true). This must be done before doing anything else with your firebaseDatabase object. So, i recomand you using the following code:

public class HelperClass {
    private static FirebaseDatabase firebaseDatabase;
    public static FirebaseDatabase getDatabase() {
        if (firebaseDatabase == null) {
            firebaseDatabase = FirebaseDatabase.getInstance();
            firebaseDatabase.setPersistenceEnabled(true);
        }
        return firebaseDatabase;
    }
}