Sending Push Notifications from Azure Mobile Apps

PDF for offline use
Sample Code:
Related Articles:
Related SDKs:

Let us know how you feel about this

Translation Quality


0/250

last updated: 2016-09

Azure Notification Hubs provide a scalable push infrastructure for sending mobile push notifications from any backend to any mobile platform, while eliminating the complexity of a backend having to communicate with different platform notification systems. This article demonstrates how to use Azure Notification Hubs to send push notifications from an Azure Mobile Apps instance to a Xamarin.Forms application.

Overview

A push notification is used to deliver information, such as a message, from a backend system to an application on a mobile device in order to increase application engagement and usage. The notification can be sent at anytime, even when the user is not actively using the targeted application.

Backend systems send push notifications to mobile devices through Platform Notification Systems (PNS), as shown in the following diagram:

To send a push notification, the backend system contacts the platform-specific PNS to send a notification to a client application instance. This significantly increases the complexity of the backend when cross-platform push notifications are required, because the backend must use each platform-specific PNS API and protocol.

Azure Notification Hubs eliminate this complexity by abstracting the details of the different platform notification systems, allowing a cross-platform notification to be sent with a single API call, as shown in the following diagram:

To send a push notification, the backend system only contacts the Azure Notification Hub, which in turn communicates with the different platform notification systems, therefore decreasing the complexity of the backend code that sends push notifications.

Azure Mobile Apps have built-in support for push notifications using notification hubs. The process for sending a push notification from an Azure Mobile Apps instance to a Xamarin.Forms application is as follows:

  1. The Xamarin.Forms application registers with the PNS, which returns a handle.
  2. The Azure Mobile Apps instance sends a notification to its Azure Notification Hub, specifying the handle of the device to be targeted.
  3. The Azure Notification Hub sends the notification to the appropriate PNS for the device.
  4. The PNS sends the notification to the specified device.
  5. The Xamarin.Forms application processes the notification and displays it.

The sample application demonstrates a todo list application whose data is stored in an Azure Mobile Apps instance. Every time a new item is added to the Azure Mobile Apps instance, a push notification is sent to the Xamarin.Forms application. The following screenshots show each platform displaying the received push notification:

For more information about Azure Notification Hubs, see Azure Notification Hubs and Add push notifications to your Xamarin.Forms app on the Azure Documentation Center.

Azure and Platform Notification System Setup

The process for integrating an Azure Notification Hub into an Azure Mobile Apps instance is as follows:

  1. Create an Azure Mobile Apps instance. For more information, see Consuming an Azure Mobile App.
  2. Create a notification hub. For more information, see Create a Notification Hub on the Azure Documentation Center.
  3. Update the Azure Mobile Apps instance to send push notifications. For more information, see Update the server project to send push notifications on the Azure Documentation Center.
  4. Register with each PNS.
  5. Configure the notification hub to communicate with each PNS.

The following sections provide additional setup instructions for each platform.

iOS

The following additional steps must be carried out to use Apple Push Notification Service (APNS) from an Azure Notification Hub:

  1. Generate a certificate signing request for the push certificate with the Keychain Access tool. For more information, see Generate the Certificate Signing Request file for the push certificate on the Azure Documentation Center.
  2. Register the Xamarin.Forms application for push notification support on the Apple Developer Center. For more information, see Register your app for push notifications on the Azure Documentation Center.
  3. Create a push notifications enabled provisioning profile for the Xamarin.Forms application on the Apple Developer Center. For more information, see Create a provisioning profile for the app on the Azure Documentation Center.
  4. Configure the notification hub to communicate with APNS. For more information, see Configure the notification hub for APNS.
  5. Configure the Xamarin.Forms application to use the new App ID and provisioning profile. For more information, see Configuring the iOS project in Xamarin Studio or Configuring the iOS project in Visual Studio on the Azure Documentation Center.

Android

The following additional steps must be carried out to use Firebase Cloud Messaging (FCM) from an Azure Notification Hub:

  1. Register for FCM. For more information, see Enable Google Cloud Messaging on the Azure Documentation Center.
  2. Configure the notification hub to communicate with FCM. For more information, see Configure the Mobile App backend to send push requests using GCM on the Azure Documentation Center.

