Chapter 8: Introduction to Windows Phone 7 Notifications for iPhone Developers

Date: Tuesday, April 26, 2011, 12:00:00 AM

Tags: Porting

Table of Contents

What Are Push Notifications?

Push notifications are used to inform the user of the occurrence of external events or updates to user's application data.. Consider the following scenario. You are interested in knowing when the price of a particular stock reaches a threshold. Both iPhone and Windows Phone 7 allow only one application to be active in the foreground at any time. You want to know about it even if the application which shows stock prices is not currently running in the foreground. Push notifications allow you to react to events that are of interest to any application, not just the one in the foreground. .

On Windows Phone 7, notifications play a very important and prominent role. The application notifications make the Windows Phone 7 tiles come alive. The notification mechanisms are used to display the most up-to-date status of the application that reflects the events of interest to the user. The tiles work with the notifications to bring information to the user. The user does not have to open the application to the see the updated status.

Notifications on Windows Phone 7

There are three types of notifications on Windows Phone 7, namely, tile notifications, toast notifications and raw notifications. They serve three distinct purposes.

Tile notification. Tile notification is used to show the up-to-date status of the application on the application tile on the start screen of the phone. This is used only if the application is pinned to the start page and is meant to provide information at a glance. There are three types of information included in a tile notification, namely, a picture - for the tile background, a count - for example, think about the count of email messages and a title that conveys a message.

clip_image002

Toast notification

A toast notification is a message that pops up on the screen for 10 seconds. It is meant to provide time sensitive information. It is system wide, but does not disrupt user operation or require user action. If the user taps the notification, the application that sent the notification is launched. The user may dismiss the toast with a flick.

clip_image003

The toast notification shows a small the application icon on the left with two text items, a title and a subtitle.

Raw notification

Unlike toast notifications, raw notifications are in-application notifications that require action. They can be generated by the application itself or sent from a web service. Web service raw notifications only appear within the specified application; there is no system-wide way to display a raw notification. They affect only that application, if the application is not currently running, the raw notification is discarded.

iPhone and Windows Notifications Compared

iPhone provides three types of notifications, namely, sound, badge, and message notifications. Badge notifications are used to display a number on the application tile. Message notification is used to display a popup message that user needs to acknowledge. Here is how the notification mechanisms compare on the two platforms.

Purpose

iPhone

Windows Phone 7

Information at a glance

iPhone notification using badge and sound

Live Tile notifications that show a count, a title and a picture

Time sensitive information that the user may ignore

N/A

Toast notification with a message

Time sensitive information that the user must acknowledge

iPhone notification using message and sound

Raw notifications when application is running

;

As compared to the iPhone badge which is used to show an updated count (an application relevant piece of information), WP7 has the additional ability to portray richer information in its tile notifications. With the title message and the updated picture, WP7 notifications make the WP7 tiles come alive.

The Architecture of Windows Phone 7 Push Notifications

At a high level push notifications have a similar architecture on iPhone and Windows Phone 7. There are three parts to the push notification system on both platforms.

1. The phone based application. A user subscribes to events or notifications of interest, either explicitly or implicitly.

2. The web service that sends the notification. The web service monitors external events of interest and checks the application status. It sends a notification to the notification service that relays it to the device.

3. The Apple or Microsoft Push Notification service that pushes the notification to the phone.

The following picture shows the architecture of the Windows Phone 7 Push notifications service.

clip_image005

The phone application with the WP7 OS, the application web service, and the Microsoft Push Notification Service work together to bring the notification to the user.

1. The application uses WP7 to register its notification endpoint with the Microsoft Push Notification Service (MPNS). A new URI is established for the endpoint and returned to the OS which forwards it to the application. Compare this to iPhone where the application creates a unique device ID by registering with the APNS.

2. The application sends the URI and a unique device ID to its notification application web service. This is typically accompanied by the notification subscription request. For example, if the application wants to be notified of changes to a flight schedule, it will send information such as the flight number, along with the notification URI and a unique device ID to the remote application web service. This is similar to what happens on iPhone where the application sends the device token along with the notification subscription.

3. When an event that the user has subscribed to takes place, the web application sends the notification to the MPNS which in turn sends the notification to the device. In response, depending upon the type of the notification, an action takes place. For iPhone, the notification request is sent to APNS which in turn sends it to the device.

The following table shows the correspondence between parts of the iPhone and Windows Phone 7 notification mechanisms.

Purpose

iPhone

Windows Phone 7

Application registration

Device token

Unique Device ID + URI

Subscription notification

Remote application web service

Remote application web service

Notification service

Apple Push Notification Service

Microsoft Push Notification Service

;

Benefits of using WP7 Push Notifications

There are number of benefits of using WP7 push notifications WP7 uses heartbeat to reduce the number of connections. Additionally, it batches the notifications, which helps reduce the radio usage to conserve the battery.

Using WP7 Notifications within the Application

Let us look at what it takes to implement push notifications in a WP7 application.

Registering for the notifications

