Windows Azure Mobile Services - Implementing Push Notifications using

Exclusive offer: get 50% off this eBook here
Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8

Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8 — Save 50%

A short, fast and focused guide to enhance your Windows 8 applications by leveraging the power of Windows Azure Mobile Services with this book and ebook

$17.99    $9.00
by Geoff Webber-Cross | January 2014 | Enterprise Articles

In this article by Geoff Webber-Cross, author of the book Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8, we will have a look at how push Notifications allow us to expand our application's user experience outside the bounds of the app with live tile updates, toast notifications, and badges in Windows 8. Windows Azure Mobile Services makes it very easy for us to trigger notifications via Windows Notifications Service (WNS) (for Store apps), Microsoft Push Notification Service (MPNS) (for Windows Phone 8 apps), Apple Notifications Service (ANS), and Google Notifications Service (GCM). We're going to discuss how to configure Windows 8 and Windows Phone applications to allow notifications, send different types of notifications using scripts, and create a list of devices to manage our user's notification channels.

(for more resources related to this topic, see here.)

Understanding Push Notification Service flow

The following procedure illustrates Push Notification Service (PNS) flow from establishing a channel to receiving a notification:

  1. The mobile device establishes a channel with the PNS and retrieves its handle (URI).
  2. The device registers its handle with a backend service (in our case, a table in our Mobile Service).
  3. A notification request can be made by another service, an admin system, and so on, which calls the backend service (in our case, an API).
  4. The service makes a request to the correct PNS for every device handle.
  5. The PNS notifies the device.

Setting up Windows Store apps

