FirebaseMessaging.getInstance(firebaseApp) for secondary app supposed to be public but it's private?

I have verified a way to do it as I had been facing a similar issue.

I registered one of the projects using the google-services.json file.

Now as per the documentation :

public void onNewToken (String token)

Called when a new token for the default Firebase project is generated.

Here the word "default" is of key importance. It mentions that the onNewToken method in the overridden FirebaseMessagingService (eg: MyFirebaseMessagingService) will only be called for the default project.

Hence in this case the first project configured using the google-services.json will be the default project and for that the onNewToken method will be called.

For the second project, I manually configured the project using the code below following the documentation:

val options = FirebaseOptions.Builder()
        .setProjectId("my-firebase-project")
        .setApplicationId("1:27992087142:android:ce3b6448250083d1")
        .setApiKey("AIzaSyADUe90ULnQDuGShD9W23RDP0xmeDc6Mvw")
        .build()

The values for the parameters can be obtained from the google-services.json file of the second project. (NOTE: DON'T INCLUDE THE SECOND PROJECT'S google-services.json IN THE PROJECT)

google-services.json to manual code mapping

  1. projectId (setProjectId) : project_id key in the root of the json
  2. applicationid (setApplicationId): client > client_info > mobilesdk_app_id. Incase of multiple project make sure that the client used is of the package_name which matches the Android app
  3. apiKey (setApiKey) : client > api_key > current_key (make sure of the package name here as well.

KEY CODE

The most important part here which is tough to find in the documentation is to get the token of the second firebase project.

val app = Firebase.initialize(this, options, "ANY_FIXED_STRING_EXCEPT_DEFAULT")

val firebaseMessaging = app.get(FirebaseMessaging::class.java) as FirebaseMessaging

ymFirebaseMessaging.token.addOnCompleteListener{
                if (!it.isSuccessful) {
                    Log.d(TAG, "Fetching FCM token failed", it.exception)

                    return@addOnCompleteListener
                }


                val token = it.result
                Log.d(TAG, "YM: $token")
                Toast.makeText(
                    activity,
                    "$TAG: Got token",
                    Toast.LENGTH_LONG
                ).show()
}

Note: this answer uses API that is deprecated in newer versions of Firebase SDK and have no replacement, nor there are any plans for replacement according to the feedback I received from Firebase support.

Answer regarding separate projects for FCM and Crashlytics:

Upon discussing with the team, they’ve verified that your use case is not supported by Firebase. You should be using a single Firebase Project/Firebase App for both FCM and Crashlytics. Thanks for understanding.

Answer regarding deprecated method to obtain a token for Sender ID:

I got an update from our engineers, currently the method FirebaseMessaging.getToken() that replaced the FirebaseInstanceId.getToken(senderId, scope) doesn't support multiple Firebase app instances. Upon checking on our end, there’s an existing feature request regarding this. With that, I’ve linked this support case to our existing feature request to support multiple instances in FIS. This will be discussed by our engineers, however, I can't specify how long this will take or exactly when (or if) this feature will be publicly released.


It is possible to receive messages from multiple senders using a different approach than instantiating multiple FirebaseApps.

You can get the Sender ID of the other project under Settings -> Cloud Messaging in Firebase Console and use it on the client to this end.

Sender ID is also what you will receive as RemoteMessage.getFrom() in FirebaseMessagingService.onMessageReceived(RemoteMessage).

Sender ID in Firebase Console

In your client app, you will have to retrieve a token for that sender, to authenticate receiving messages from the other project. Then use that token in the backend as the target of the push message.

val senderId = getSenderIdFromServer()

val token = FirebaseInstanceId.getInstance().getToken(senderId, "FCM")

sendTokenToServer(token)

Warning: FirebaseInstanceId.getToken is now deprecated and there is no replacement that I see in the SDK.

Looks like it's not possible to receive topic messages from a different project though. And currently the new server SDK lacks the ability to send to a device group.


You can access the Firebase message instance using the get(<class>) call. This is with Firebase version 20.x.x

String appName = "FCM";
FirebaseOptions options = new FirebaseOptions.Builder()
                .setApplicationId(applicationId)
                .setApiKey(apiKey)
                .setGcmSenderId(gcmSenderId)
                .setProjectId(projectId)
                .build();

FirebaseApp app = FirebaseApp.initializeApp(context, options, appName);
FirebaseMessaging messageApp = app.get(FirebaseMessaging.class);
messageApp
     .getToken()
     .addOnFailureListener(
         ex -> {
            Log.w(TAG, "FAILED to get FCM token ", ex);
         })
     .addOnSuccessListener(
        instanceIdResult -> {
            String token = instanceIdResult;
            mPrefs.edit().putString(DEVICE_FCM_ID_KEY, token)
                         .putString(DEVICE_REG_ID_APP_VERSION_KEY, mWsiApp.getAppVersion())
                         .apply();
     });