辅助应用程序的 FirebaseMessaging.getInstance(firebaseApp) 应该是公开的,但它是私有的?

Csa*_*oth 3 android kotlin firebase firebase-cloud-messaging

我正在尝试为辅助 Firebase 应用订阅 FCM(Firebase 云消息传递)主题,根据文档,这可以通过getInstance将辅助 FirebaseApp 实例作为参数的重载来完成:

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)
Run Code Online (Sandbox Code Playgroud)

获取指定 FirebaseApp 的 FirebaseMessaging 实例。

我正在使用 Kotlin,我正在build.gradle像这样拉入包:

implementation "com.google.firebase:firebase-messaging:20.2.0"
Run Code Online (Sandbox Code Playgroud)

但是当我尝试FirebaseMessaging使用重载的实例化 时getInstance,我收到一个错误,指出它不可访问。当我查看包源时,反编译表明重载的构造函数不像无参数的那样是公开的getInstance

implementation "com.google.firebase:firebase-messaging:20.2.0"
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

Tej*_*ala 12

我已经验证了一种方法,因为我遇到了类似的问题。

我使用该google-services.json文件注册了其中一个项目。

现在根据文档

public void onNewToken(字符串令牌)

在为默认Firebase 项目生成新令牌时调用。

在这里,“默认”一词至关重要。它提到onNewToken覆盖中的方法FirebaseMessagingService(例如:MyFirebaseMessagingService)只会为默认项目调用。

因此,在这种情况下,使用 配置的第一个项目google-services.json将是默认项目,为此onNewToken将调用该方法。

对于第二个项目,我使用以下文档中的代码手动配置项目:

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

参数值可以从google-services.json第二个项目的文件中获得。 (注意:不要在项目中包含第二个google-services.json项目)

google-services.json 手动代码映射

  1. projectId (setProjectId) : project_idjson 根中的 key
  2. applicationid (setApplicationId): client > client_info > mobilesdk_app_id。如果有多个项目,请确保使用的客户端package_name与 Android 应用程序匹配
  3. apiKey (setApiKey) : client > api_key > current_key(还要确保这里的包名。

关键代码

在文档中很难找到的最重要的部分是获取第二个 firebase 项目的令牌。

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()
}
Run Code Online (Sandbox Code Playgroud)

  • 你救了我的命。谢谢。确实记录得很差。`val firebaseMessaging = app.get(FirebaseMessaging::class.java) as FirebaseMessaging` 正是我所寻找的。 (4认同)

Csa*_*oth 1

我利用我的 Java 背景,按照“sudo 给我做一个三明治”的思路进行了修改。基本上,我通过反射强制获取另一个getInstance,强制它可访问并无论如何调用它。但这显然是一个黑客行为,所以我正在等待一个合法的解决方案。

        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}")
                }
            }
Run Code Online (Sandbox Code Playgroud)

须藤给我做一个三明治!