Taylor Maxwell Taylor Maxwell - 10 months ago 54
Android Question

Parse Server on Azure doesn't save deviceToken for Android devices

I am setting up a new Parse Server on Azure Notification Hubs to enable a transition away from the hosted Parse.com service. I was able to install the Parse Server iOS framework in our app and have the Azure Parse Server save the user's info (including the deviceToken) when they sign in to the app. [Subsequently when our Windows Application sends out a push request to the Parse Server API, the Parse server fires the sendPush method and then is able to successfully send push notifications to that user.] However I have encountered a problem in implementing notifications in our Android app.
While the Android app is able to use the Parse Server framework (1.13.1) to talk to the Azure Parse Server and create a record in the installation, it does not seem to save the deviceToken and subsequent attempts to send push notifications to that user from the Application over the Parse Server API do show up in the Parse Server logs with code 200 but the notifications are never seen on the Android phone.
I have followed the instructions from Microsoft on setting up an Azure Parse Server using FCM (Firebase Communications Manager):
(Part of those instructions say to set up a

<receiver />
called com.microsoft.windowsazure.notifications.NotificationsBroadcastReceiver, however in Google's migrate-to-FCM instructions they say that "com.google.android.gms.gcm.GcmReceiver is added automatically" so I'm not clear what the receiver is supposed to be for Azure Parse Server notifications.)
I used FCM due to the fact that Google seems to have deprecated the older GCM. I don't know if the Parse server is unable to get the FCM token the same way it expects to get the GCM token. Just to be specific, this is the code that I use to save the installation in an onSuccess method that fires after the user logs in to their [non-Parse] App account successfully [thus having found out what their mainUserName is]:

ParseInstallation.getCurrentInstallation().put("user", mainUserName);
ParseInstallation.getCurrentInstallation().put("username", mainUserName);


This code runs after the FCM token has already been acquired--I can see it in my logs that it was successful. In the RegistrationIntentService class, inside the onHandleIntent method, the code includes a request to FirebaseInstanceId:

String FCM_token = FirebaseInstanceId.getInstance().getToken();

and then a request to the Azure Notification Hub:

NotificationHub hub = new NotificationHub(NotificationSettings.HubName,
NotificationSettings.HubListenConnectionString, this);

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

This data is then stored for use later in sharedPreferences at the end of the method:

sharedPreferences.edit().putString("registrationID", regID ).apply();
sharedPreferences.edit().putString("FCMtoken", FCM_token ).apply();

What makes me confused is that I can receive test push notifications on my Android device from the Azure backend using the Notificaton Hub 'test send' feature but cannot receive notifications coming from the Parse server. I think that this is possibly due to the deviceToken not being saved to the _Installation. I've tried using the
method to just add the FCM_token but the Parse server responds that doing that is not allowed. How can the Android app interact with the Parse framework and the Parse server on Azure so that the deviceToken will actually be saved?

Answer Source

The code posted in the question is necessary but not sufficient: in order to register successfully with FCM and obtain a device token, the AndroidManifest <application /> tag must contain a number of <service /> and <receiver /> elements that both configure FCM and allow its messages to reach the device.

In the Azure article that is linked to in the question, Microsoft says to add a few but does not mention all of these elements that I discovered are necessary in order for the Parse notifications to work:

<service android:name=".MyInstanceIDService"> <intent-filter> <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/> </intent-filter> </service> <service android:name="<your.app.name>.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> <meta-data android:name="com.parse.push.gcm_sender_id" android:value="id:<your-FCM-sender-id>" /> <service android:name="com.parse.PushService" /> <receiver android:name="com.parse.GcmBroadcastReceiver" 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="<your.package.name>" /> </intent-filter> </receiver> <receiver android:name="com.parse.ParsePushBroadcastReceiver" android:exported="false"> <intent-filter> <action android:name="com.parse.push.intent.RECEIVE" /> <action android:name="com.parse.push.intent.OPEN" /> <action android:name="com.parse.push.intent.DELETE" /> </intent-filter> </receiver>

You will want to change <your.package.name> to the package name of your app and <your-FCM-sender-id> to the sender ID that you find in the Google Firebase console for your app under Project settings -> Cloud Messaging.

In the course of transitioning away from Parse.com to an Azure Hub at my employer, i1Biometrics, we set up a simplistic demo Android app called Kirkland in order to model how to set up an app using Parse server on Azure. The code snippet above is taken from it and you can view the whole AndroidManifest file to see the entire context.