Visual Studio 2013 has a new wizard, which associates the app with the store in order to obtain a push notifications URI. Code is added to the app to interact with the service that will be updated to have a Channels table. This table has an Insert script to insert the channel and ping back a toast notification upon insert. The following procedure takes us through using the wizard to add a push channel to our app:

  1. Right-click on the project, and then navigate to Add | Push Notification.
  2. Follow the wizard and sign in to your store account (if you haven't got one, you will need to create one).
  3. Reserve an app name and select it. Then, continue by clicking on Next.
  4. Click on Import Subscriptions... and the Import Windows Azure Subscriptions dialog box will appear.
  5. Click on Download subscription file. Your default browser will be launched and the subscriptions file will be automatically downloaded. If you are logged into the portal, this will happen automatically; otherwise, you'll be prompted to log in.
  6. Once the subscription file is downloaded, browse to the downloaded file in the Import Windows Azure Subscriptions dialog box and click on Import.
  7. Select the subscription you wish to use, click on Next, and then click on Finish in the final dialog box. In the Output window in Visual Studio, you should see something like the following:

    Attempting to install 'WindowsAzure.MobileServices' Successfully installed NuGet Package 'WindowsAzure.MobileServices' Successfully added 'push.register.cs' to the project Added field to the App class successfully Initialization code was added successfully Updated ToastCapable in the app manifest Client Secret and Package SID were updated successfully on the Windows Azure
    Mobile Services portal The 'channels' table and 'insert.js' script file were created successfully Successfully updated application redirect domain Done

We will now see a few things have been done to our project and service:

  • The Package.StoreAssociation.xml file is added to link the project with the app on the store.
  • Package.appxmanifest is updated with the store application identity.
  • Add a push.register.cs class in services\mobile services\[Your Service Name], which creates a push notifications channel and sends the details to our service.
  • The server explorer launches and shows us our service with a newly created table named channels, with an Insert method that inserts or updates (if changed) our channel URI. Then, it sends us a toast notification to test that everything is working.

Run the app and check that the URI is inserted into the table. You will get a toast notification. Once you've done this, remove the sendNotifications(item.channelUri); call and function from the Insert method. You can do this in Visual Studio via the Server Explorer console. I've modified the script further to make sure the item is always updated, so when we send push notifications, we can send them to URIs that have been recently updated so that we are targeting users who are actually using the application (channels actually expire after 30 days too, so it would be a waste of time trying to push to them). The following code details these modifications:

function insert(item, user, request) { var ct = tables.getTable("channels"); ct.where({ installationId: item.installationId }).read({ success: function (results) { if (results.length > 0) { // always update so we get the updated date var existingItem = results[0]; existingItem.channelUri = item.channelUri; ct.update(existingItem, { success: function () { request.respond(200, existingItem); } }); } else { // no matching installation, insert the record request.execute(); } } }) }

I've also modified the UploadChannel method in the app so that it uses a Channel model that has a Platform property. Therefore, we can now work out which PNS provider to use when we have multiple platforms using the service. The UploadChannel method also uses a new InsertChannel method in our DataService method (you can see the full code in the sample app). The following code details these modifications:

public async static void UploadChannel() { var channel = await Windows.Networking.PushNotifications.
PushNotificationChannelManager.
CreatePushNotificationChannelForApplicationAsync(); var token = Windows.System.Profile.HardwareIdentification.
GetPackageSpecificToken(null); string installationId = Windows.Security.Cryptography.
CryptographicBuffer.EncodeToBase64String(token.Id); try { var service = new DataService(); await service.InsertChannel(new Channel() { ChannelUri = channel.Uri, InstallationId = installationId, Platform = "win8" }); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } }

Setting up tiles

To implement wide or large square tiles, we need to create the necessary assets and define them in the Visual Assets tab of the Package.appxmanifest editor. This is shown in the following screenshot:

Setting up badges

Windows Store apps support badge notifications as well as tile and toast. However, this requires a slightly different configuration. To implement badge notifications, we perform the following steps:

  1. Create a 24 x 24 pixel PNG badge that can have opacity, but must use only white color.
  2. Define the badge in the Badge Logo section of the Visual Assets tab of the Package.appxmanifest editor.
  3. Add a Background Tasks declaration in the Declarations tab of the Package.appxmanifest editor, select Push notification, and enter a Start page, as shown in the following screenshot:

  4. Finally, in the Notifications tab of the Package.appxmanifest editor, set Lock screen notifications to Badge. This is shown in the following screenshot:

  5. To see the badge notification working, you also need to add the app to the lock screen badge slots in Lock Screen Applications | Change PC Settings | Lock Screen.

Setting up Windows Phone 8 apps

Visual Studio 2012 Express for Windows Phone doesn't have a fancy wizard like Visual Studio 2013 Express for Windows Store. So, we need to configure the channel and register it with the service manually. The following procedure sets up the notifications in the app by using the table that we created in the preceding Setting up Windows Store apps section:

  1. Edit the WMAppManifest.xml file to enable ID_CAP_IDENTITY_DEVICE, which allows us to get a unique device ID for registering in the Channels table, and ID_CAP_PUSH_NOTIFICATION, which allows push notifications in the app. These options are available in the Capabilities tab, as shown in the following screenshot:

  2. To enable wide tiles, we need to check Support for large Tiles (you can't see the tick unless you hover over it, as there is apparently a theming issue in VS!) and pick the path of the wide tile we want to use (by default, there is one named FlipCycleTileLarge.png under Tiles in the Assets folder). This is shown in the following screenshot:

  3. Next, we need to add some code to get the push channel URI and send it to the service:

    using Microsoft.Phone.Info; using Microsoft.Phone.Notification; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; using TileTapper.DataServices; using TileTapper.Models; namespace TileTapper.Helpers { public class ChannelHelper { // Singleton instance public static readonly ChannelHelper Default = new ChannelHelper(); // Holds the push channel that is created or found private HttpNotificationChannel _pushChannel; // The name of our push channel private readonly string CHANNEL_NAME = "TileTapperPushChannel"; private ChannelHelper() { } public void SetupChannel() { try { // Try to find the push channel this._pushChannel = HttpNotificationChannel.Find(CHANNEL_NAME); // If the channel was not found, then create a new
    // connection to the push service if (this._pushChannel == null ) { this._pushChannel = new HttpNotificationChannel(CHANNEL_NAME); this.AttachEvents(); this._pushChannel.Open(); // Bind channel for Tile events this._pushChannel.BindToShellTile(); // Bind channel for Toast events this._pushChannel.BindToShellToast(); } else this.AttachEvents(); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } } private void AttachEvents() { // Register for all the events before attempting to // open the channel this._pushChannel.ChannelUriUpdated + = async (s, e) => { // Register URI with service await this.Register(); }; this._pushChannel.ErrorOccurred += (s, e) => { System.Diagnostics.Debug.WriteLine(e.ToString()); }; } private async Task Register() { try { var service = new DataService(); await service.InsertChannel(new Channel() { ChannelUri = this._pushChannel.ChannelUri.AbsoluteUri, InstallationId = this.GetDeviceUniqueName(), Platform = "wp8" }); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } } // Note: to get a result requires // ID_CAP_IDENTITY_DEVICE // to be added to the capabilities of the WMAppManifest // this will then warn users in marketplace private byte[] GetDeviceUniqueID() { byte[] result = null; object uniqueId; if (DeviceExtendedProperties.TryGetValue("DeviceUniqueId",
    out uniqueId)) result = (byte[])uniqueId; return result; } private string GetDeviceUniqueName() { byte[] id = this.GetDeviceUniqueID(); string idEnc = Encoding.Unicode.GetString(id, 0, id.Length); string deviceID = HttpUtility.UrlEncode(idEnc); return deviceID; } } }

    This is a singleton class that holds an instance of the HttpNotificationChannel object, so that channel URI changes can be captured and sent up to our service. The two methods at the end of the code snippet, GetDeviceUniqueID and GetDeviceUniqueName, will give a unique device identifier for the channels table.

  4. Now that we have the code to manage the channel, we need to call the SetupChannel method in the App.xaml.cs launching method as shown in the following code snippet:

    private void Application_Launching(object sender, LaunchingEventArgs e) { TileTapper.Helpers.ChannelHelper.Default.SetupChannel(); }

Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8 A short, fast and focused guide to enhance your Windows 8 applications by leveraging the power of Windows Azure Mobile Services with this book and ebook
Published: January 2014
eBook Price: $17.99
Book Price: $29.99
See more
Select your format and quantity:

Service scripts

In the TileTapper game, we send out notifications when a new level is created and when a new high score is submitted. We'll see how to send all the notification types (except raw; by all means do this if you need to in your application, but we're not going to discuss it now).

First, we’ll look at a set of scripts which gets all the URIs from the channels table, which have been updated in the last 30 days so we know they are likely to be active and then sends notifications out to the correct PNS services depending on the platform type.

The sendNotifications function gets the channels from the channels table. Then, it loops through them, calling the addToQueue method that queues PNS task functions for each channel. We don't call the PNS methods in the for loop as they run asynchronously and would try to execute simultaneously, which would lead to many failures as the server can only make a limited number of HTTP requests concurrently. The following code demonstrates this:

// Queue of PNS functions var queue = []; function sendNotifications(levelName) { // Query channels updated in the last 30 days var sql = "SELECT channelUri, platform FROM channels WHERE updated
>= DATEADD(Day, -30, GETDATE())"; mssql.query(sql, { success: function(results) { // Because the PNS functions are asynchronous, we will loop
// through channels // and add a set of functions to a function queue for each
// channel so we can // process requests one at a time to save starving our
// connections and failing for(var i = 0; i < results.length; i++) { addToQueue(results[i], levelName); } // Process first item dequeue(); } }); }

The addToQueue function determines which notification functions are required, based on the platform type; and pushes a task function into the queue so that they can be called one at a time as they complete, as shown in the following code snippet:

// Wrap functions and enqueue function addToQueue(channel, levelName) { if(channel.platform == "win8") { queue.push(function() { sendMultiTileWns(channel.channelUri,
levelName); }); queue.push(function() { sendToastWns(channel.channelUri,
levelName); }); queue.push(function() { sendBadgeWns(channel.channelUri,
levelName); }); } else if(channel.platform == "wp8") { queue.push(function() { sendToastMpns(channel.channelUri,
levelName); }); queue.push(function() { sendTileMpns(channel.channelUri,
levelName); }); } }