On Windows Phone 7, registering for the notification requires two pieces of information, namely, a unique ID and a URI. This tuple is the counterpart of the device token on iPhone. The URI is used by the MPNS to address the device uniquely. The application push web service sends the notification message that includes the URI to the MPNS, which then forwards it to the device.

Compare this with the registration for notification on iPhone. To receive the notification, you need to download a provisioning profile configured for notification. Once provisioned, the application uses registerForNotificationType using one or more notification types.

Generating a unique ID

The device generates its own unique ID using a GUID and saves it in the isolated storage for subsequent runs of the application. The application should subsequently send the same device ID since the notification service uses it to index the subscription information as well as the notification endpoint.

//if you have previously created a unique id, use it, otherwise create a new one
if (IsolatedStorageSettings.ApplicationSettings.Contains("DeviceId")){
    //retrieve the unique id saved in the isolated storage
    _deviceId = (Guid)IsolatedStorageSettings.ApplicationSettings["DeviceId"];
}else{
    //create a new guid and save it in the isolated storage
    _deviceId = Guid.NewGuid();
    IsolatedStorageSettings.ApplicationSettings["DeviceId"] = _deviceId;
}

// Sset up a notification channel and subscribe to notifications
SetupNotificationChannel();

Obtaining the notification URI

The device registers with MPNS to obtain a URI that MPNS will subsequently use to address the device uniquely. The URI is contained in the HttpNotificationChannel (simply called Channel) object. If the Channel with a specific name does not exist, the application creates a new Channel. If the service updates the notification URI, application receives the updated URI via the ChannelUriUpdated event handler.

string ChannelName = "MyUniqueChannelName";

private void SetupNotificationChannel(){
    //Find the channel with the given name
    _channel = HttpNotificationChannel.Find(ChannelName);

    if (_channel == null){
        //Channel does not exist. Create one
        _channel = new HttpNotificationChannel(ChannelName);
    
        //hookup the event handler to receive updated channel object with the new notification URI
        _channel.ChannelUriUpdated += ChannelUriUpdated;
        _channel.ErrorOccurred += (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => ErrorOccurred(e));

        //Channel URI will be sent in the event handler after Open is called
        _channel.Open();
    } else {
        //found an existing channel, now hook up notificaton handlers
        HookupNotificationHandlers(); 
    
        //communicate with the app web service for subscribing to notifications
        SubscribeToNotifications();
    }
}

Handling Notifications

Whenever the notification URI is updated, the ChannelUriUpdated event handler is called. Once the application receives the updated URI, it binds the channel to the toast and tile notifications if they are not bound already. These binding are used when the application is not running. WP7 will handle these notifications in the standard manner as described above. The iPhone too provides a standard manner in which notifications are handled when the application is not running. This behavior is configured automatically on the iPhone.

private void ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e) {
    //retrieve the Channel again as the URI is updated
    _channel = HttpNotificationChannel.Find(ChannelName);

    //bind the channel with Toast and Tile 
    if (!_channel.IsShellToastBound) {
        _channel.BindToShellToast();
    }

    if (!_channel.IsShellTileBound) 
        _channel.BindToShellTile();
    }

    //Setup the notification event handlers
    HookupNotificationHandlers(); 

    //Send the device id and the URI to the app notification web service. 

    //web service should update the URI if it is already stored in the web service

    SubscribeToNotifications();
}

The following method shows how the toast and raw notifications are handled when the application is running. When these notifications are received, the ToastReceived and HttpNotificationReceived methods are invoked. ToastReceived is used for toast notifications whereas HttpNotificationReceived is used for raw notifications. A tile notification has a standard behavior and a running application is not notified. Compare that with iPhone where the application receives didReceiveRemoteNotification call back if the application is running when the notification arrives. The application can then handle the notifications the way it wants.

Since these notifications are not received on the UI thread, we use BeginInvoke to handle them on the UI thread. In this example, these notifications are displayed on the page but you may choose to use them in other ways.

private void HookupNotificationHandlers() {
    _channel.ShellToastNotificationReceived += (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => ToastReceived(e));
    _channel.HttpNotificationReceived += (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => HttpNotificationReceived(e));
    _channel.ErrorOccurred += (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => ErrorOccurred(e));
}

private void HttpNotificationReceived(HttpNotificationEventArgs e) {
    var reader = new StreamReader(e.Notification.Body);
    var message = reader.ReadToEnd();

    notifications.Items.Add("Raw notification message : " + message);

    reader.Close();
}

private void ToastReceived(NotificationEventArgs e)    {
    notifications.Items.Add("Toast notification message : " + e.Collection["wp:Text1"]);
}

Subscribing to Notifications

Once the application has the updated URI, it can use it to subscribe to notifications with its remote application web service. In our sample application, we will print the channel URI to the console and use it from our message sender application. You should send both the device ID and the URI along with additional parameters needed to subscribe to application specific notifications.

private void SubscribeToNotifications() {
    Debug.WriteLine("Use this channel URI to send notification:" + _channel.ChannelUri.ToString());
}
Sending notifications

