MOBILE

Windows Phone 7 Development : Push Notifications - Implementing Toast Notifications

5/17/2011 3:40:07 PM
For the toast notifications walkthrough, you will implement a Windows Phone 7 client application that will create a notification channel, and a Windows Forms application that can send the notifications to the Windows Phone 7 application via that channel. The Windows Phone 7 client application will be a single screen application with one button and one text box, as shown in Figure 17-4. The Windows Forms application will consist of the single form shown in Figure 17-5. You will follow this order of program implementation:
  1. You will create the Windows Phone 7 Notification client application. This application will establish a notification channel and print the URI of that communication channel into the Output window.

  2. Create and execute the Windows Forms application that will send notifications. You will take the URI of the notification channel that you established in Step 1, paste it into the "Push Notifications URL" field of this application, and submit the notification.

  3. Verify that you are able to receive toast notifications in the Windows Phone 7 application.

1. Creating a Client Application

The Windows Phone 7 Notification client application will consist of a command button that will create a push notification channel and print its URI into the Debug window. You will also add a text box to the application to display the URI for visual confirmation. Follow these steps to create the application.

  1. Launch Visual Studio 2010 Express for Windows Phone and create a new Windows Phone Application project. Name it "PNClient."

  2. From the Toolbox, drag and drop a text box on the design surface. Rename the text box to txtURI, adjust its width to be the full width of the screen, and adjust its height to be about a quarter of the screen's height. Set the text box's TextWrapping property to "Wrap" and clear out its Text property.

  3. From the Toolbox, drag and drop a button on the design surface. Rename the button to btnCreateChannel and set the Content property to "Create Channel." Your Windows Phone 7 design surface should now look like Figure 1.

  4. Add the following using directives to the top of the MainPage.xaml.cs file.

    using Microsoft.Phone.Notification;
    using System.Diagnostics;

  5. You need to add code that will capture the URI of the notification channel in the Output window. At the top of the code page, right underneath the

    public partial class MainPage : PhoneApplicationPage
    {

    add the following code:

    Uri channelUri;
    public Uri ChannelUri
    {
    get { return channelUri; }

    set
    {
    channelUri = value;
    OnChannelUriChanged(value);
    }
    }

    private void OnChannelUriChanged(Uri value)
    {
    Dispatcher.BeginInvoke(() =>
    {
    txtURI.Text = "changing uri to " + value.ToString();
    });

    Debug.WriteLine("changing uri to " + value.ToString());
    }


The last bit of code above will print the URI of the push notification channel opened by the application into the Visual Studio Output window, which will allow you to copy and paste that URI into the Windows Forms application that you will be building in the next section. Certainly, in the real-world application, this copy and paste method is not appropriate; a more robust method of exchanging that URI, such as passing it to a web service, would be more appropriate.

  1. Open MainPage.xaml in Design view (right-click MainPage.xaml in Solution Explorer and select View Designer), double-click the "Create Channel" button, and make the btnCreateChannel_Click event handler look like the following:

    private void btnCreateChannel_Click(object sender, RoutedEventArgs e)
    {
    SetupChannel();
    }

  2. Paste the following SetupChannel function into the btnCreate_Click event handler . Here, you use the HttpNotificationChannel class to try to find an existing push notification channel or open a new channel with a given channel name.

    Figure 1. Windows Phone 7 application that will create a push notification URI and receive push notifications
    private void SetupChannel()
    {
    HttpNotificationChannel httpChannel = null;
    string channelName = "DemoChannel";

    try
    {
    //if channel exists, retrieve existing channel
    httpChannel = HttpNotificationChannel.Find(channelName);
    if (httpChannel != null)
    {
    //If we cannot get Channel URI, then close the channel and reopen it
    if (httpChannel.ChannelUri == null)
    {
    httpChannel.UnbindToShellToast();
    httpChannel.Close();
    SetupChannel();
    return;
    }
    else


    {
    ChannelUri = httpChannel.ChannelUri;
    }
    BindToShell(httpChannel);
    }
    else
    {
    httpChannel = new HttpNotificationChannel(channelName);
    httpChannel.ChannelUriUpdated += new
    EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated);

    httpChannel.ShellToastNotificationReceived+=new
    EventHandler<NotificationEventArgs>(httpChannel_ShellToastNotificationReceived);

    httpChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(httpChannel_ExceptionOccurred);

    httpChannel.Open();
    BindToShell(httpChannel);
    }
    }
    catch (Exception ex)
    {
    Debug.WriteLine("An exception setting up channel " + ex.ToString());
    }
    }


