Take Control of Your Firebase Init on Android

A while back, we discussed how Firebase initializes on Android. There was a lot of great discussion around that, and it sounded like some of you experimented with the same technique for getting your own Android libraries initialized. Many of you also noted that there were a few situations when you couldn’t use the normal automatic init procedure.

Q&A

What if you have a customized build system?

Normally, Android apps using Firebase are built with Gradle and the Google Services Gradle Plugin. This plugin pulls your Firebase project data out of google-services.json, and adds it to your app’s resources. Once the resources are added to your project, there is a component called FirebaseInitProvider that automatically picks up those values and initializes Firebase with them.

However, if you have a different build system, such as Bazel, or you’re otherwise unable to use the Gradle plugin, you need to find another way to get those resources into your app. The solution could be as simple as creating your own resource XML file and adding the correct values to it. The documentation for the plugin gives the details of how to get those values out of your google-services.json file and into your resources.

What if you need to select your app’s Firebase project at runtime?

It’s very rare, but sometimes an app must be able to select its Firebase project at runtime. This means your app can’t use the automatic init provided by the FirebaseInitProvider that’s merged into your app. In that case, the solution has two tasks.

Selecting a project at runtime

1. Disabling FirebaseInitProvider

FirebaseInitProvider is normally automatically merged into your app build by the Android build tools when doing a build with Gradle. If you’re doing your own init, however, you’ll to make sure it doesn’t get merged at all. The way to do that is to use your own app’s manifest to override that behavior. In your manifest, add an entry for FirebaseInitProvider, and make sure to use a node marker to set its tools:node attribute to the value "remove". This tells the Android build tools not to include this component in your app:

<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"
    >

2. Calling FirebaseApp.initializeApp() to initialize

Because you removed FirebaseInitProvider, you’ll need to perform the same init somewhere in your app (in your own ContentProvider during its onCreate, to ensure Analytics can measure your app correctly). The method you’ll need to call is FirebaseApp.initializeApp(Context, FirebaseOptions). If you click through to the javadoc, you’ll see a few varieties of that method. The one you want takes both a Context and FirebaseOptions to initialize the default FirebaseApp instance. You can create a FirebaseOptions object using its Builder:

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());

The documentation for the plugin will help you locate the correct strings for your project in your google-services.json file.

With these changes in place, you no longer need the Google services plugin and its JSON config file in your project.

Take control!

Again, if you’re happy with the way your Android app builds, you shouldn’t need to implement any of the changes here. Otherwise, if your situation requires it, the information here should be all you need to do to take control of your Firebase init.