Kanika
Kanika

Reputation: 734

Android: Can an Android app have multiple FirebaseMessagingServices

I am building a library project in which I have a FirebaseMessagingService. I also have a FirebaseMesagingService in my app. What I see is, whenever an FCM is sent from the server, only one FirebaseMessagingService processes it. This was not the case when I was using GCM Receivers. Both the GCM Receivers used to receive the message and based on message content, they would/would not do anything about it.

How can I achieve the same in FCM.

Upvotes: 13

Views: 6360

Answers (5)

Oleksiy Pavlenko
Oleksiy Pavlenko

Reputation: 71

If you look at the source code of the Android Firebase Messaging, you will see that a broadcast receiver is used to listen for the “com.google.android.c2dm.intent.RECEIVE” event. The old event name from the GCM is also used in Firebase Cloud Messaging. It is possible to have multiple broadcast receivers, so your library can register its receiver in the android manifest:

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

A broadcast receiver in your library will receive Firebase cloud messages:

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

Upvotes: 1

Ankur
Ankur

Reputation: 1308

In such cases, you should make your LibraryFirebaseMessagingService as parent of your AppFirebaseMessagingService, and declare only AppFirebaseMessagingService in app's AndroidManifest.xml file.

For Example:

in your Library:

public class LibraryFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
         //Your library logic
    }
}

Now in your app:

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

Now in your app's AndroidManifest.xml file:

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

No need to declare LibraryFirebaseMessagingService in any AndroidManifest.xml

Upvotes: 1

vchornenyi
vchornenyi

Reputation: 334

I've got the same issue a few days ago and in our team, we used a slightly different approach which involves reflection.

In general, we use delegate class and provide context via reflection.

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

I've written an article on Medium about this approach if you are interested in the details: link

Upvotes: 2

Kanika
Kanika

Reputation: 734

The android app cannot have multiple FirebaseMessagingService as its a service not a receiver. What one can do, is to check two conditions:

  1. If app has FCMMessagingService registered in its functionality, then provide a method in the library project which can take the message as parameter, received by app's FCMMessagingService.

  2. If the app does not have FCM functionality integrated in it, then have FCMMessagingService in your library project which can handle the fcm sent by the server.

Upvotes: 3

Umang
Umang

Reputation: 1070

Your library's manifest should not have a FirebaseMessagingService subclass. Adding the messa service to the app's manifest should be a part of the integration step, integrating the SDK. Also you should provide a hook in the SDK from where the app can pass the FCM message payload to the SDK.

Essentially if the app does not have its own FirebaseMessagingService subclass it would add your SDK's listener service in the manifest else it will add the hook in its own listener service which passes the payload to your SDK and SDK takes the required action

Upvotes: 6

Related Questions