Quickstart-android: Firebase database Persistence not working

Created on 23 May 2016  路  15Comments  路  Source: firebase/quickstart-android

I m not able to enable the presistence, see here i m doing this as per the new api

`
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}

}
`

but still its not working, its crashing and giving error:

FATAL EXCEPTION: main
Process: com.vrjco.v.someapp:background_crash, PID: 30170
java.lang.RuntimeException: Unable to create application com.vrjco.v.someapp.App: java.lang.IllegalStateException: FirebaseApp with name [DEFAULT] doesn't exist.
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4752)
at android.app.ActivityThread.access$1600(ActivityThread.java:172)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1368)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5653)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: FirebaseApp with name [DEFAULT] doesn't exist.
at com.google.firebase.FirebaseApp.getInstance(Unknown Source)
at com.google.firebase.FirebaseApp.getInstance(Unknown Source)
at com.google.firebase.database.FirebaseDatabase.getInstance(Unknown Source)
at com.vrjco.v.someapp.App.onCreate(App.java:14)

Most helpful comment

@vrjgamer FirebaseApp is initialized by a ContentProvider so it is not initialized at the time Application.onCreate is called.

This means you have two options:

  1. Manually initialize FirebaseApp in your Application.onCreate (not recommended)
  2. Call setPersistenceEnabled some other time in your application, like when the first Activity launches.

Be careful though, you can only call setPersistenceEnabled before you have called getReference() for the first time. For this reason I often wrap FirebaseDatabase in a singleton like this:

public class MyDatabaseUtil {

  private static FirebaseDatabase mDatabase;

  public static getDatabase() {
    if (mDatabase == null) {
      mDatabase = FIrebaseDatabase.getInstance()
      mDatabase.setPersistenceEnabled(true);
      // ...
    }

    return mDatabase;

  }

}

And then I call MyDatabaseUtil.getDatabase() from my Activities when I want to use the Database.

All 15 comments

@vrjgamer FirebaseApp is initialized by a ContentProvider so it is not initialized at the time Application.onCreate is called.

This means you have two options:

  1. Manually initialize FirebaseApp in your Application.onCreate (not recommended)
  2. Call setPersistenceEnabled some other time in your application, like when the first Activity launches.

Be careful though, you can only call setPersistenceEnabled before you have called getReference() for the first time. For this reason I often wrap FirebaseDatabase in a singleton like this:

public class MyDatabaseUtil {

  private static FirebaseDatabase mDatabase;

  public static getDatabase() {
    if (mDatabase == null) {
      mDatabase = FIrebaseDatabase.getInstance()
      mDatabase.setPersistenceEnabled(true);
      // ...
    }

    return mDatabase;

  }

}

And then I call MyDatabaseUtil.getDatabase() from my Activities when I want to use the Database.

Thanks that was really helpful, it fixed my issue

@samtstern Why is it not recommended to initialize setPersistenceEnabled(true) in my app's Application class?

@csbenz it will not work because FirebaseApp is not automatically initialized until after your Application onCreate is called.

Also there are a few reasons in general why you may want to avoid subclassing Application if you can:

  • If you use Firebase Crash Reporting, your Application's onCreate may be called multiple times due to the multi-process nature of that service.
  • If your app uses multidex there can be some issues, see MultidexApplication

Thanks a ton for this.

Is there a way to avoid using a singleton? Singletons stay in memory long after the app has been closed by the user.

@sharat9211 the only point of the singleton here is to make sure that you call setPersistenceEnabled exactly once. You can do that using any method you like, such as tracking a boolean state or similar. No need to use a singleton if you have concerns.

public class DatabaseUtil {

    private static FirebaseDatabase mDatabase;

    public static FirebaseDatabase getDatabase() {
        if (mDatabase == null) {
            mDatabase = FirebaseDatabase.getInstance();
            mDatabase.setPersistenceEnabled(true);
        }

        return mDatabase;
    }
}

Not Working

It would really be helpful if there is a way to use the setPeristenceEnabled across different Activities.

@csbenz Here they explain why it usually isn't recommended to put instance data in Application
https://guides.codepath.com/android/Understanding-the-Android-Application-Class

in the Limitations and Warning section

@samtstern I don't know if it's working properly or not, but I think it's not working properly. I'm using Dagger to create my fireplace application and firebaseDatabase so that each step will depend on another step.

i have an application module that look like this :
@Module class AppModule(val application: Application) {

@Provides
@ApplicationScope
internal fun provideContext() : Context = application.applicationContext

@Provides
@ApplicationScope
internal fun provideFirebaseApp(context: Context) : FirebaseApp = FirebaseApp.initializeApp(context) as FirebaseApp

@Provides
@ApplicationScope
internal fun provideResources() : Resources = application.resources

@Provides
@ApplicationScope
internal fun provideFirebaseDatabase(firebaseApp: FirebaseApp): FirebaseDatabase {
    val firebaseDatabase = FirebaseDatabase.getInstance(firebaseApp)

    firebaseDatabase.setPersistenceEnabled(true)
    if (BuildConfig.DEBUG) firebaseDatabase.setLogLevel(Logger.Level.DEBUG)

    return firebaseDatabase
}

@Provides
@ApplicationScope
internal fun provideFirebaseStorage(firebaseApp: FirebaseApp) : FirebaseStorage {
    val firebaseStorage = FirebaseStorage.getInstance(firebaseApp)

    if (BuildConfig.DEBUG) firebaseStorage.maxUploadRetryTimeMillis = 2000
    else firebaseStorage.maxUploadRetryTimeMillis = 300000

    return firebaseStorage
}

@Provides
@UserTable
@ApplicationScope
internal fun provideShoppingItemsTable(firebaseDatabase: FirebaseDatabase) : DatabaseReference =
        firebaseDatabase.reference.child(ConstantHolder.USERS)

}

for what i understand firebaseDatabase persistence mean that if i turn off the internet, all my push and query will still work because firebase cached the data right ?

the problem is that when i try to push data after turning off the network it's still not working . maybe firebase has some retry policy like the firebaseStorage ? or persistence only work if i launch the app without internet ?

Why not just call FirebaseDatabase.getInstance().setPersistenceEnabled(true); in the onCreate method of the first activity you will ever use before you do anything? I just added this to my code and I haven't run into any problems, granted I haven't gone through very extensive testing, but I can login, logout, restart the app while logged in, and perform various database related activities without crashing online or off.

You just simply uninstall the previously installed app. And let it install the fresh app. It will resolve the problem.

For Kotlin Try this:

class DatabaseUtil {
    companion object {
        private val firebaseDatabase: FirebaseDatabase = FirebaseDatabase.getInstance()

        init {
            firebaseDatabase.setPersistenceEnabled(true)
        }

        fun getDatabase() : FirebaseDatabase {
            return firebaseDatabase
        }
    }
}
Was this page helpful?
0 / 5 - 0 ratings