The dequeue method simply shifts a task function off the queue and calls it. As each function completes, it calls this function whether it succeeds or fails to empty the queue and process all PNS requests. The working of the dequeue method is shown in the following code snippet:

function dequeue(){ // Dequeue and execute if(queue.length > 0) (queue.shift())(); }

If a notification fails, we delete the channel registration from the table using the following function:

function deleteChannel(uri) { var sql = "DELETE FROM channels WHERE channelUri = '" + uri + "'"; mssql.query(sql); }

WNS scripts for Store apps

WNS supports the following notifications:

  • sendTile
  • sendToast
  • sendBadge
  • sendRaw
  • send

sendTile and sendToast have a template-specific suffix to define the payload type.

WNS doesn't support tile templates with multiple tile sizes. So, we can use the send method to stick multiple tile bindings together and update more than one tile. There's a full reference available at http://msdn.microsoft.com/en-us/library/windowsazure/jj860484.aspx.

Sending toast notifications

The following function sends a toast notification using the sendToastText04 method:

function sendToastWns(uri, name) { // Send wns push for store apps push.wns.sendToastText04(uri, { text1: "TileTapper", text2: "New level available", text3: name }, { success: function(pushResponse) { console.log("Sent push toast WNS:", pushResponse); dequeue(); }, error: function(error) { console.error(error); deleteChannel(uri); dequeue(); } }); }

Sending tile notifications

The following function sends a tile notification using the sendTileSquareText01 method:

function sendTileWns(uri, name) { // Send wns push for store apps push.wns.sendTileSquareText01(uri, { text1: "TileTapper", text2: "New level available", text3: name }, { success: function(pushResponse) { console.log("Sent push toast WNS:", pushResponse); dequeue(); }, error: function(error) { console.error(error); deleteChannel(uri); dequeue(); } }); }

Sending multiple tiles

The following function sends a tile notification using multiple bindings that are defined using the raw XML templates. It gives us the benefit of sending multiple tile templates in one request, rather than sending them individually.

function sendMultiTileWns(uri, name) { // Send wns push for store apps push.wns.send(uri, "<tile>" + "<visual version='2'>" + "<binding template = 'TileSquare150x150Text01'
fallback='TileSquareText01'>" + "<text id='1'>TileTapper</text>" + "<text id='2'>New level available</text>" + "<text id='3'>" + name + "</text>" + "</binding>" + "<binding template = 'TileWide310x150Text01'
fallback='TileWideText01'>" + "<text id='1'>TileTapper</text>" + "<text id='2'>New level available</text>" + "<text id='3'>" + name + "</text>" + "</binding>" + "</visual>" + "</tile>", "wns/tile", { success: function(pushResponse) { console.log("Sent push toast WNS:", pushResponse); dequeue(); }, error: function(error) { console.error(error); deleteChannel(uri); dequeue(); } }); }

Sending badge notifications

The following function sends an alert badge notification using the sendBadge method:

function sendBadgeWns(uri, name) { // Send wns push for store apps push.wns.sendBadge(uri, "alert", { success: function(pushResponse) { console.log("Sent push toast WNS:", pushResponse); dequeue(); }, error: function(error) { console.error(error); deleteChannel(uri); dequeue(); } }); }

MPNS scripts for Windows Phone apps

MPNS supports the following notifications:

  • sendFlipTile
  • sendTile
  • sendToast
  • sendRaw

There's a full reference available at http://msdn.microsoft.com/en-us/library/windowsazure/jj871025.aspx.

Sending toast notifications

The following function sends a toast notification using the sendToast method:

function sendToastMpns(uri, name) { // Send wns push for store apps // We can add a param object to pass params to a certain page:
// param: "NewPage.xaml?item=5" push.mpns.sendToast(uri, { text1: "TileTapper - New level available", text2: name }, { success: function(pushResponse) { console.log("Sent push toast WNS:", pushResponse); dequeue(); }, error: function(error) { console.error(error); deleteChannel(uri); dequeue(); } }); }

Sending tile notifications

The following function sends a tile notification using the sendFlipTile method:

function sendTileMpns(uri, name) { // Send wns push for store apps // We can add a param object to pass params to a certain page:
// param: "NewPage.xaml?item=5" push.mpns.sendFlipTile(uri, { backTitle: "TileTapper - New level available", backContent: name }, { success: function(pushResponse) { console.log("Sent push toast WNS:", pushResponse); dequeue(); }, error: function(error) { console.error(error); deleteChannel(uri); dequeue(); } }); }

Summary

In this article, we've covered setting up our Windows 8 and Windows Phone 8 applications to receive different notification types. We have also worked on the service to send different notifications from the WNS and MPNS notifications service.

Tiles and toast notifications are big subjects as there are a plethora of templates on each platform. So, it's worth having a good look at the documentation to help you choose the right templates.

In this article, we've learned here with the Notifications Hub, which provides us with a different, more scalable mechanism for managing push notifications.

Resources for Article:


Further resources on this subject:


Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8 A short, fast and focused guide to enhance your Windows 8 applications by leveraging the power of Windows Azure Mobile Services with this book and ebook
Published: January 2014
eBook Price: $17.99
Book Price: $29.99
See more
Select your format and quantity:

About the Author :


Geoff Webber-Cross

Geoff Webber-Cross has commercial and personal experience of developing Windows 8 and Windows Phone applications and using Azure for websites, mobile services, web services, and Windows services. He enjoys learning about new technologies and solving difficult software problems.

Books From Packt


Microsoft Azure: Enterprise Application Development
Microsoft Azure: Enterprise Application Development

Microsoft Windows Azure Development Cookbook
Microsoft Windows Azure Development Cookbook

Microsoft SQL Azure Enterprise Application Development
Microsoft SQL Azure Enterprise Application Development

Microsoft Silverlight 5 and Windows Azure Enterprise Integration
Microsoft Silverlight 5 and Windows Azure Enterprise Integration

Windows Azure programming patterns for Start-ups
Windows Azure programming patterns for Start-ups

Windows Phone 8 Application Development Essentials
Windows Phone 8 Application Development Essentials

 Windows Phone 8 Game Development
Windows Phone 8 Game Development

 Learning Windows 8 Game Development
Learning Windows 8 Game Development


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software