I'm trying to set up a Xamarin.Forms Android client app to receive push notifications from my Azure C# backend. My GCMListenerService.OnMessageReceived()
method is not triggered when I send a message from my backend using SendGcmNativeNotificationAsync(...)
, although the result return success/"Enqueued". I'm successfully receiving windows notifications from the same server event.
My GCMListenerService.OnMessageReceived()
method IS triggered when I send a test message from the Firebase Console, but NOT when I send a test message from the Azure Console -> Notification Hubs area (portal says successfully sent).
I can confirm that my client receives a registration token from Firebase and has Google Play Services available. I'm testing on a physical device, not an emulator.
Any suggestions on the next steps to troubleshoot this? Not sure what to try next.
I'm using Log.Debug statements in GCMListenerService.OnMessageReceived()
to determine if a message has been received or not.
Thanks for any help!
I got it working. I didn't realise that the Android app needed to register with the Notifications Hub; which is silly in retrospect.
Usually this is taken care of by the Xamarin Component GoogleCloudMessagingClient
used by all the walkthroughs, but I didn't want to use that component because I'm learning and wanted to see the boilerplate code.
For anyone else taking this approach, here are the things I needed to add (this isn't copy-paste code to use, just demonstrates my missing link):
var cs = ConnectionString.CreateUsingSharedAccessKeyWithListenAccess(
new Java.Net.URI("sb://YOUR-SERVICE-BUS.servicebus.windows.net/"),
"YOUR-KEY"); // you can get these two values from Azure Console -> Your NotificationHub -> Settings -> Access Policies
var hubName = "your-hub-name"; //the name of your Notification Hub resource on Azure
hub = new NotificationHub(hubName, cs, context); //create the hub (this class is in WindowsAzure.Messaging namespace, which is accessible after you add the Azure Messaging component to your android project)
hub.Register(registrationId, "YOUR_TAG"); //tag can be anything (alphanumeric, -, _, no spaces)
//hub.Register registers this device and its registrationId (from cloud messaging) to the Notifications Hub.
This is in addition to all the other things you need to do as per all the official walkthroughs. I'll list them here as someone may find it helpful.
List of Steps, Google for Details
Firebase:
Azure:
Android Client Project:
AndroidManifest.xml
:<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<permission android:name="[YOUR PACKAGE NAME HERE].permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="[YOUR PACKAGE NAME HERE].permission.C2D_MESSAGE" />
MainActivity
, check if Google Play Services are available.RegistrationIntentService
service to register the client device with Firebase Cloud MessagingMainActivity
onCreate()
methodInstanceIDListenerService
service (for if the app registrationID changes, Google easily for details)GcmListenerService
service for receiving and reacting to cloud messages (Google easily for details)AndroidManifest.xml
, for example the GcmListenerService
as follows (Google easily for more details):<application android:label="YOUR_APP_NAME">
<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="[YOUR APP PACKAGE NAME HERE]" />
</intent-filter>
</receiver>
</application>
If using Xamarin you can simply use the Service
attribute instead of editing AndroidManifest.xml
, which will add the required declarations to the manifest for you, e.g.
[Service(Exported = false)]
class RegistrationIntentService : IntentService
{
NotificationHub
instance and register the unique token / registrationID Firebase returned for the device (as per the code at the start of this post, e.g. my missing link).