The code in the SetupChannel() function warrants an explanation, since there is quite a bit going on there and this is the nucleus of creating a channel for a Windows Phone 7 Notification client application. In the first few lines, you define a new object of type HttpNotificationChannel, give it a name, and wire up an event to fire when an error occurs. You'll also wire up an event to fire when the URI of the notification channel changes. Next, you'll try to find the channel with a given name for the application and then bind it to receive toast notifications (via the BindToShell function shown here). If the channel is found, you'll use an existing channel to obtain the push notification URI and you will not need to wire various httpChannel event handlers. If the channel is not found, you'll create a new one and wire up appropriate httpChannel events. Notice the ShellToastNotificationReceived event—it occurs if your application is running in the foreground when it receives a toast notification. Normally, push notifications are designed to alert that there is something happening when the application is not running and when application tile needs to be updated. However, occasionally, your application may be running when a toast notification is received—to handle cases like that, ShellToastNotificationReceived event handler is introduced.

  1. To handle toast notifications when the application is running in the foreground, add the code below for the ShellToastNotificationReceived event handler. This code will read the notification messages received and print them in the textbox on the screen.

    void httpChannel_ShellToastNotificationReceived(object sender,
    NotificationEventArgs e)
    {
    Dispatcher.BeginInvoke(() =>
    {
    txtURI.Text = "Toast Notification Message Received: ";


    if (e.Collection != null)
    {
    Dictionary<string, string> collection =
    (Dictionary<string, string>)e.Collection;
    System.Text.StringBuilder messageBuilder = new System.Text.StringBuilder();
    foreach (string elementName in collection.Keys)
    {
    txtURI.Text+= string.Format("Key: {0}, Value:
    {1}\r\n", elementName, collection[elementName]);
    }
    }
    });
    }


  2. To bind a toast notification subscription to a given HttpNotificationChannel instance, you must call the BindToShellToast method of the HttpNotificationChannel class. Underneath the SetupChannel function, paste the following code to accomplish that:

    private static void BindToShell(HttpNotificationChannel httpChannel)
    {
    //This is a toast notification
    try
    {
    httpChannel.BindToShellToast();
    }
    catch (Exception)
    {
    Debug.WriteLine("An exception occurred binding to shell " + ex.ToString());
    }
    }


  3. In the SetupChannel function, you designated the httpChannel_ExceptionOccurred should fire in case of an error. Add this function to your code as defined here:

    void httpChannel_ExceptionOccurred(object sender, NotificationChannelErrorEventArgs
    e)
    {
    //Display Message on error
    Debug.WriteLine ( e.Message);
    }


  4. You also need to add code that will fire if the ChannelUri gets updated:

    void httpChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
    {
    //You get the new Uri (or maybe it's updated)
    ChannelUri = e.ChannelUri;
    }



Figure 2. Design surface for Windows Phone 7 Notification client application

At this point, you have finished building the Windows Phone 7 client application and are ready to implement the Windows Forms application for sending notification messages to the mobile device.

2. Creating an Application to Send Notifications

In the previous section, you wrote a Windows Phone 7 client application that creates a notification channel to the MPN Service to indicate that it wishes to receive push notification messages. By creating a channel, the application has also created an MPNS endpoint to which the web-based application can send POST requests. The endpoint exists on an MPNS server operated by Microsoft and will forward any requests it receives to the appropriate mobile device and application to which the endpoint points.

You can create POST requests from virtually any application environment, including web sites, web services, and desktop applications, making this type of notification architecture very flexible and easy to use. In this example, you will create a Windows Forms application that packages POST requests to the URI generated in the previous section. This application will create POST requests and send them off to the MPNS in the cloud, which will in turn properly route the requests to the mobile devices and applications.

To ensure proper message routing and successful delivery, there are two key pieces of information that any application sending push notifications to a Windows Phone 7 device must supply. Those key pieces of information are the following:

  1. The URI of the notification channel that the service must use to communicate with a Windows Phone 7 device. It is up to the Windows Phone 7 client application to request the URI and pass it to the service that will use it.

  2. A proper XML message to POST to the URI. While the format of the XML message is simple, it has to be followed precisely for the notifications to succeed. To make things slightly more confusing, Microsoft changes schema in its early product releases in an effort to make it more uniform; those changes could break existing functionality and make documentation not relevant.

The latest MPNS XML template for toast notifications looks like the following, where <Notification Title> and <Notification Text> are the text of the notification title and the text of the toast notification message to be sent to a Windows Phone 7 device:

<?xml version="1.0" encoding="utf-8"?>
<wp:Notification xmlns:wp="WPNotification">
<wp:Toast>
<wp:Text1><Notification Title></wp:Text1>
<wp:Text2><Notification Text></wp:Text2>
</wp:Toast>
</wp:Notification>

Figure 3. Windows Forms application that will send push notifications to WP7 app

Now that you know the XML template format of the expected POST request and, using cut and paste, can quickly obtain the URI of the notification channel, as you'll see shortly, you're ready to create an application to dispatch notifications to the Windows Phone 7 client app. Follow these steps to accomplish that:

  1. Launch Visual C# 2010 Express (or another edition of Visual Studio that will allow you to create Windows Forms projects) and create a new Windows Forms project. Name it "PNServer."

  2. Form1.cs is added by default. Double-click it to bring up the design view. From the toolbox, drag three labels and three text boxes and make Form1.cs look like Figure 17-5. Name the text boxes txtURL, txtTitle, and txtText accordingly.

  3. Add a Button control onto Form1. Change its text property to "Send Notification" and change its name to "btnSendNotification."

  4. Finally, add the label control to the bottom of the form and change its name to "lblStatus."

  5. Right-click Form1.cs in Solution Explorer and choose View Code (alternately, you can also press F7). Add the following using statements to the top:

    using System.Net;
    using System.IO;

  6. After the constructor, add the following definition of the XML to be POSTed to MPNS:

    string ToastPushXML = "<?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>";

  7. Switch back to the design view on Form1.cs (by right-clicking Form1.cs in Solution Explorer and choosing View Designer). Double-click the "Send Notification" button to bring up the btnSendNotification_Click event handler.

You'll use the btnSendNotification_Click event handler, with the help of the .NET HttpWebRequest class, to create a POST request, to the push notification URI that the Windows Phone 7 client has obtained. The beauty of communication with MPNS is that once this POST request is composed and sent off, MPNS will take care of the delivery of the notification from there. The critical piece of information is the URI to send the POST request to, since that URI is what uniquely identifies both a Windows Phone 7 device and an application to send push notifications to.

Make the btnSendNotification_Click event handler look like the code here:

private void btnSendNotification_Click(object sender, EventArgs e)
{
if (txtURL.Text == string.Empty)
{
MessageBox.Show("Please enter a url");
return;
}

if (txtTitle.Text == string.Empty || txtText.Text == string.Empty)
{
MessageBox.Show("Please enter text and title to send");
return;
}

string url = txtURL.Text;

HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(url);



sendNotificationRequest.Method = "POST";
sendNotificationRequest.Headers = new WebHeaderCollection();
sendNotificationRequest.ContentType = "text/xml";

sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "toast");
sendNotificationRequest.Headers.Add("X-NotificationClass", "2");

string str = string.Format(ToastPushXML, txtTitle.Text, txtText.Text);
byte[] strBytes = new UTF8Encoding().GetBytes(str);
sendNotificationRequest.ContentLength = strBytes.Length;
using (Stream requestStream = sendNotificationRequest.GetRequestStream())
{
requestStream.Write(strBytes, 0, strBytes.Length);
}

HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();
string notificationStatus = response.Headers["X-NotificationStatus"];
string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];
lblStatus.Text = "Status: " + notificationStatus + " : " + deviceConnectionStatus;
}


