Toast notifications with Windows Phone 7.5 and Azure

Toast notifications are one kind of push notifications. They are sent by a web service and can be received by a phone even when it doesn’t have your application open. They work like SMS and Facebook messaging on Windows Phone, showing a box with an icon, a title and some text on the top of the screen when received.

Toast notification received in the home screen

In this tutorial I will describe how you can create a WCF service that sends these messages and an companion app on Windows Phone 7 that receives them.

Part 1: Creating the toast notification WCF service

Prerequisities:

  • knowledge on publish a WCF service to Azure websites
  • a website running on Azure
  • a storage service running on Azure

Recommended reading:

1. Open Visual Studio (I’m using 2010) and create a new WCF Service Library project (WCF -> WCF Service Library)

2. Remove IService1.cs and Service1.cs by right clicking them in Solution Explorer and choosing Delete.

3. Right click your project in Solution Explorer and choose Add -> New Item. Scroll through the list to find WCF Service, name the item ToastService.svc and click Add.

4. In similar way, add add a new Class to the project (Add -> New Item -> Class) and name it ToastSubscription.cs.

5. Add Windows Azure Storage references to the project by opening the Package Manager Console and running the command

PM> Install-Package WindowsAzure.Storage

6. Open ToastSubscription.cs and insert the following code:

 using System;
  using Microsoft.WindowsAzure.StorageClient;
  namespace ToastExample
  {
  
 public
 sealed
 class
 ToastSubscription : TableServiceEntity
   {
  
 // The class must have a constructor with zero parametres
  
 public ToastSubscription() { }
  
 // Having the same partition key for all subscriptions is faster
  
 private
 const
 string _subscriptionsPartition = "subscriptions";
 // Every device has a channel through which it can receive our notifications
 private
 string _devicePushChannel = string.Empty;
 public
 string DevicePushChannel
   {
  
 get { return _devicePushChannel; }
  
 set { _devicePushChannel = value; }
   }
  
 public ToastSubscription(string devicePushChannel)
   {
  
 this.PartitionKey = _subscriptionsPartition;
  
 this.RowKey = Guid.NewGuid().ToString();
  
 // We can't use devicePushChannel as the row key because it contains backslashes
  
 this.DevicePushChannel = devicePushChannel;
   }
   }
  }
 

7. Open IToastService.cs and change the code to following:

using System.ServiceModel;
  namespace ToastExample
  {
   [ServiceContract]
  
 public
 interface
 IToastService
   {
   [OperationContract]
  
 bool SubscribeToToasts(string devicePushChannel);
   [OperationContract]
  
 bool SendToastMessage(string toastTitle, string toastText);
   }
  }
 

8. Open ToastService.cs and change the code to following:

using System;
 
using System.Collections.Generic;
 
using System.IO;
 
using System.Linq;
 
using System.Net;
 
using System.Text;
 
using Microsoft.WindowsAzure;
 
using Microsoft.WindowsAzure.StorageClient;
 
namespace ToastExample
 
{
 

 public
 class
 ToastService : IToastService
 
 {
 

 private
 const
 string ConnectionString =
 

 "DefaultEndpointsProtocol=https;AccountName=YOUR ACCOUNT NAME;" +
 

 "AccountKey=YOUR PRIMARY ACCESS KEY";
 

 private
 const
 string SubscriptionTableName = "subscriptions";
 

 public
 bool SubscribeToToasts(string devicePushChannel)
 
 {
 

 // Connect to Azure
 

 var storageAccount = CloudStorageAccount.Parse(ConnectionString);
 

 CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
 
 tableClient.CreateTableIfNotExist(SubscriptionTableName);
 

 var serviceContext = tableClient.GetDataServiceContext();
 

 // Find entities that have the same push channel
 

 ToastSubscription previousSubscription =
 
 (from e in serviceContext.CreateQuery<ToastSubscription>(SubscriptionTableName)
 

 where e.DevicePushChannel == devicePushChannel
 

 select e).FirstOrDefault();
 

 // only add a new item if there was no previous one found (when the user is not subscribed)
 

 if (previousSubscription == null)
 
 {
 

 ToastSubscription newSubscription = new
 ToastSubscription(devicePushChannel);
 
 serviceContext.AddObject(SubscriptionTableName, newSubscription);
 
 serviceContext.SaveChangesWithRetries();
 
 }
 

 return
 true;
 
 }
 

 private
 List<ToastSubscription> GetSubscriptions()
 
 {
 

 // Connect to Azure
 

 var storageAccount = CloudStorageAccount.Parse(ConnectionString);
 

 CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
 
 tableClient.CreateTableIfNotExist(SubscriptionTableName);
 

 var serviceContext = tableClient.GetDataServiceContext();
 

 // Return all toast subscriptions in the table
 

 var toastQuery = serviceContext.CreateQuery<ToastSubscription>(SubscriptionTableName);
 

 return toastQuery.ToList();
 
 }
 

 public
 bool SendToastMessage(string toastTitle, string toastText)
 
 {
 

 // Based on http://mobile.dzone.com/articles/notification-subscription
 

 // Toast messages are always formatted in this xml format
 

 string toastString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
 

 "<wp:Notification xmlns:wp=\"WPNotification\">" +
 

 "<wp:Toast>" +
 

 "<wp:Text1>{0}</wp:Text1>" +
 

 "<wp:Text2>{1}</wp:Text2>" +
 

 "</wp:Toast>" +
 

 "</wp:Notification>";
 
 toastString = string.Format(toastString, toastTitle, toastText);
 

 byte[] messageBytes = Encoding.UTF8.GetBytes(toastString);
 

 // List all subscribers and send the message to all of them
 

 var subscriptionList = GetSubscriptions();
 

 foreach (ToastSubscription subscription in subscriptionList)
 
 {
 

 Uri channelUri = new
 Uri(subscription.DevicePushChannel);
 

 //Add headers to HTTP Post message.
 

 var myRequest = (HttpWebRequest)WebRequest.Create(channelUri); // The device's channelURI
 
 myRequest.Method = WebRequestMethods.Http.Post;
 
 myRequest.ContentType = "text/xml";
 
 myRequest.ContentLength = messageBytes.Length;
 
 myRequest.Headers.Add("X-MessageID", Guid.NewGuid().ToString()); // gives this message a unique ID
 
 myRequest.Headers["X-WindowsPhone-Target"] = "toast";
 

 // 2 = immediatly push toast
 

 // 12 = wait 450 seconds before push toast
 

 // 22 = wait 900 seconds before push toast
 
 myRequest.Headers.Add("X-NotificationClass", "2");
 

 //Merge headers with payload.
 

 using (Stream requestStream = myRequest.GetRequestStream())
 
 {
 
 requestStream.Write(messageBytes, 0, messageBytes.Length);
 
 }
 

 //Send notification to the device
 

 try
 
 {
 

 var response = (HttpWebResponse)myRequest.GetResponse();
 
 }
 

 catch (WebException ex)
 
 {
 

 //Log or handle exception
 
 }
 
 }
 

 return
 true;
 
 }
 
 }
 
}
 

