安卓:一个安卓应用程序可以拥有多个FirebaseMessagingServices吗?

13

我正在构建一个库项目,其中包含一个FirebaseMessagingService。 我的应用程序中也有一个FirebaseMesagingService。 我发现,每当服务器发送FCM时, 只有一个FirebaseMessagingService会处理它。 当我使用GCM接收器时,情况并非如此。 两个GCM接收器都会接收消息,并根据消息内容进行处理或不作任何处理。

我该如何在FCM中实现相同的功能。


你的意思是什么?你想要不止一个FirebaseMessagingService吗? - Peter Haddad
你目前找到解决方案了吗?我可以问一下你最终使用的方法是什么吗?谢谢! - Ripityom
1
嘿@Ripityom,我已经回答了。如果解释不清楚,请告诉我。 - Kanika
5个回答

5
你的库清单(manifest)不应该含有FirebaseMessagingService子类。将消息服务(messa service)添加到应用程序的清单(manifest)应该是集成步骤的一部分,即集成SDK。此外,你应该在SDK中提供一个钩子(hook),用于应用程序传递FCM消息载荷给SDK。
如果应用程序没有自己的FirebaseMessagingService子类,则会将你的SDK的监听器服务(listener service)添加到清单(manifest)中;否则,它将在自己的监听器服务中添加钩子,将负载传递给你的SDK,并由SDK执行所需操作。

2
这个问题涉及到 FirebaseMessagingService,而不是 FirebaseListenerService。在 https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessagingService 上的文档明确建议通过示例清单 xml 来创建该服务的子类。 - Cliabhach
1
我指的是子类本身,可能表述不够清晰,对于MessagingService和ListenerService的拼写错误混淆了fcm和gcm的命名约定感到抱歉。 - Umang
1
好的,这有点帮助。我已经取消了我的踩。答案仍然令人困惑 - 或许您可以添加一些解释您的推理的内容?例如:1. 在每个APK中,只有一个FMS子类可以接收推送消息;2. 如果将两个库添加到APK中,每个库都有自己的子类,则只有一个会接收推送消息;3. 因此,应用程序应该使用自己的子类接收推送消息;4. 库应该提供一个钩子(而不是子类),应用程序子类可以在需要时调用它,以便库执行其任务;5. 这确保了应用程序始终处于控制状态。 - Cliabhach

3

安卓应用程序不能有多个FirebaseMessagingService,因为它是一个服务而不是接收器。可以做的是检查两个条件:

  1. 如果应用程序在其功能中注册了FCMMessagingService,则在库项目中提供一个方法,该方法可以将由应用程序的FCMMessagingService接收到的消息作为参数。

  2. 如果应用程序没有集成FCM功能,则在您的库项目中拥有FCMMessagingService,该服务可以处理服务器发送的fcm。


3

我几天前也遇到了同样的问题,在我们团队中,我们使用了略微不同的方法来解决这个问题,其中涉及到反射。

通常情况下,我们使用委托类,并通过反射提供上下文。

public class OwnPushService extends FirebaseMessagingService {

    private List<FirebaseMessagingService> messagingServices = new ArrayList<>(2);

    public GCPushService() {
        messagingServices.add(new AirshipFirebaseMessagingService());
        messagingServices.add(new TLFirebaseMessagingService());
    }

    @Override
    public void onNewToken(String s) {
        delegate(service -> {
            injectContext(service);
            service.onNewToken(s);
        });
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        delegate(service -> {
            injectContext(service);
            service.onMessageReceived(remoteMessage);
        });
    }

    private void delegate(GCAction1<FirebaseMessagingService> action) {
        for (FirebaseMessagingService service : messagingServices) {
            action.run(service);
        }
    }

    private void injectContext(FirebaseMessagingService service) {
        setField(service, "mBase", this); // util method for recursive field search
    }
}

如果您对这种方法感兴趣,我已经在Medium上写了一篇文章,其中详细介绍了这个过程:链接


2
顺便说一下,上下文也可以在初始化期间注入一次,不需要为每个消息传递方法注入一次。这是 Kotlin 版本:https://gist.github.com/yongjhih/cbd646f6740e166db6d64930cbdc7a8f - Andrew Chen
感谢您提供的解决方案。通过这个,我能够为另一个错误编写一个解决方案 https://stackoverflow.com/a/64804557/6117565 - bikram

1

如果您查看Android Firebase Messaging的源代码,您会发现广播接收器被用于监听“com.google.android.c2dm.intent.RECEIVE”事件。Firebase Cloud Messaging中也使用了GCM的旧事件名称。可以有多个广播接收器,因此您的库可以在android清单中注册其接收器:

<application>
    <receiver
        android:name="com.mylibrary.FirebaseMessagingReceiver"
        android:permission="com.google.android.c2dm.permission.SEND"
        android:exported="true">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
    </receiver>
</application>

你的库中的广播接收器将接收Firebase云消息:

class FirebaseMessagingReceiver: BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        
    }
}

1
在这种情况下,您应该将您的LibraryFirebaseMessagingService作为您的AppFirebaseMessagingService的父类,并且只在应用程序的AndroidManifest.xml文件中声明AppFirebaseMessagingService
例如:
在您的库中:
public class LibraryFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
         //Your library logic
    }
}

现在在你的应用程序中:

public class AppFirebaseMessagingService extends LibraryFirebaseMessagingService {
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
         if(shouldLibraryHandlethis(remoteMessage)) {
            super.onMessageReceived(remoteMessage);
         } else {
            //Your app logic
         }
    }
}

现在在您的应用程序的AndroidManifest.xml文件中:

<service
    android:name=".AppFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

不需要在任何AndroidManifest.xml中声明LibraryFirebaseMessagingService


1
如果所有库都使用这种方法,你如何扩展它们? - Jemshit Iskenderov
对我有效,请记得添加super.onMessageReceived(remoteMessage); - Satya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接