Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GcmListenerService.onMessageReceived() not called

I'm currently working on implementing GCM notifications into my app.

The problem that I'm having is that the onMessageReceived() method from my GcmListenerService implementation isn't called. I receive the data from the GCM servers fine, since it automatically generates a notification (I wish to replace this with my own notification using the onMessageReceived() method) but after that none of my log calls are printed in the log.

JSON that is sent from server to GCM server

{
    "notification" : {
        "title" : "Title",
        "text" : "Message",
        "icon" : "@drawable\/ic_notification",
        "click_action" : "OPEN_MAIN_ACTIVITY"
    },
    "registration_ids":[
        "xxxx", "xxxx", "xxxx", "etc"
    ]
}

AndroidManifest.xml (GCM part only)

<!-- GCM START -->
    <receiver
        android:name="com.google.android.gms.gcm.GcmReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <category android:name="com.my.package" />
        </intent-filter>
    </receiver>

    <service
        android:name=".Services.ListenerService"
        android:exported="false" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
    </service>

    <service
        android:name=".Services.IDListenerService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.gms.iid.InstanceID"/>
        </intent-filter>
    </service>
    <!-- GCM END -->

GcmListenerService (just a quick print to see if its called at all)

public class ListenerService extends GcmListenerService {

    private static final String TAG = "MyGcmListenerService";

    @Override
    public void onMessageReceived(String from, Bundle data) {
        String message = data.getString("title");
        Log.d(TAG, "From: " + from);
        Log.d(TAG, "Message: " + message);
    }
}

Not sure if the method to request tokens is relevant, but I can post it if needed.

If any part of the question is unclear, let me know, I'm not the best at explaining.

like image 518
Dan Avatar asked Jul 02 '15 07:07

Dan


3 Answers

As explained in this Github issue which is exactly your problem:

From https://developers.google.com/cloud-messaging/server#notifications_and_data_messages "GCM will display the notification part on the client app’s behalf. When optional data is provided, it is sent to the client app once user clicks on the notification and opens the client app. [...] On Android, data payload can be retrieved in the Intent used to launch your activity."

So, the data is passed in the intent used to launch the activity, after the user taps on the notification. This means you need to do the following:

  • Add a click_action to the notification key you send from the server: e.g.

    send_queue.append({'to': REGISTRATION_ID,
                   'message_id': random_id(),
                   "notification" : {
                      "body" : "Hello from Server! What is going on? Seems to work!!!",
                      "title" : "Hello from Server!",
                      "icon" : "@drawable/ic_school_white_48dp",
                      "sound": "default",
                      "color": "#03A9F4",
                      "click_action": "OPEN_MAIN_ACTIVITY"
                    },
                   'data': { 'message': "Hello" }})
    

See the reference for notification payload at: https://developers.google.com/cloud-messaging/server-ref#notification-payload-support

  • In AndroidManifest.xml add an intent filter on the activity you want to be opened once the user clicks on the notification, with the same action name you used on the "click_action" key on the server side, e.g:

    <activity
        android:name=".ui.MainActivity"
        android:label="@string/title_activity_main" >
        <intent-filter>
            <action android:name="OPEN_MAIN_ACTIVITY" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
    
  • Get the data from the intent on your onCreate() method or on onNewIntent() if you've set the launchMode to singleTop for the activity you want to launch when the notification is clicked, e.g:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        Intent intent = getIntent();
    
        if (intent.hasExtra(Constants.KEY_MESSAGE_TXT)) {
            String message = intent.getStringExtra(Constants.KEY_MESSAGE_TXT);
            Log.d(TAG, message);
        } 
    }
    

I've tested this and can confirm that it works. (using XMPP connection)

like image 120
Alex Bitek Avatar answered Oct 01 '22 22:10

Alex Bitek


The GcmListenerService.onMessageReceived() will not be called if the downstream message (json) contains a notification.

like image 41
Zephyr Avatar answered Oct 01 '22 22:10

Zephyr


To receive the message in onMessageReceived you need to define the top level "data" field in your message object. The notification field is handled automatically and generates a notification, onMessageReceived does not get passed any of the data in the notification field.

Update your message object to include a data field and onMessageReceived should be called:

{
    "notification" : {
        "title" : "Title",
        "text" : "Message",
        "icon" : "@drawable\/ic_notification",
        "click_action" : "OPEN_MAIN_ACTIVITY"
    },
    "data": {
        "some_key": "some_value"
    },
    "registration_ids":[
        "xxxx", "xxxx", "xxxx", "etc"
    ]
}
like image 28
Arthur Thompson Avatar answered Oct 01 '22 22:10

Arthur Thompson