Receive Android Push Notification even though App is Closed

7

I've tried using Google GCM but when the app is closed (Swipe or clear from the task manager), it wont receive any push notifications. And when i open the app again, the notification is already gone and lost.

GCM is working for: - App is open - App is minimized

Not working: - App is closed (swipe from task manager) - App is closed via clear all open apps in task manager

I want receive push notifications even though the app is closed just like Facebook or instagram. How can i achieve this?? Is this possible in GCM? if yes how? if no then what are the other way to achieve this??

here is my code:

AndroidManifest.xml

<!-- [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" />
            <category android:name="com.example.airwyntin.notificationtest" />
        </intent-filter>
    </receiver>
    <!-- [END gcm_receiver] -->

    <!-- [START gcm_listener] -->
    <service
        android:name=".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=".MyInstanceIDListenerService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.gms.iid.InstanceID"/>
        </intent-filter>
    </service>
    <!-- [END instanceId_listener] -->
    <service
        android:name=".RegistrationIntentService"
        android:exported="false">
    </service>

MyGcmListenerService.java:

public class MyGcmListenerService extends GcmListenerService {


private static int notifId = 0;

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("alert");


    Log.i(TAG, "From: " + from);

    if (message != null) {
        Log.d(TAG, "From: " + from);
        Log.d(TAG, "Message: " + message);

        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, NotificationView.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    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.mipmap.ic_launcher)
            .setContentTitle("GCM Tesst Message")
            .setContentText(message)
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);

    //Vibration
    notificationBuilder.setVibrate(new long[] { 0, 200, 200, 200, 200, 200 });


    //LED
    //notificationBuilder.setLights(Color.RED, 3000, 3000);

    NotificationManager notificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    Notification notif = notificationBuilder.build();
    notif.flags |= Notification.FLAG_AUTO_CANCEL;

    /*notif.ledARGB = 0xFFff0000;
    notif.flags = Notification.FLAG_SHOW_LIGHTS;
    notif.ledOnMS = 100;
    notif.ledOffMS = 100;*/

    notificationManager.notify(notifId++ /* ID of notification */, notif);

}
}

MyInstanceIDListenerService.java:

public class MyInstanceIDListenerService extends InstanceIDListenerService {

private static final String TAG = "MyInstanceIDLS";

/**
 * Called if InstanceID token is updated. This may occur if the security of
 * the previous token had been compromised. This call is initiated by the
 * InstanceID provider.
 */
// [START refresh_token]
@Override
public void onTokenRefresh() {
    // Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
    Intent intent = new Intent(this, RegistrationIntentService.class);
    startService(intent);
}
// [END refresh_token]


}

RegistrationIntentService.java:

public class RegistrationIntentService extends IntentService {

private static final String TAG = "RegIntentService";
private static final String[] TOPICS = {"global"};

public RegistrationIntentService() {
    super(TAG);
}

@Override
protected void onHandleIntent(Intent intent) {
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);

    try {
        // [START register_for_gcm]
        // Initially this call goes out to the network to retrieve the token, subsequent calls
        // are local.
        // R.string.gcm_defaultSenderId (the Sender ID) is typically derived from google-services.json.
        // See https://developers.google.com/cloud-messaging/android/start for details on this file.
        // [START get_token]
        InstanceID instanceID = InstanceID.getInstance(this);
        String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
                GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
        // [END get_token]
        Log.i(TAG, "GCM Registration Token: " + token);

        // TODO: Implement this method to send any registration to your app's servers.
        sendRegistrationToServer(token);

        // Subscribe to topic channels
        subscribeTopics(token);

        // You should store a boolean that indicates whether the generated token has been
        // sent to your server. If the boolean is false, send the token to your server,
        // otherwise your server should have already received the token.
        sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, true).apply();
        // [END register_for_gcm]
    } catch (Exception e) {
        Log.d(TAG, "Failed to complete token refresh", e);
        // If an exception happens while fetching the new token or updating our registration data
        // on a third-party server, this ensures that we'll attempt the update at a later time.
        sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, false).apply();
    }
    // Notify UI that registration has completed, so the progress indicator can be hidden.
    Intent registrationComplete = new Intent(QuickstartPreferences.REGISTRATION_COMPLETE);
    LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}

/**
 * Persist registration to third-party servers.
 *
 * Modify this method to associate the user's GCM registration token with any server-side account
 * maintained by your application.
 *
 * @param token The new token.
 */
private void sendRegistrationToServer(String token) {
    // Add custom implementation, as needed.
}

/**
 * Subscribe to any GCM topics of interest, as defined by the TOPICS constant.
 *
 * @param token GCM token
 * @throws IOException if unable to reach the GCM PubSub service
 */
// [START subscribe_topics]
private void subscribeTopics(String token) throws IOException {
    GcmPubSub pubSub = GcmPubSub.getInstance(this);
    for (String topic : TOPICS) {
        pubSub.subscribe(token, "/topics/" + topic, null);
    }
}
// [END subscribe_topics]

}
android
notifications
google-cloud-messaging
push
asked on Stack Overflow Jun 1, 2016 by heyou • edited Jun 1, 2016 by heyou

3 Answers

0

As per the official statement of GCM it works with Google play services library so try to check if your mobile have the latest updates of Google play services installed also sometimes internet connectivity problem conject the network causes the problem with GCM push notification or else you can check for delivery receipt if receiver has really receive the message or not. But what you say that GCM will not work when app is not in foreground is incorrect

answered on Stack Overflow Jun 1, 2016 by Akshay Chopde
0

When the app is closed forcefully by the user : notifications don't arrive

It's a feature of the Android platform. Force stopping an application by the user puts the application in a stopped state and none of its code is run, including any broadcast receivers declared in manifest. Only when the user explicitly launches the app it is put in a state where the receivers get fired.

For more documentation regarding Force Stop, please follow this links:

answered on Stack Overflow Jun 4, 2016 by Android Enthusiast
0

A simple solution for this problem is that, "set priority high while building your notification". Priority constant varies in the range from -2 to 2(lowest to highest) and 0 is default value for this field. Hope this will help. Thanks.

answered on Stack Overflow Sep 21, 2016 by Ashutosh Gourav

User contributions licensed under CC BY-SA 3.0