The POST request includes two headers:

  • The X-WindowsPhone-Target header defines the notification type. The possible values for this header are "toast," "token," or not defined. "Toast" defines the notification of toast type, while "token" defines a tile notification. If this header is not defined, then it is a raw notification.

  • The X-NotificationClass header defines how soon the MPNS should deliver the notification. The value of "2" specifies that the toast notification is to be delivered immediately. Had you specified the value of "12," for example, the MPNS would have been instructed to wait 450 seconds, or seven and a half minutes before notification delivery.

Now it's time to test the application and its service.

2.1. Verifying Delivery of Push Notifications

With the Windows Phone 7 Notification client application ready to receive notification messages and the Windows Forms application ready to send them, you are ready to verify the proper delivery of those notifications. Follow these steps to test push notification delivery:

  1. First, you will need to obtain the URI of the notification channel. Open the PNClient project created in the "Creating a Client Application" section. Make sure that you have a connection to the Internet, and press F5 to run the project.

  2. Click the Create Channel button and, after a short while, you should see messages (the URI of the notification channel, actually) printed in the text box on the screen—that's a confirmation that the notification URI is available to copy from the Output window.

  3. In Visual Studio 2010 Express for Windows Phone, click the Debug => Windows => Output menu option to bring up the Output window. The URI should be printed together with the "changing uri to ..." message, as shown in Figure 4. Highlight the URI and press Ctrl/C to copy it into the buffer. Make sure to leave the application running in the Windows Phone emulator, since you will be receiving push notifications on this emulator screen.

  4. Switch to the PNServer Windows Forms project and press F5 to run it. In the Push Notifications URL text box, paste the URI obtained in Step 1 by pressing Ctrl/V. In the Push Notifications Title and Push Notifications Text text boxes, you can enter any text—for example, "Time to buy!" and "MSFT up $2 after WP7 release." Press the Send Notification button.

