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

谁说我不能喝 提交于 2020-11-29 03:16:29

问题


I'm trying to subscribe to an FCM (Firebase Cloud Messaging) topic for a secondary Firebase App and according to the documentation this could be done by the overloaded getInstance which takes the secondary FirebaseApp instance as a parameter:

https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/messaging/FirebaseMessaging#public-static-synchronized-firebasemessaging-getinstance-firebaseapp-app

public static synchronized FirebaseMessaging getInstance (FirebaseApp app)

Gets the FirebaseMessaging instance for the specified FirebaseApp.

I'm using Kotlin and I'm pulling in the package in build.gradle like this:

implementation "com.google.firebase:firebase-messaging:20.2.0"

But when I try to instantiate the FirebaseMessaging with the overloaded getInstance, I get an error stating that it's not accessible. When I look at the package source, the decompilation shows that the overloaded constructor is not public like the parameterless getInstance:

public class FirebaseMessaging {
    public static final String INSTANCE_ID_SCOPE = "FCM";
    private final Context zzb;
    private final FirebaseInstanceId zzc;
    private final Task<zzab> zzd;
    @Nullable
    @SuppressLint({"FirebaseUnknownNullness"})
    @VisibleForTesting
    static TransportFactory zza;

    @NonNull
    public static synchronized FirebaseMessaging getInstance() {
        return getInstance(FirebaseApp.getInstance());
    }

    @Keep
    @NonNull
    static synchronized FirebaseMessaging getInstance(@NonNull FirebaseApp var0) {
        return (FirebaseMessaging)var0.get(FirebaseMessaging.class);
    }

Did I miss something?


回答1:


I reached into my Java background to pull a hack along the lines of "sudo make me a sandwich". Basically I forcefully obtain the other getInstance through reflection, force it to be accessible and call it anyway. But this is clearly a hack, so I'm waiting for a legit solution.

        val getInstance2: Method =
            FirebaseMessaging::class.java.getDeclaredMethod("getInstance", FirebaseApp::class.javaObjectType)
        getInstance2.setAccessible(true)  // if security settings allow this
        // null - for static methods
        val firebaseMessaging: FirebaseMessaging =
            getInstance2.invoke(null, appSingleton.firebaseApp!!) as FirebaseMessaging
        firebaseMessaging.subscribeToTopic(GEO_FENCE_TOPIC)
            .addOnCompleteListener { task ->
                if (!task.isSuccessful) {
                    Timber.d("Could not subscribe to topic ${GEO_FENCE_TOPIC}")
                } else {
                    Timber.d("Subscribed to topic ${GEO_FENCE_TOPIC}")
                }
            }

sudo make me a sandwich!!!




回答2:


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).

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.



来源:https://stackoverflow.com/questions/62253691/firebasemessaging-getinstancefirebaseapp-for-secondary-app-supposed-to-be-publ

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!