Universal Windows Platform

The following additional steps must be carried out to use the Windows Notification Service (WNS) from an Azure Notification Hub:

  1. Register for the Windows Notification Service (WNS). For more information, see Register your Windows app for push notifications with WNS on the Azure Documentation Center.
  2. Configure the notification hub to communicate with WNS. For more information, see Configure the notification hub for WNS on the Azure Documentation Center.

Adding Push Notification Support to the Xamarin.Forms Application

The following sections discuss the implementation required in each platform-specific project to support push notifications.

iOS

The process for implementing push notification support in an iOS application is as follows:

  1. Register with the Apple Push Notification Service (APNS) in the AppDelegate.FinishedLaunching method. For more information, see Registering with the Apple Push Notification System.
  2. Implement the AppDelegate.RegisteredForRemoteNotifications method to handle the registration response. For more information, see Handling the Registration Response.
  3. Implement the AppDelegate.DidReceiveRemoteNotification method to process incoming push notifications. For more information, see Processing Incoming Push Notifications.

Registering with the Apple Push Notification Service

Before an iOS application can receive push notifications, it must register with the Apple Push Notification Service (APNS), which will generate a unique device token and return it to the application. Registration is invoked in the FinishedLaunching override in the AppDelegate class:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    ...
    var settings = UIUserNotificationSettings.GetSettingsForTypes(
        UIUserNotificationType.Alert, new NSSet());

    UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
    UIApplication.SharedApplication.RegisterForRemoteNotifications();
    ...
}

When an iOS application registers with APNS it must specify the types of push notifications it would like to receive. The RegisterUserNotificationSettings method registers the types of notifications the application can receive, with the RegisterForRemoteNotifications method registering to receive push notifications from APNS.

Failing to call the RegisterUserNotificationSettings method will result in push notifications being silently received by the application.

Handling the Registration Response

The APNS registration request occurs in the background. When the response is received, iOS will call the RegisteredForRemoteNotifications override in the AppDelegate class:

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    const string templateBodyAPNS = "{\"aps\":{\"alert\":\"$(messageParam)\"}}";

    JObject templates = new JObject();
    templates["genericMessage"] = new JObject
    {
        {"body", templateBodyAPNS}
    };

    // Register for push with the Azure mobile app
    Push push = TodoItemManager.DefaultManager.CurrentClient.GetPush();
    push.RegisterAsync(deviceToken, templates);
}

This method creates a simple notification message template as JSON, and registers the device to receive template notifications from the notification hub.

The FailedToRegisterForRemoteNotifications override should be implemented to handle situations such as no network connection. This is important because users might start the application while offline.

Processing Incoming Push Notifications

The DidReceiveRemoteNotification override in the AppDelegate class is used to process incoming push notifications when the application is running, and is invoked when a notification is received:

public override void DidReceiveRemoteNotification(
    UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
    NSDictionary aps = userInfo.ObjectForKey(new NSString("aps")) as NSDictionary;

    string alert = string.Empty;
    if (aps.ContainsKey(new NSString("alert")))
        alert = (aps[new NSString("alert")] as NSString).ToString();

    // Show alert
    if (!string.IsNullOrEmpty(alert))
    {
        UIAlertView avAlert = new UIAlertView("Notification", alert, null, "OK", null);
        avAlert.Show();
    }
}

The userInfo dictionary contains the aps key, whose value is the alert dictionary with the remaining notification data. This dictionary is retrieved, with the string notification message being displayed in a dialog box.

If an application isn't running when a push notification arrives, the application will be launched but the DidReceiveRemoteNotification method won't process the notification. Instead, get the notification payload and respond appropriately from the WillFinishLaunching or FinishedLaunching overrides.

For more information about APNS, see Push Notifications in iOS.

Android

