When I am getting 'notification' GCM messages, android is automatically creating a notification from the title and body, and putting it into the notification shade.
When I say "notification" here, I mean the one called notification in this document https://developers.google.com/cloud-messaging/concept-options#notifications_and_data_messages
The problem I am having is that when I click on that, nothing happens - It does not launch my activity, or dismiss the notification.
I have tried using the "click_action" options, and that has had no effect. I have added a "data" section, and that has no effect.
when my app is in foreground, I get the onMessageReceived as expected, and the NotificationCompat I build in that re-launches the application as expected.
What am I missing to get the background notifications to launch the app?
Here is the manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="example.package"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="21" />
<!-- [START gcm_permission] -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- [END gcm_permission] -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<permission
android:name="example.package.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="example.package.permission.C2D_MESSAGE" />
<application
android:name="example.package.application.appApplication"
android:allowBackup="true"
android:icon="@drawable/app_app_icon"
android:label="@string/app_name"
android:theme="@style/AppTheme"
tools:replace="android:icon, allowBackup"
>
<activity
android:name="example.package.main.activity.MainActivity"
android:label="@string/app_name"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- [START gcm_receiver] -->
<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" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="example.package" />
</intent-filter>
</receiver>
<!-- [END gcm_receiver] -->
<!-- [START gcm_listener] -->
<service
android:name="example.package.service.MyGcmListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<!-- [END gcm_listener] -->
<!-- [START instanceId_listener] -->
<service
android:name="example.package.service.MyInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<!-- [END instanceId_listener] -->
<service
android:name="example.package.service.RegistrationIntentService"
android:exported="false"></service>
</application>
</manifest>
Here is a sample json I send to GCM:
{
"to" : "<snipped>",
"notification" : {
"title" : "<snipped>",
"body" : "<snipped>",
"icon" : "ic_launcher"
},
"data":{"a":"b"},
"content_available": true,
"click_action":"android.intent.action.MAIN"
}
The only thing I get with verbose logging on when I click the item in the notification window is:
08-30 11:54:35.942 3684-3980/? D/InputReader: Input event(4): value=1 when=7306609326000
08-30 11:54:35.942 3684-3980/? D/InputReader: Input event(4): value=1 when=7306609326000
08-30 11:54:35.942 3684-3980/? I/InputReader: Touch event's action is 0x0 (deviceType=0) [pCnt=1, s=0.323 ] when=7306609326000
08-30 11:54:35.952 3684-3980/? D/InputReader: lastThreadEndTime = 7303509457022, currentThreadStartTime = 7303509466814, diff = 0
08-30 11:54:35.952 3684-3979/? I/InputDispatcher: Delivering touch to (4091): action: 0x0, toolType: 1
08-30 11:54:35.952 4091-4091/? D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
08-30 11:54:35.952 3684-4035/? D/lights: button : 1 +
08-30 11:54:35.992 3684-4035/? D/lights: button : 1 -
08-30 11:54:36.112 3684-3980/? D/InputReader: Input event(4): value=0 when=7306778958000
08-30 11:54:36.112 3684-3980/? D/InputReader: Input event(4): value=0 when=7306778958000
08-30 11:54:36.112 3684-3980/? I/InputReader: Touch event's action is 0x1 (deviceType=0) [pCnt=1, s=] when=7306778958000
08-30 11:54:36.112 3684-3979/? I/InputDispatcher: Delivering touch to (4091): action: 0x1, toolType: 1
This is occurring on a Marshmallow and JellyBean devices, though I have not tested anything between.
I know that I can send the 'data' element alone, to kick my service even when in background, but that has the downside of not working if the application has been force stopped. I'm really trying to figure out what I need to do to get the behavior Google describes on that link.
Here is MyGcmListenerService - It does get properly called while the app is in the foreground.
public class MyGcmListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
/**
* Called when message is received.
*
* @param from SenderID of the sender.
* @param data Data bundle containing message data as key/value pairs.
* For Set of keys use data.keySet().
*/
// [START receive_message]
@Override
public void onMessageReceived(String from, Bundle data) {
// String message = data.getString("message");
String message = data.getBundle("notification").getString("body");
String customFields = data.getBundle("notification").getString("customFields");
String title = data.getBundle("notification").getString("title");
Log.d("From: " + from);
Log.d( "Title: " + title);
Log.d( "Message: " + message);
Log.d( "CustomFields: " + customFields);
if (from.startsWith("/topics/")) {
// message received from some topic.
} else {
// normal downstream message.
}
// [START_EXCLUDE]
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/
/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
sendNotification(message);
// [END_EXCLUDE]
}
// [END receive_message]
/**
* Create and show a simple notification containing the received GCM message.
*
* @param message GCM message received.
*/
private void sendNotification(String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
/* resumes the current activity - just like pressing link on home page */
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setContentTitle("GCM Message")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
To clarify, I am looking specifically on how to get this behavior working with GCM:
According to https://developers.google.com/cloud-messaging/downstream 'When your app is in the background, Android directs messages with notification to the system tray. A user click on a notification opens the app launcher by default.'
I have been able to re-write it with FCM, and I don't see this issue, but I really want to know what I am missing.