5

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?

Greg Ennis
  • 14,917
  • 2
  • 69
  • 74

2 Answers2

6

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);
    }
}
Community
  • 1
  • 1
  • Thanks, it's great to see Smooch offers the ability to do this. Unfortunately I am sure carnival does not. However I should be able to use the same approach and call `startWakefulService` twice with each service, and make sure that my relaying intent service is listed first in the manifest. Will try this and update here. – Greg Ennis Apr 11 '16 at 15:23
  • This works. I actually dont need to disable GCM registration and do my own, because I'm using the same sender ID and API key for both services. Also I can use the smoochNotification flag to send the message to the right place and not just blindly send it to both. So, all good... Thanks! – Greg Ennis Apr 11 '16 at 15:47
0

You are using both as gradle dependencies? You will have to download both libraries and use them as modules, they probably are using the same services, if you download them you can change the services name and solve any issue that can be corelating both.

My guess is that you will probably have to create the GCM broadcast receiver from with your app module (even if it calls the libs services).

Renato Probst
  • 5,914
  • 2
  • 42
  • 45
  • Sorry, I don't understand your answer. The service names aren't the problem - they both have unique names already. I have considered defining my own service to call the other two but it seems fraught with issues. – Greg Ennis Apr 11 '16 at 12:10