The process for implementing push notification support in an Android application is as follows:

  1. Add the Google Cloud Messaging Client component to the Android project, and import the Gcm.Client namespace into the MainActivity class.
  2. Register with Firebase Cloud Messaging (FCM) in the MainActivity.OnCreate method. For more information, see Registering with Firebase Cloud Messaging.
  3. Register with the Azure Notification Hub in the GcmServiceBase.OnRegistered method. For more information, see Registering with the Azure Notification Hub.
  4. Implement the GcmService.OnMessage method to process incoming push notifications. For more information, see Displaying the Contents of a Push Notification.
  5. Implement the GcmService.OnUnregistered and GcmService.OnError methods to de-register and process errors from FCM. For more information, see De-registering and Processing Errors.

Registering with Firebase Cloud Messaging

Before an Android application can receive push notifications, it must register with FCM, which will generate a registration token and return it to the application. Registration is invoked in the OnCreate override in the MainActivity class:

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
    public static MainActivity CurrentActivity { get; private set; }

    protected override void OnCreate(Bundle bundle)
    {
        ...
        CurrentActivity = this;
        try
        {
            GcmClient.CheckDevice(this);
            GcmClient.CheckManifest(this);
            GcmClient.Register(this, PushHandlerBroadcastReceiver.SENDER_IDS);
        }
        catch (...)
        {
            ...
        }
    }
    ...
}

After checking that FCM is supported and that the manifest has the correct information, the application registers to receive push notifications from FCM. Note that the CurrentActivity property is used to expose the MainActivity instance, so that the GcmService helper class can perform registration with the notification hub on the UI thread. This helper class is used to handle interactions with FCM – specifically when registration with FCM succeeds, when the application receives a push notification message, and when FCM errors occur.

In order to register with FCM, the PushHandlerBroadcastReceiver class defines a public array, SENDER_IDS, that stores the project number for FCM (obtained from Google Developer Console):

[BroadcastReceiver(Permission = Gcm.Client.Constants.PERMISSION_GCM_INTENTS)]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_MESSAGE }, Categories = new string[] { "@PACKAGE_NAME@" })]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_REGISTRATION_CALLBACK }, Categories = new string[] { "@PACKAGE_NAME@" })]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_LIBRARY_RETRY }, Categories = new string[] { "@PACKAGE_NAME@" })]
public class PushHandlerBroadcastReceiver : GcmBroadcastReceiverBase<GcmService>
{
    public static string[] SENDER_IDS = new string[] { "<INSERT_YOUR_SENDER_ID_HERE>" };
}

The SENDER_IDS array value is used by the GcmService helper class in a call to its base class constructor:

[Service]
public class GcmService : GcmServiceBase
{
    public static string RegistrationToken { get; private set; }

    public GcmService() : base(PushHandlerBroadcastReceiver.SENDER_IDS) { }
    ...
}

The Google Cloud Messaging Client component then uses the value of the SENDER_IDS property stored in the base class to register with FCM.

Note that the GcmService class should also contain the following permission requests above the namespace declaration:

[assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]
[assembly: UsesPermission(Name = "android.permission.INTERNET")]
[assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]
//GET_ACCOUNTS is only needed for android versions 4.0.3 and below
[assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]

Registering with the Azure Notification Hub

The GcmService class implements the GcmServiceBase.OnRegistered method, which is invoked when an application successfully registers for push notifications with FCM:

[Service]
public class GcmService : GcmServiceBase
{
    ...
    protected override void OnRegistered(Context context, string registrationToken)
    {
        Log.Verbose("PushHandlerBroadcastReceiver", "GCM Registered: " + registrationToken);
        RegistrationToken = registrationToken;

        var push = TodoItemManager.DefaultManager.CurrentClient.GetPush();
        MainActivity.CurrentActivity.RunOnUiThread(() => Register(push, null));
    }

    public async void Register(Microsoft.WindowsAzure.MobileServices.Push push, IEnumerable<string> tags)
    {
        try
        {
            const string templateBodyGCM = "{\"data\":{\"message\":\"$(messageParam)\"}}";

            JObject templates = new JObject();
            templates["genericMessage"] = new JObject
            {
                {"body", templateBodyGCM}
            };

            await push.RegisterAsync(RegistrationToken, templates);
            Log.Info("Push Installation Id", push.InstallationId.ToString());
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message);
            Debugger.Break();
        }
    }
    ...
}