9. Your WCF service is ready to go! Publish it in Azure, check the links in the beginning of the post for help if needed.

Part 2: Utilizing the toast notifications on a Windows Phone 7.5 app

Prerequisities:

  • You need to know how to add basic elements to a Windows Phone Application page

1. Create an empty Windows Phone 7 application.

2. Add service reference to the WCF service you just created by right clicking the project and choosing Add -> Add Service Reference and pasting the url of your service in the address field. Change the namespace to ToastService and click OK.

3. Add two text boxes and a button to Mainpage.xaml. These will be used to enter a title and some text for the toast notification and to send it.

4. Open Mainpage.cs and change the code to following:

 
using System;
 
using System.Windows;
 
using Microsoft.Phone.Controls;
 
using Microsoft.Phone.Notification;
 
using ToastAppDemo.ToastService;
 
namespace ToastAppDemo
 
{
 

 public
 partial
 class
 MainPage : PhoneApplicationPage
 
 {
 

 ToastServiceClient toastClient;
 

 private
 HttpNotificationChannel _devicePushChannel;
 

 // Constructor
 

 public MainPage()
 
 {
 
 InitializeComponent();
 
 toastClient = new
 ToastServiceClient();
 
 SubscribeToNotifications();
 
 }
 

 private
 void SubscribeToNotifications()
 
 {
 
 _devicePushChannel = HttpNotificationChannel.Find("DevicePushChannel");
 

 if (_devicePushChannel == null)
 
 {
 
 _devicePushChannel = new
 HttpNotificationChannel("DevicePushChannel");
 
 _devicePushChannel.Open();
 
 }
 
 _devicePushChannel.ShellToastNotificationReceived += ToastReceived;
 

 // Wait until the channel is open
 
 _devicePushChannel.ChannelUriUpdated += new
 EventHandler<NotificationChannelUriEventArgs>(devicePushChannel_ChannelUriUpdated);
 
 }
 

 void devicePushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
 
 {
 
 toastClient.SubscribeToToastsAsync(e.ChannelUri.ToString());
 

 // Allows the application to react to toast notifications
 
 _devicePushChannel.BindToShellToast();
 
 }
 

 private
 void ToastReceived(object sender, NotificationEventArgs e)
 
 {
 

 // If the toast is received when the application is in foreground, show it in a message box
 
 Dispatcher.BeginInvoke(() => {
 

 MessageBox.Show(e.Collection["wp:Text2"], e.Collection["wp:Text1"], MessageBoxButton.OK);
 
 });
 
 }
 

 private
 void button1_Click(object sender, RoutedEventArgs e)
 
 {
 
 toastClient.SendToastMessageAsync(textBox1.Text, textBox2.Text);
 
 }
 
 }
 
}
 

5. Run the application and enjoy your toast notifications! To get the most out of the experience, deploy the application to a Windows Phone device and run it in the emulator simultaneously. The messages sent from either one will be received by both.

About the author

Alex KivikoskiAlex Kivikoski (Twitter)
Alex is an IT student from Turku University of Applied Sciences with a great passion for good looking design in web and
mobile software. He has four applications in Windows Phone marketplace and the number is going to grow soon. On his free time he plays flute, bass and other instruments and runs his own business.

Advertisements

About arcticmsp

The Finnish Microsoft Student Partners are a group of enthusiastic students, who are interested in technology and all things new, techy and cool!
This entry was posted in Uncategorized. Bookmark the permalink.

2 Responses to Toast notifications with Windows Phone 7.5 and Azure

  1. Pingback: Toast notifications with Windows Phone and Azure | azkafaiz.com

  2. Pingback: Toast notifications with Windows Phone 7.5 and Azure

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s