3

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.

Kaloglu
  • 1,651
  • 1
  • 20
  • 31
Matthew Carlson
  • 654
  • 5
  • 12
  • post code of MyGcmListenerService.java – Orbitcoder Aug 30 '16 at 17:50
  • @Bhupendra I'll post it, but it's effectively identical to the gcm same on googles git page. It does not appear to be called in any way, during this process, when the notification in the notification bar is created by the OS. – Matthew Carlson Aug 30 '16 at 18:07

1 Answers1

0

Based from this related SO question, in JSON, "notification" is used for send simple notification without action.

According to this documentation:

Notifications provide an easy way for developers to send a user-visible display message with some predefined keys and optional custom key/value pairs. Data payloads include the developer’s custom key/value pairs only, and the client app must handle the message. You can send messages that have both notification and data payloads.

This SO question also suggested to replace MainActivity.class in the message receiver with the entry activity.

final Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);

You can also check on this link with a sample code on how to open application when notification was clicked. Hope this helps!

Community
  • 1
  • 1
abielita
  • 13,147
  • 2
  • 17
  • 59
  • Thanks for the info, but it's not supposed to be without action, it's supposed to open the launcher intent. Your second part shows java code, looking like you are recommending I use the "data" message, which is what I'm trying to avoid. 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.` – Matthew Carlson Aug 31 '16 at 12:33