This method stores the returned registration token before invoking the Register method on the UI thread. The Register method creates a simple notification message template as JSON, and registers the device to receive template notifications from the notification hub.

Displaying the Contents of a Push Notification

The GcmService class implements the GcmServiceBase.OnMessage method, which is invoked when FCM sends a push notification to the application:

[Service]
public class GcmService : GcmServiceBase
{
    ...
    protected override void OnMessage(Context context, Intent intent)
    {
        Log.Info("PushHandlerBroadcastReceiver", "GCM Message Received!");

        var msg = new StringBuilder();
        if (intent != null && intent.Extras != null)
        {
            foreach (var key in intent.Extras.KeySet())
                msg.AppendLine(key + "=" + intent.Extras.Get(key).ToString());
        }

        // Retrieve the message
        var prefs = GetSharedPreferences(context.PackageName, FileCreationMode.Private);
        var edit = prefs.Edit();
        edit.PutString("last_msg", msg.ToString());
        edit.Commit();

        string message = intent.Extras.GetString("message");
        if (!string.IsNullOrEmpty(message))
        {
            CreateNotification("New todo item!", "Todo item: " + message);
        }
    }

    void CreateNotification(string title, string desc)
    {
        ...
    }
}

This method retrieves the message from the notification, and sends it to the notification manager for display by the CreateNotification method.

De-registering and Processing Errors

The GcmService class implements the GcmServiceBase.OnUnregistered and GcmServiceBase.OnError methods, which are invoked when the application unregisters from FCM, or when an errors occurs, respectively:

[Service]
public class GcmService : GcmServiceBase
{
    ...
    protected override void OnUnRegistered(Context context, string registrationToken)
    {
        Log.Error("PushHandlerBroadcastReceiver", "Unregistered RegisterationToken: " + registrationId);
    }

    protected override void OnError(Context context, string errorId)
    {
        Log.Error("PushHandlerBroadcastReceiver", "GCM Error: " + errorId);
    }
    ...
}

Both methods log error messages to the Android logs.

For more information about FCM, see Google Cloud Messaging.

Universal Windows Platform

Before a Universal Windows Platform (UWP) application can receive push notifications it must register with the Windows Notification Service (WNS), which will return a notification channel. Registration is invoked by the InitNotificationsAsync method in the App class:

private async Task InitNotificationsAsync()
{
    var channel = await PushNotificationChannelManager
          .CreatePushNotificationChannelForApplicationAsync();

    const string templateBodyWNS =
        "<toast><visual><binding template=\"ToastText01\"><text id=\"1\">$(messageParam)</text></binding></visual></toast>";

    JObject headers = new JObject();
    headers["X-WNS-Type"] = "wns/toast";

    JObject templates = new JObject();
    templates["genericMessage"] = new JObject
    {
        {"body", templateBodyWNS},
        {"headers", headers} // Needed for WNS.
    };

    await TodoItemManager.DefaultManager.CurrentClient.GetPush()
          .RegisterAsync(channel.Uri, templates);
}

This method gets the push notification channel, creates a notification message template as JSON, and registers the device to receive template notifications from the notification hub.

The InitNotificationsAsync method is invoked from the OnLaunched override in the App class:

protected override async void OnLaunched(LaunchActivatedEventArgs e)
{
    ...
    await InitNotificationsAsync();
}

This ensures that the push notification registration is created or refreshed every time the application is launched, therefore ensuring that the WNS push channel is always active.

When a push notification is received it will automatically be displayed as a toast – a modeless window containing the message.

Summary

This article demonstrated how to use Azure Notification Hubs to send push notifications from an Azure Mobile Apps instance to a Xamarin.Forms application. Azure Notification Hubs provide a scalable push infrastructure for sending mobile push notifications from any backend to any mobile platform, while eliminating the complexity of a backend having to communicate with different platform notification systems.

Xamarin Workbook

If it's not already installed, install the Xamarin Workbooks app first. The workbook file should download automatically, but if it doesn't, just click to start the workbook download manually.