Français English

Raw Notifications on Windows Phone 8

Tags: Windows Phone 8, WinRT, WP8

 

Let’s talk about a kind of notification that is not as much known as its siblings Tile or Toast but that can be also very useful : the Raw Notification.

What is it? Well it is the third kind if push notification. The characteristics are :

  • It is not visual, it is just data pushed to your application.
  • There is no fixed format, you can send anything you want. The only limitation is the size of the data : maximum 1kb
  • The application must be running

 

I suppose you are familiar with the Push Notification architecture on Windows Phone. If not, here is a summary :

Let’s start !

Capability

I guess you know the music : first add push capability :

Registering the channel

Now your app has to register a push notification channel. For that, you use the HttpNotificationChannel class :

private void RegisterChannel()
{
    var channel = HttpNotificationChannel.Find(_channelName);

    // if channel exist, we consider it is already all set
    if (channel != null)
        return;

    channel = new HttpNotificationChannel(_channelName);

    channel.ChannelUriUpdated += channel_ChannelUriUpdated;

    channel.ErrorOccurred += channel_ErrorOccurred;

    channel.HttpNotificationReceived += channel_HttpNotificationReceived;

    channel.Open();    
}

So I am checking if a channel is open. If so, I just stop there as I consider it good (Let’s make things simple).

Otherwise I create and open a new channel. I register to different events. ChannelUriUpdate is launched when the channel URI is updated, so you can send the new one to your third party service. ErrorOccured is self-explanatory. And HttpNotificationReceived is the one we’ll check later as it is the one that will be called when a notification is received.

Sending the channel URI to your service

Now that you have the channel URI, you must send it to your service (or a third party one) so it can send the notification.

For exemple, you can have a very easy web service accepting an URI :

    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        void SendPushChannel(Uri channel);
    }

    public class Service1 : IService1
    {
        public void SendPushChannel(Uri channel)
        {
            if (!ChannelList.DefaultList.Contains(channel))
                ChannelList.DefaultList.Add(channel);
        }
    }


   public class Service1 : IService1
    {
        public void SendPushChannel(Uri channel)
        {
            if (!ChannelList.DefaultList.Contains(channel))
                ChannelList.DefaultList.Add(channel);
        }
    }

This is a VERY simple service, just for demonstration purpose. It should be normally more complex, where you can unregister a channel, save the channels to a DB,etc…

Not to mention that the service should use secure transport.

Just add the service reference to your app project and send the channel URI to the service.

Sending a notification

 

As I said, you can send any data in the notification, as long as it is less than 1kb. It can be text, xml,etc…

What I will do is I will send JSON serialisation of a class I created :

 [DataContract]
    public class RawData
    {
        [DataMember]
        public string Label { get; set; }

        [DataMember]
        public int Value { get; set; }
    }

Now the code to send it :

    // uri is the channel URI
    // data is the RawMessage I will send

    string rawMessage;
    // Serializing the data
    var serializer = new DataContractJsonSerializer(typeof(RawData));

    using (var ms = new MemoryStream())
    {
        serializer.WriteObject(ms, data);
        rawMessage = Encoding.Default.GetString(ms.ToArray());
    }

    var sendNotificationRequest = (HttpWebRequest)WebRequest.Create(uri);

    sendNotificationRequest.Method = "POST";

    // Set the notification payload to send.
    var notificationMessage = Encoding.Default.GetBytes(rawMessage);

    // Set the web request content length.
    sendNotificationRequest.ContentLength = notificationMessage.Length;
    sendNotificationRequest.ContentType = "text/xml";
    sendNotificationRequest.Headers.Add("X-NotificationClass", "3");


    using (var requestStream = sendNotificationRequest.GetRequestStream())
    {
        requestStream.Write(notificationMessage, 0, notificationMessage.Length);
    }

    // Send the notification and get the response.
    var response = (HttpWebResponse)sendNotificationRequest.GetResponse();
    string notificationStatus = response.Headers["X-NotificationStatus"];
    string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
    string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];

 

You can check the response codes of the WPNS here.

Receiving the notification

 

Now the client should receive the notification and the HttpNotificationReceived event will be launched. Here is an example code :

        void channel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
        {
            var serializer = new DataContractJsonSerializer(typeof(RawData));

            var RawNotification = (RawData)serializer.ReadObject(e.Notification.Body); 
            // Do something 
        }

 

Simple, I just deserialize it and then do what I have to do with it.

Conclusion

This is just a simple example to get started about the raw notifications. I made a simple sample app with a WP8 client, an MVC form to enter data to send in the raw notification and a simple WCF service to register the uri.

To do before using it :

  • Run VS as administrator (as I use IIS)
  • Enable the WP emulator to connect to its host (see this article)
  • Change the service IP address (Phone solution, file ServiceReferences.client) with the one of the host

 

Download

Comments powered by Disqus