Greg Ennis Greg Ennis - 6 months ago 29
Android Question

Using 2 or more GCM Intent Services in one Application

I am writing an application that integrates with Smooch and Carnival. Both these libraries receive GCM push messages using the standard approach of defining a GCM Intent Service to receive messages.

When I use only Smooch, everything works great. When I use only Carnival, everything works great. The problem comes in when I try to use both. What I have found is that the GCM receiver will simply start the first service listed in the manifest that defines intent

com.google.android.c2dm.intent.RECEIVE
.

In fact, I found that the order the libraries are listed in my
build.gradle
affects in which order their manifests are merged into the application manifest. So, if I put smooch first, it works (but Carnival doesn't receive anything). And if I put Carnival first, it works (but Smooch never receives anything).

How can I handle multiple GCM intent services when I don't control either one? In general, how should applications define and manage multiple GCM intent services?

Answer

The reason you can't get push to work in both Carnival and Smooch is that both libraries are registering their own GcmListenerService, and in Android the first GcmListenerService defined in your manifest will receive all GCM messages.

I have a solution for you based primarily off the following SO article: Multiple GCM listeners using GcmListenerService

The best solution would be to just have one GcmListenerService implementation, and have this handle messages for both.

In order to specify your own GcmListenerService, follow the instructions from Google's Cloud Messaging Documentation.

Smooch provides the tools necessary for you to disable their internal GCM registration when you have your own.

To do so, simply call setGoogleCloudMessagingAutoRegistrationEnabled while initializing Smooch:

Settings settings = new Settings("<your_app_token>");
settings.setGoogleCloudMessagingAutoRegistrationEnabled(false);
Smooch.init(this, settings);

And in your own GcmRegistrationIntentService, call Smooch.setGoogleCloudMessagingToken(token); with your token.

Once that is complete, you'll be able to pass the GCM message on to any GCM Receiver that you'd like.

@Override
public void onMessageReceived(String from, Bundle data) {
    final String smoochNotification = data.getString("smoochNotification");

    if (smoochNotification != null && smoochNotification.equals("true")) {
        data.putString("from", from);

        Intent intent = new Intent();
        intent.putExtras(data);
        intent.setAction("com.google.android.c2dm.intent.RECEIVE");
        intent.setComponent(new ComponentName(getPackageName(), "io.smooch.core.GcmService"));

        GcmReceiver.startWakefulService(getApplicationContext(), intent);
    }
}

EDIT

As of Smooch version 3.2.0, you can now more easily trigger Smooch’s notification by calling GcmService.triggerSmoochGcm in your onMessageReceived.

@Override
public void onMessageReceived(String from, Bundle data) {
    final String smoochNotification = data.getString("smoochNotification");

    if (smoochNotification != null && smoochNotification.equals("true")) {
        GcmService.triggerSmoochGcm(data, this);
    }
}
Comments