Windows Phone 7 - London Tube Companion Application


As part of my continual learning of Windows Phone 7, I decided to develop an application which displays the status of tube lines for the London Underground. As well as displaying the line status, the application also allows users to request push notifications when the status of a tube line changes.
Windows Phone 7 architecture allows for several types of push notifications, all of which are delivered by the cloud based Push Notification service. The notification types are as follows:
  • Raw Notification : Raw Data is sent to the application. Only available when the application is open.
  • Tile Notification: If the application is pinned to the phone’s start screen, then the application’s tile can be modified.
  • Toast Application: Text based notification is displayed to the currently active screen. This does not require the application to be open.
In this example I decided to use toast notifications to inform the user of any changes to the tube line status, as it would allow the user to be informed no matter which application they were using on the phone.

The article here details the push notification architecture. In my example the Windows Phone application is the Tube Companion windows phone application, and the cloud application is a service which periodically polls for changes in tube status, and then sends out notifications to the relevant subscribers.

Setting up the phone application to receive toast notifications
In order for the phone to receive toast notifications, the phone application must carry out the following:
  • Create a channel to the Push Notification service. Although the phone application itself does not create the notifications, it is the phone’s responsibility to create the notification channel between itself and the push notification service. Once the channel has been created and opened, a unique Uri for the application and device instance is created, and this can passed to any external cloud based service. It is then the responsibility of the cloud based service to post messages to the Uri, which results in the notification being sent to the device.
  • Register to receive the relevant channel events. The ChannelUriUpdated event is fired when the channel has been opened. Once this occurs the application and device specific Uri is available. The ShellNotificationReceived event is fired once a toast notification is received and the application is running. This would allow you to apply additional application logic when the application has context. If the application is not running then this event would not fire and a standard toast notification would be received in the normal manner.
  • Open the channel.
  • Bind to the relevant notification type. In order to receive toast notifications from the Push Notification service we have to explicitly request to receive toast notifications, otherwise only raw notification types would be sent to the application.
  • Subscribe to notifications. The Channel Uri is sent from the phone application to my cloud service, and stored in it’s notification subscription database. The cloud service then uses this Uri in order to send notifications back to the device.
 try
{
_httpChannel = new HttpNotificationChannel(CHANNEL_NAME, "TubeCompanionService");
_httpChannel.ChannelUriUpdated += new EventHandler(_httpChannel_ChannelUriUpdated);
_httpChannel.Open();

.....
}

void _httpChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{

System.Diagnostics.Debug.WriteLine("Received application uri: " + e.ChannelUri.ToString());
_httpChannel.HttpNotificationReceived += new EventHandler(_httpChannel_HttpNotificationReceived);
_httpChannel.ShellEntryPointNotificationReceived += new EventHandler(_httpChannel_ShellEntryPointNotificationReceived);
_httpChannel.ShellNotificationReceived += new EventHandler(_httpChannel_ShellNotificationReceived);
_httpChannel.ExceptionOccurred += new EventHandler(_httpChannel_ExceptionOccurred);
_httpChannel.BindToShellEntryPoint();
_httpChannel.BindToShellNotification();

_tubeCompanionWS.SubscribeToNotifications(e.ChannelUri.ToString());

}

Setting up the service to send toast notifications
In order for the service to send toast notifications, the following needs to occur:
  • The toast notification XML message is created. The XML message must conform to the schema documented here, and essentially details the notification message to be displayed.
  • A HttpWebRequest object is created, and is passed the phone/device instance Uri as it’s constructor.
  • The toast notification XML is converted to a byte array and passed as the content of the HttpWebRequest .
  • Request headers are set. Documented here
  • The HttpWebRequest is posted. This results in the notification being sent to the application on the device.
public class PushNotification
    {
const string MESSAGE_ID = "X-MessageID";
const string NOTIFICATION_CLASS = "X-NotificationClass";
const string NOTIFICATION_STATUS = "X-NotificationStatus";
const string SUBSCRIPTION_STATUS = "X-SubscriptionStatus";
const string DEVICE_CONNECTION_STATUS = "X-DeviceConnectionStatus";
const string WINDOWSPHONE_TARGET_HEADER = "X-WindowsPhone-Target";
public void SendToastNotification(Uri channelUri, string message)
{
ToastNotificationMessage toastMessage = new ToastNotificationMessage();

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(channelUri);
request.Method = "POST";
request.ContentType = "text/xml";
request.Headers = new WebHeaderCollection();
request.Headers.Add(MESSAGE_ID,Guid.NewGuid().ToString());
request.Headers.Add(NOTIFICATION_CLASS, "2");
//request.Headers[WINDOWSPHONE_TARGET_HEADER] = "toast";
byte[] toastMessageBytes = toastMessage.CreateToastMessage(message);
request.ContentLength = toastMessageBytes.Length;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(toastMessageBytes, 0, toastMessageBytes.Length);
}

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string notificationStatus = response.Headers[NOTIFICATION_STATUS];
string subscriptionStatus = response.Headers[SUBSCRIPTION_STATUS];
string deviceConnectionStatus = response.Headers[DEVICE_CONNECTION_STATUS];
}
}

public class ToastNotificationMessage
{
public byte[] CreateToastMessage(string message)
{
string prefix = "Content-Type: text/xml\r\nX-WindowsPhone-Target: toast\r\n\r\n";
StringBuilder builder = new StringBuilder();
builder.Append("");
builder.Append("");
builder.Append("");
builder.Append("");
builder.Append(message);
builder.Append("
");
builder.Append("
");
builder.Append("
");
ASCIIEncoding encoding = new ASCIIEncoding();
string messageXML = builder.ToString();
messageXML = prefix + messageXML;
return encoding.GetBytes(messageXML);

}
}

Windows Phone 7 CTP April Refresh
This application was built with the Windows Phone 7 CTP April refresh, and it is worth stating that there is currently an issue with this version of the emulator whereby the notification channel cannot be opened until the emulator has been running for around two minutes. Therefore a delay has to be introduced prior to creating and opening this channel.

Additionally changes to the WMAppManifest.xml also have to be made and these are documented here

Comments

  1. Hi Andy,

    Thanks for giving us this good article. Can you provide the full source code for this cause it seems really useful?

    ReplyDelete
  2. Will it be possible for you to share the source code for the service you implemented?

    ReplyDelete
  3. Thanks for the great informative article Andy. Any chance you could share the source code for the London Line Status please? As I'm trying to implement the same thing for my app.

    I would be very grateful.

    Kind regards

    ReplyDelete
  4. Your blog post for Windows Phone 7 - London Tube Companion Application is impressive and I think you also provide the source code for this.
    Tube Companion for Windows Phone 7 sets out to try and at least ease the pain a little of being squashed into a carriage with hundreds of other people, by letting you find out the live situation of the underground - and plan an alternate route - on the go.
    For more information please visit here whatsapp push notification windows phone

    ReplyDelete

Post a Comment

Popular posts from this blog

Windows Phone 7 - Jogging Application Part 2

Windows Phone 7 - Selecting device photos without PhotoChooserTask