6
votes

For quick information, I am using the following tutorial:

https://azure.microsoft.com/en-us/documentation/articles/notification-hubs-android-push-notification-google-gcm-get-started/

Problem I can receive the push notifications (sent from my Nodejs server) when application is opened. However, when I close the application and remove it from recents too, then I don't receive any push notifications. I am using Azure Push Notifications Hub.

All the code is in above link, however, I am also putting it here as how I have implemented it.

Added the following chunks in Android Manifest file : ( tag not shown for simplicity, I have added chunks in correct places)

<meta-data android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />

<service android:name="<your package>.MyInstanceIDService" android:exported="false">
    <intent-filter>
        <action android:name="com.google.android.gms.iid.InstanceID"/>
    </intent-filter>
</service>

<service
    android:name="<your package>.RegistrationIntentService"
    android:exported="false">
</service>

<receiver android:name="com.microsoft.windowsazure.notifications.NotificationsBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <category android:name="<your package name>" />
    </intent-filter>
</receiver>

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<permission android:name="<your package>.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="<your package>.permission.C2D_MESSAGE"/>

The following are the classes that I added according to tutorial:

public class NotificationSettings {
    public static String SenderId = "<Your project number>";
    public static String HubName = "<Your HubName>";
    public static String HubListenConnectionString = "<Your default listen connection string>";
}

The InstanceID listener service:

import android.content.Intent;
import android.util.Log;
import com.google.android.gms.iid.InstanceIDListenerService;

public class MyInstanceIDService extends InstanceIDListenerService {

    private static final String TAG = "MyInstanceIDService";

    @Override
    public void onTokenRefresh() {

        Log.i(TAG, "Refreshing GCM Registration Token");

        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
    }
};

RegistrationIntentService Class:

import android.app.IntentService;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;

import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.google.android.gms.iid.InstanceID;
import com.microsoft.windowsazure.messaging.NotificationHub;

public class RegistrationIntentService extends IntentService {

    private static final String TAG = "RegIntentService";

    private NotificationHub hub;

    public RegistrationIntentService() {
        super(TAG);
    }

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

        try {
            InstanceID instanceID = InstanceID.getInstance(this);
            String token = instanceID.getToken(NotificationSettings.SenderId,
                    GoogleCloudMessaging.INSTANCE_ID_SCOPE);        
            Log.i(TAG, "Got GCM Registration Token: " + token);

            // Storing the registration id that indicates whether the generated token has been
            // sent to your server. If it is not stored, send the token to your server,
            // otherwise your server should have already received the token.
            if ((regID=sharedPreferences.getString("registrationID", null)) == null) {      
                NotificationHub hub = new NotificationHub(NotificationSettings.HubName,
                        NotificationSettings.HubListenConnectionString, this);
                Log.i(TAG, "Attempting to register with NH using token : " + token);

                regID = hub.register(token).getRegistrationId();

                // If you want to use tags...
                // Refer to : https://azure.microsoft.com/en-us/documentation/articles/notification-hubs-routing-tag-expressions/
                // regID = hub.register(token, "tag1", "tag2").getRegistrationId();

                resultString = "Registered Successfully - RegId : " + regID;
                Log.i(TAG, resultString);       
                sharedPreferences.edit().putString("registrationID", regID ).apply();
            } else {
                resultString = "Previously Registered Successfully - RegId : " + regID;
            }
        } catch (Exception e) {
            Log.e(TAG, resultString="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.
        }

        // Notify UI that registration has completed.
        if (MainActivity.isVisible) {
            MainActivity.mainActivity.ToastNotify(resultString);
        }
    }
}

And Notification Handler:

public class MyHandler extends NotificationsHandler {
    public static final int NOTIFICATION_ID = 1;
    private NotificationManager mNotificationManager;
    NotificationCompat.Builder builder;
    Context ctx;

    @Override
    public void onReceive(Context context, Bundle bundle) {
        ctx = context;
        String nhMessage = bundle.getString("message");
        sendNotification(nhMessage);
        if (MainActivity.isVisible) {
            MainActivity.mainActivity.ToastNotify(nhMessage);
        }
    }

    private void sendNotification(String msg) {

        Intent intent = new Intent(ctx, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        mNotificationManager = (NotificationManager)
                ctx.getSystemService(Context.NOTIFICATION_SERVICE);

        PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
                intent, PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(ctx)
                        .setSmallIcon(R.mipmap.ic_launcher)
                        .setContentTitle("Notification Hub Demo")
                        .setStyle(new NotificationCompat.BigTextStyle()
                                .bigText(msg))
                        .setSound(defaultSoundUri)
                        .setContentText(msg);

        mBuilder.setContentIntent(contentIntent);
        mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
    }
}

There are still some chunks of code that I haven't included here but they can be seen from above link.

Kindly, let me know if there is any special permission to listen to push notification when app is not running.

EDIT

I think if somehow we keep this function onReceive alive even when app is closed then we can acheive this. Still not sure how to do this.

1
Did you ever figure out the answer to this?portfoliobuilder
Not Yet. I am still trying to figure out.SamFast

1 Answers

0
votes

I had a similar problem, not sure if the root cause is the same as yours.

The app would receive push notifications when the app was launched or in background, but would stop receiving notifications when I killed the app from the task manager.

Turns out, the problem was in my Manifest. From the documentation,

Your + ".permission.C2D_MESSAGE" permission to prevent other Android applications from registering and receiving the Android application's messages. The permission name must exactly match this pattern—otherwise the Android application will not receive the messages.

I had defined my permission as

<permission
    android:name=".permission.C2D_MESSAGE"
    android:protectionLevel="signature" />

<uses-permission android:name=".permission.C2D_MESSAGE" />

The reason I used the . notation instead of the complete package name was that I had used the applicationIdSuffix for my debug build. I assumed Gradle would complete the package name correctly based on the build type.

This was where I was mistaken. Apparently Gradle does not update the package with suffix in Permissions. To fix this, I replaced the code with,

<permission
    android:name="${applicationId}.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />

<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />

With this, the app started receiving notifications even when killed.