In our sample example, we demonstrate how to send the notification using a simple WPF application. It takes the URI and other parameters needed for each type of notification and performs HTTP post to MPNS.

As opposed to the JSON format used in iPhone, WP7 notification uses XML format for the tile and toast messages. In this example, the first three methods format the message appropriately and call the SendMessage method. The structure of the three methods is very similar. Messages are sent to the device using HTTP POST to the application URI received in the subscription request. In this example, we ignore the status of the notification POST but ideally, you should handle the response appropriately.

public void SendToastNotification(string message) {
    string toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                          "<wp:Notification xmlns:wp=\"WPNotification\">" +
                          "<wp:Toast>" +
                          "<wp:Text1>{0}</wp:Text1>" +
                          "</wp:Toast>" +
                          "</wp:Notification>";

    string formattedToastMessage = string.Format(toastMessage, message);

    byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(formattedToastMessage);

    SendMessage(uri, messageBytes, NotificationType.Toast);
}

public void SendRawNotification(string message) {
    byte[] messageBytes = Encoding.UTF8.GetBytes(message);

    SendMessage(uri, messageBytes, NotificationType.Raw);
}

public void SendTileUpdate(string title, int count, string imageUrl) {
    string tileMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                         "<wp:Notification xmlns:wp=\"WPNotification\">" +
                         "<wp:Tile>" +
                         "<wp:BackgroundImage>{0}</wp:BackgroundImage>" +
                         "<wp:Count>{1}</wp:Count>" +
                         "<wp:Title>{2}</wp:Title>" +
                         "</wp:Tile> " +
                         "</wp:Notification>";

    string formattedTileMessage = string.Format(tileMessage, imageUrl, count, title);

    byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(formattedTileMessage);

    SendMessage(uri, messageBytes, NotificationType.Tile);
}

private void SendMessage(Uri uri, byte[] messageBytes, NotificationType notificationType) {
    var request = (HttpWebRequest)WebRequest.Create(uri);

    request.Method = WebRequestMethods.Http.Post;
    request.ContentType = "text/xml";
    request.ContentLength = messageBytes.Length;
    request.Headers.Add("X-MessageID", Guid.NewGuid().ToString());

    switch (notificationType) {
        case NotificationType.Toast:
            request.Headers["X-WindowsPhone-Target"] = "toast";
            request.Headers.Add("X-NotificationClass", ((int)BatchingInterval.ToastImmediately).ToString());
            break;
        case NotificationType.Tile:
            request.Headers["X-WindowsPhone-Target"] = "token";
            request.Headers.Add("X-NotificationClass", ((int)BatchingInterval.TileImmediately).ToString());
            break;
        case NotificationType.Raw:
            request.Headers.Add("X-NotificationClass", ((int)BatchingInterval.RawImmediately).ToString());
            break;
    }

    using (var requestStream = request.GetRequestStream()){
        requestStream.Write(messageBytes, 0, messageBytes.Length);
    }
}

Sending notifications from the application web service

In a real WP7 application, you will send both the device ID and the Channel URI to the application web service. The web service should store the Channel URIs indexed by the device ID. While the channel URI may change, the device ID remains the same. The web service should update the channel URI every time it receives the device ID and channel URI from the device.

Throttling

MPNS allows both unauthenticated and authenticated notifications. However, unauthenticated push requests are throttled if they exceed 500 messages per day. There are no such restrictions on authenticated requests which uses client SSL for authentication.

Comparing iPhone and WP7 Notifications

While the two services are similar, there are subtle differences between iPhone and WP7 notification mechanisms. Developers can take advantage of the MPNS mechanism to improve the user experience.

On Windows Phone 7, tile notification can use remote image files which can be used to show fresh status on WP7 tiles. Similarly on WP7, there is no limit on the size of the notification messages and developers can use them creatively. There is no guarantee of delivery of messages on either service. Notifications may not be delivered MPNS provides a status of the delivery which developers can use to resend the notification.

Functionality

iPhone

Windows Phone7

Notification Service

Apple Push Notification Service

Microsoft Notification Service

Payload format

JSON

XML

Payload resource

Local sound files

Local or remote image files. Size of remote file can be upto 80kb

Payload length

256 bytes

No limit on the size of payload

Delivery guarantee

No guarantee

No guarantee

Delivery class

Delivered ASAP

Delivered immediately or within 450 or 900 seconds

Delivery status

No status of delivery

Able to get the status of delivery.

Connection Trust

TLS between application web service and APNS

No SSL for < 500 notifications or SSL otherwise for connection between app web service and MPNS

;

Summary

The push notification mechanism plays a very critical role in Windows Phone 7. It makes tiles come alive and provides up-to-date information at a glance. Windows Phone 7 provides a compelling notification mechanism that is easy to use. Developers can start using notifications immediately even without setting up client authentication. While the architecture of the services on iPhone and WP7 is similar, developers can take advantage of the additional features WP7 notification mechanism provides.

Resources

1. Push Notifications for Windows Phone: MSDN reference on Windows Phone push notification.

2. Windows Phone 7 in 7: Push Notifications

 
blog comments powered by Disqus