Silverlight for Windows Phone 7: Push Notifications (Part 2 of 2)
In previous post I described how to build server part of push notification mechanism for Windows Phone 7. This time I’ll show how to handle push notifications on the phone.
To demonstrate it I created pretty simple Silverlight application for Windows Phone. The UI of this application looks like the follows:
Lets see how the push mechanism is implemented. Phone API defines a class, which responsible for push notifications: HttoNotificationChannel. This class is responsible for subscribing to events and receiving those messages once they arrives.
Phone registers to such channel with channel name (and optionally service name). Once channel is opened, phone will get the event. In addition, channel could be “retrieved” by name – this helps to maintain minimum required number of opened channels from the phone to MPNS.
Best practice is to try find the existing channel first, and only if it is not found then open new channel.
The major difference between opened channel and not opened is ChannelUri property – this property initialized only when channel opened (or found and retrieved). My phone application will try to find existing channel, and if not will open a new one. After channel opened or found it will register the channel (ChannelUri) with my cloud service. This Uri will be used by service to send a notifications to the phone. In addition it will subscribe to various channel events – some of them to respond on arrived messages, some of them to handle possible communication errors. Lets see “DoConnect” function which executed in sample’s constructor:
//First, try to pick up existing channel
httpChannel = HttpNotificationChannel.Find(channelName);
if (null != httpChannel)
Dispatcher.BeginInvoke(() => UpdateStatus("Channel recovered"));
//Create the channel
httpChannel = new HttpNotificationChannel(channelName, "HOLWeatherService");
//Register to UriUpdated event - occurs when channel successfully opens
Dispatcher.BeginInvoke(() => UpdateStatus("Channel open requested"));
Exactly according to best practice first it tries to find a channel and if not found opens a new one. If channel found, then the variable will be initialized and ChannelUri returned from MPNS. Same will happen after successful Open command.
SubscribeToService function (executed also from httpChannel_ChannelUriUpdated handler) calls the WCF Registration service (described in first part):
private void SubscribeToService()
RegistrationSVC.RegistrationServiceClient client = new RegistrationSVC.RegistrationServiceClient();
client.RegisterCompleted += (s, e) =>
if (null == e.Error)
Dispatcher.BeginInvoke(() => UpdateStatus("Registration succeeded"));
Dispatcher.BeginInvoke(() => UpdateStatus("Registration failed: " + e.Error.Message));
And subscribing to channel events do the following:
private void SubscribeToChannelEvents()
//Subscribe to the channel events
When notification received (in my case I have to take care for real only for RAW notifications), event handler function will parse received payload and initialize UI fields with received data:
private void ParseRAWPayload(Stream e, out string weather, out string location, out string temperature)
using (var reader = new StreamReader(e))
string payload = reader.ReadToEnd().Replace('\0', ' ');
document = XDocument.Parse(payload);
location = (from c in document.Descendants("WeatherUpdate")
Trace("Got location: " + location);
temperature = (from c in document.Descendants("WeatherUpdate")
Trace("Got temperature: " + temperature);
weather = (from c in document.Descendants("WeatherUpdate")
Once all the data parsed I could update the UI:
void httpChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
string weather, location, temperature;
ParseRAWPayload(e.Notification.Body, out weather, out location, out temperature);
Dispatcher.BeginInvoke(() => this.PageTitle.Text = location);
Dispatcher.BeginInvoke(() => this.txtTemperature.Text = temperature);
Dispatcher.BeginInvoke(() => this.imgWeatherConditions.Source =
new BitmapImage(new Uri(@"Images/" + weather + ".png", UriKind.Relative)));
This way my UI updated with data sent from Cloud Service Client (Silverlight) application.
In order to receive Toast & Tile events, I have to bind the channel to Toast notifications:
and also bind it to Tile notifications:
Collection<Uri> uris = new Collection<Uri>();
Now my application complete :)
Instructions to run: the whole project could be executed from single machine – just change service references in phone & Silverlight client projects. But – this is IMHO not so interesting :) Compile phone part only and deploy XAP file to emulator (pr real device if you already lucky to have it) using XAP Deployment utility installed with Windows Phone Developer Tools (WPDT):
Navigate to the list of phone applications and long click on “Weather Sample [DevCorner]” icon. Select “Pin to start”:
Now start the application from start tile
and navigate to Silverlight client hosted on my site here. Send notification to emulator running on YOUR machine from my site and see it arrives:
Click “Windows” button and send Toast & Tile alerts:
Stay tuned for more posts about new features of Windows Phone 7!