Is it safe to initialize Firebase on background thread in Android? What to watch out for?

Viewed 639

In my setup, Firebase takes ~250ms to init (measured on Nexus 5 as a difference in "time to first display" with and without FirebaseInitProvider / CrashlyticsInitProvider on cold start). This is a problem because without Firebase my app takes just 350ms to cold start, and Firebase makes that double.

I'm considering disabling the default FirebaseInitProvider and CrashlyticsInitProvider, which run on the main thread before application starts, and do the initialization manually on a background thread (e.g. starting it from Application.onCreate()).

Q: is it safe to call FirebaseApp.initializeApp() on a background thread? And if so, what should I watch out for? I am aware that if need to e.g. getUser() while Firebase is still starting in background, I have to implement some locking so that my thread waits for it to be ready. I also don't care about accurate screen time reporting, so it's not a problem if Firebase Analyics registers its activity lifecycle callback with a delay.

P.S. There's a synchronized block within FirebaseApp.initializeApp(), which means the engineers assumed someone would try to call that from another thread. I'm more worried about the internals, which are not open-sourced to examine.

P.P.S. Also, my app is a single-process app, so it's unlikely that Application.onStart() will be called multiple times for me (unless I'm missing something here).

1 Answers

From https://firebase.googleblog.com/2017/03/take-control-of-your-firebase-init-on.html

You can get your init info from google-services.json in your project or set a breakpoint in firebase init and see what's in the context.

Disable automatic init in your manifest...

<provider
    android:name="com.google.firebase.provider.FirebaseInitProvider"
    android:authorities="${applicationId}.firebaseinitprovider"
    tools:node="remove"
    />

If you don't have the "tools" namespace added to your manifest root tag, you'll have to add that as well:

<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="your.package"
    >

Init explicitly in your code like this... Could be called from a background thread here possibly...

FirebaseOptions.Builder builder = new FirebaseOptions.Builder()
    .setApplicationId("1:0123456789012:android:0123456789abcdef")
    .setApiKey("your_api_key")
    .setDatabaseUrl("https://your-app.firebaseio.com")
    .setStorageBucket("your-app.appspot.com");
FirebaseApp.initializeApp(this, builder.build());
Related