Thursday, July 28, 2011

Push notifications in Windows Phone 7.5 (Mango) -part 1

With push notifications, you can have your website or service send messages to an app running on a bunch of phone devices registered to receive the messages. These messages may trigger a toast popup on the phone, update a specific tile, or simply pass some raw data  to the phone app.

Push notifications work by creating a dedicated, one-on-one communication channel between the phone app and the Microsoft Push Notification Service (MPNS). Then, when your service or web app wants to send a notification to the phone, it sends it to the MPNS through a pre-determined URI, and MPNS will forward it to the phone as soon as it can.


In Mango, push notifications have gained in robustness. They are now more reliable, efficient, and performant. An example of reliability improvement is the revamped so-called TDET detection mechanism, which is the timeout period on a mobile network after which the data connection to your device is dropped for network efficiency. There is a wide range of mobile network configurations in this regard, which used to cause problems for push notifications delivery – push notification require a persistent channel to exist between MPNS and the device. Mango brings broader network compability in this respect.

As a result of the deep improvements, you now have up to 30 MPNS channels on a single device, vs. 5 previously (I think that was the number). In any case, each app can still have only one MPNS channel.
Here’s the basic process to implement push notifications in your app :

- Create a web app or service to let devices register and to send out notifications to them
- In the phone app, create an MPNS channel and then register the phone with web app
- In the phone app, bind to the channel to receive toast, tile and/or raw notifications
- In the web app, implement the operation to create and send notifications to the devices
- From an external client, call the web app’s send method, passing notification data to it

Let's look at each of these steps.

Create the web app or service
In your solution, create a new WCF application. In your service definition interface you can define 2 methods, one that phones will call to register with the service, and the other to send notifications to registered devices. For example  :
public interface IMyPushService
void RegisterPhone(int driverId, string channelUri);
void PushToSubscribedPhones(NotificationData data);

Note that RegisterPhones takes a unique Id for the device and the URI that the channel URI that the device obtained from MPNS, as we’ll see. Its implementation can be as simple as storing the device’s channel Uri in a static dictionary :

static Dictionary<int, Uri> subscribedPhones = new Dictionary<int, Uri>();
public void RegisterPhone(int driverId, string channelUri)
subscribedPhones[driverId] = new Uri(channelUri, UriKind.Absolute);

PushToSubscribedPhones accepts a custom object that will contain the data we need to include in our notification messages. So NotificationData can be any class that exposes properties we need to send that data back and forth. Of course it needs to be decorated with the [DataContract] attribute.

public class NotificationData
[DataMember] public string PushType;
[DataMember] public string Title;
[DataMember] public int Count;
[DataMember] public string TileUri;
[DataMember] public string BackTitle { get; set; }
[DataMember] public string BackContent { get; set; }
... }

We’ll come back to PushToSubscribedPhones in a moment.

Register the phone app with MPNS

When your phone application starts it needs to establish a communication channel with MPNS. It looks for an existing one from a previous execution (channels are persisted on the phone), and if none is found, it creates one  :

channel = HttpNotificationChannel.Find(channelName);
if (channel == null)
channel = new HttpNotificationChannel(channelName);

You hook up a handler for the ChannelUriUpdated event, and in the handler you can retrieve the channelUri asynchronously returned by MPNS and then register with the custom service through the RegisterPhone operation :

channel.ChannelUriUpdated += OnChannelUriUpdated;
void OnChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
pushClient.RegisterPhoneAsync(App.MyDriverId, e.ChannelUri.ToString());

Once you’ve hooked up the handler, you can call the Open() method on Channel if the channel is new, which will asynchronously request a channel Uri.

Bind to the channel to receive toast and/or tile notifications

If you want your phone app to receive toast and/or tile notifications, in the above handler you also need to call the BindToShellXXX methods accordingly :

if (!channel.IsShellTileBound)
if (!channel.IsShellToastBound)

Note that the channel you create will only be persisted on the device across app instances if you bind to it for toast or tile. If you don’t, it will be destroyed and you’ll need to create a new channel the next time you run the app.

In addition to the ChannelUriUpdated event, you may want to handle the ShellToastNotificationReceived event if you want your app to receive toasts even when the app is running – in which case toasts normally get discarded. You can also handle HttpNotificationReceived if you want your app to receive and handle raw notifications, which are pieces of custom data send through MPNS.

So at this point, we have our web service sketched out and our phone app registered with both MPNS and our service. The next step is to implement the PushToSubscribedPhones() operation in the service. I’m running out of time so I’ll do that in Part2.

Stay tuned !

Part 2 is now live

No comments:

Post a Comment