Remember that push notifications appear on the phone only when the Windows Phone 7 application associated with these notifications is not running in the foreground on the phone. Therefore, if the PNClient application was running—which is likely—in the foreground when you pressed the Send Notification button, no notifications will have appeared on the phone screen. To enable them, do the following, otherwise skip to the next paragraph:

  1. Press the Windows button on the emulator (that's the middle button on the emulator with the Windows logo on it) to switch to the Start screen of the phone, which shuts down PNClient application. In the PNServer app, press the Send Notification button again.

As you can see, creating and receiving push notifications is a somewhat involved process, with a separate Windows Phone 7 application establishing a notification channel and receiving notifications, and a separate application sending, or "pushing" these notifications to that Windows Phone 7 app. Once you understand how to work with other types of notifications—namely, tile and raw—you will learn how to build a service that will programmatically acquire and keep track of the connected clients. From an application development point of view, the good news is that the process of creating other notification types—tile notifications and raw notifications—is very similar to the process of creating toast notifications that we have described previously. In the next section, you will take a look at how to create tile notifications; but instead of creating everything from scratch, you will concentrate only on the changes needed to the toast notifications already implemented.

Figure 4. Notification channel URI printed in the Output window
Other  
  •  iPhone Application Development : Creating a Navigation-Based Application
  •  Windows Phone 7 Development : Push Notifications - Introducing the Push Notifications Architecture
  •  Windows Phone 7 Development : Push Notifications - Understanding Push Notifications
  •  Windows Phone 7 Development : Handling Multiple Concurrent Requests with Rx.NET
  •  WAP and Mobile HTML Security : Application Attacks on Mobile HTML Sites
  •  WAP and Mobile HTML Security : Authentication on WAP/Mobile HTML Sites & Encryption
  •  iPhone Application Development : Displaying and Navigating Data Using Table Views - Building a Simple Table View Application
  •  iPhone Application Development : Understanding Table Views and Navigation Controllers
  •  Windows Phone 7 Development : Revising WeatherRx to Manage Slow Data Connections
  •  Windows Phone 7 Development : Handling Data Connection Issues with Rx.NET
  •  Windows Phone 7 Development : Handling Errors in Rx.NET
  •  Windows Phone 7 Development : Using Rx.NET with Web Services to Asynchronously Retrieve Weather Data
  •  Windows Phone 7 Development : Media - Adding Sounds to an Application
  •  iPhone Application Development : Building a Multi-View Tab Bar Application (part 4) - Implementing the Summary View
  •  iPhone Application Development : Building a Multi-View Tab Bar Application (part 3) - Implementing the Volume View
  •  iPhone Application Development : Building a Multi-View Tab Bar Application (part 2) - Implementing the Area View
  •  iPhone Application Development : Building a Multi-View Tab Bar Application (part 1)
  •  Windows Phone 7 Development : Working with Video (part 2) - Coding the Application
  •  Windows Phone 7 Development : Working with Video (part 1)
  •  Windows Phone 7 Development : Plotting an Address on a Bing Maps Map and Working with the Bing Maps Service
  •  
    Top 10
    Why Apple Wins? (Part 2)
    Samsung Series 5 Ultra
    Arcsoft Perfect365
    Exchange Server 2007: Recover a Non-Mailbox Role
    The Reality Of Gaming Laptops (Part 1)
    Create virtual desktop with nSpaces (Part 2)
    Exchange Server 2007: Administrate Transport Settings - Implement Email Address Policies
    Coming Soon – Willow Bends The Rules
    Managing Exchange Server 2010 : Archiving and compliancy (part 1) - Exchange 2010 Archiving
    Enabling ActiveSync in Exchange Server 2010
    Most View
    FUJIFILM X-S1
    The choices of mobile computing for SOHO users (part 1)
    SharePoint 2010 : Business Intelligence - Excel Services (part 2) - Accessing Excel Services Over SOAP
    Canon PIXMA MX895
    Backing Up the Exchange Server 2010 Environment : Roles and Responsibilities & Developing a Backup Strategy
    SharePoint 2010 : SQL Backup Tools
    IIS 7.0 : Implementing Access Control - Authentication (part 3) - IIS Client Certificate Mapping Authentication
    Windows 7: Getting into Your Multimedia (part 1) - Configuring Windows Media Player for the First Use
    How Much Is Your Data Worth? (Part 1)
    Mobile Viruses the risk keeps growing (Part 1)
    Surviving Changes to the Signature of a Stored Procedure
    Manage Server Core
    Legal Trouble with Social Networks (Part 1)
    Windows Server 2008 : Create Virtual Hard Drives and Machines
    Corel Painter X : Working with Layers - The Chair
    Send an Email via SMTP
    Searching for Google’s future (Part 1) - Taking the tablets
    Programming with DirectX : Shading and Surfaces - Implementing Texture Mapping (part 1) - 2D Texture Mapping Demo
    Is It Time To Tweet? (Part 2)
    Hosting a Multi-Tenant Application on Windows Azure : Single-Tenant vs. Multi-Tenant & Multi-Tenancy Architecture in Azure