4

Google is recommending to use GcmListenerService in place of GcmBroadcastReceiver.

Am making a Library project(com.android.library plugin) which is using GCM. It works well when Application project(com.android.application plugin) is NOT using GCM for it's own.

When Application project is using GCM for it's own, Library project receiver is not getting called!

Library module has defined GCM permissions and receiver & service entries in it's manifest. App module has defined it's service entry in it's own manifest.

With GcmBroadcastReceiver this could've been possible, as it is a broadcast. Have seen many questions here for the same. Don't want to use GcmBroadcastReceiver because of deprecation.

Is there any way to make this work?

Edit: Which Service will get invoked is depends on order in which it's defined in merged manifest xml. If I reverse the order, the other Service is getting invoked! Is there any way to call both Services?

sandeepd
  • 515
  • 2
  • 16
  • Does this address your problem? [http://stackoverflow.com/questions/17212275/register-gcm-from-a-library-project][1] [1]: http://stackoverflow.com/questions/17212275/register-gcm-from-a-library-project – N.T. Aug 17 '15 at 12:26
  • @N.T. That link is taking about GCMBroadcastReceiver. Google is recommending to migrate to GcmListenerService based implementation, see [here](https://developers.google.com/cloud-messaging/android/client). If nothing works I will have no option but to use GCMBroadcastReceiver only. – sandeepd Aug 17 '15 at 12:33

2 Answers2

4

@morepork has answered this correctly. Am just answering this to add code snippet.

This surely isn't perfect solution, but I didn't find any better for the moment.

This is how my code looks like:

@Override
public void onMessageReceived(String from, Bundle data) {
    if(!"MY_SENDER_ID".equals(from)) {
        data.putString("from", from);

        Intent intent = new Intent();
        intent.putExtras(data);
        intent.setAction("com.google.android.c2dm.intent.RECEIVE");
        intent.setComponent(new ComponentName(getPackageName(), "my.application.packageId.MyGcmListenerService"));

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

Need to make sure to start all Service Listeners defined in merged manifest, and this Listener having highest priority. I know kind of a constraint.

Edit: Just decompiled the com.google.android.gms.gcm.GcmReceiver class, it's not doing anything great than previous GcmBroadcastReceiver. Just handling token refresh extra. So it's better to use GcmBroadcastReceiver only when you need multiple callbacks.

sandeepd
  • 515
  • 2
  • 16
1

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

If you really want to have two implementations, make one the main implementation by increasing it's priority (see here). Then you can have that service invoke the second one by creating an intent with the data, explicitly setting the component, then starting the other service.

morepork
  • 973
  • 6
  • 9
  • I'll be distributing my library for public use, in AAR format with ProGuard. Obviously Library service wouldn't be knowing which App service to call. Besides that, I feel Priority attribute is for Activity and Broadcast only. – sandeepd Aug 18 '15 at 04:09
  • Okay, out of curiosity, I tried using Priority attribute, it worked as you said. But my problem still remain the same, I want both Services to get invoked. Let me provide a method for client app to provide his Service name, and then invoke it from my Lib Service if SenderId is not mine. Thanks a lot! – sandeepd Aug 18 '15 at 06:12
  • Can you provide more details? I'm having the same problem. The main implementation can be inside the library? If i implement this way, the application should change to support this new implementation? – Sandro Simas Apr 15 '16 at 14:15