Push Notification in Windows Phone 7

Windows Phone 7 has now got support for Push Notifications. Before diving into the implementation let us understand the working of Push Technology.

Push Technology:

This technology involves communication in form of messages initiated by a publisher or central server. Push services follow publish-subscribe model where in the server pushes the information to the clients and the client application subscribes and pulls the information.

Windows Phone 7 Push Notification functionality support :

Windows Phone 7 does not support multitasking, hence push notification is the only method to notify the user.

The push services work as follows in line of business applications:

 image

Steps:

1)  The cloud service sends notification requests to Push Notification service.

2)  It routes the notification to the application. Notifications may be one of the three types:

       a. Tile Notification – The tile notifications are handled by phone ,if the application is pinned to the start page. The title, tile image and the tile number are three items that can be altered with a tile notification. The phone receives tile notifications only when application is not in running state.

       b. Toast Notifications – A toast notification comes in when the application is running. If the user clicks the notification, the application will launch.

       c. Raw Notifications – Raw notifications include raw data of any format and size but within limits. The phone receives them only when the application is running.

3)  Once the notification type is set, a notification channel is created to receive the push notifications at the client side. A subscription is also created which allows the cloud service to push notifications to that channel. A channel is represented by a URI which contains all of the information associated with the subscription.

4)  Once an application receives the push notification, it can access the cloud service using the cloud service’s protocol to retrieve any needed information.

Now lets us go through the steps to complete our demo :

Step 1: Simulating the cloud service to sending Push Notifications.

Step 2 : Setting up notification channel to receive notifications.

Step 3: Registering with the notification service.

Step 4 : A client application on Windows Phone 7 receiving notifications.

The solution structure will include 3 projects:

img1

NotificationService:  A WCF project acting as a background process to send messages.
NotificationSender:   A WPF project sending messages.
NotificationConsumer:  Windows Phone 7 client application receiving messages and displaying them as notifications.

NotificationService Project:

 img2

The service contract includes methods to send toast messages, send raw messages and let client application subscribe for notifications:

[ServiceContract]
    public interface IService1
    {

      //function to let client application subscribe to notification service.
      [OperationContract]
        void Subscribe(Guid _uniqueID,string uri);

        //method to send toast notifications
        [OperationContract]
        void SendToastNotification(string message);

        //method to send raw notifications.
        [OperationContract]
        void SendRawNotification(string message);

    }

The class(Service1.svc.cs) implementing the service is as follows:

namespace NotificationService
{

    //Notification Types
    public enum NotificationType
    {
        Tile = 1,
        Toast = 2,
        Raw = 3
    }

    //Time interval required to send messages.
    public enum BatchingInterval
    {
        TileImmediately = 1,
        ToastImmediately = 2,
        RawImmediately = 3,
        TileWait450 = 11,
        ToastWait450 = 12,
        RawWait450 = 13,
        TileWait900 = 21,
        ToastWait900 = 22,
        RawWait900 = 23
    }

    public class Service1 : IService1
    {

        private static Dictionary<Guid, Uri> _clientUris = new Dictionary<Guid, Uri>();

        public void Subscribe(Guid _uniqueID, string uri)
        {
            if (_clientUris.ContainsKey(_uniqueID))
            {
                _clientUris[_uniqueID] = new Uri(uri);
            }

            else
            {
                _clientUris.Add(_uniqueID, new Uri(uri));
            }
        }

        public void SendToastNotification(string message)
        {
            var toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                 "<wp:Notification xmlns:wp=\"WPNotification\">" +
                    "<wp:Toast>" +
                       "<wp:Text1>{0}</wp:Text1>" +
                      "</wp:Toast>" +
                 "</wp:Notification>";
            toastMessage = string.Format(toastMessage,message);

            var messageBytes = System.Text.Encoding.UTF8.GetBytes(toastMessage);

            foreach (var uri in _clientUris.Values)
            {
                SendMessage(uri, messageBytes, NotificationType.Toast);
            }
        }

        public void SendRawNotification(string message)
        {
            var messageBytes = Encoding.UTF8.GetBytes(message);

            foreach (var uri in _clientUris.Values)
            {
                SendMessage(uri, messageBytes, NotificationType.Raw);
            }   
        }

        public void SendTileNotification(string message)
        {
            throw new NotImplementedException();
        }

        private void SendMessage(Uri uri, byte[] messageBytes, NotificationType notificationType)
        {
            var request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = WebRequestMethods.Http.Post;
            request.ContentType = "text/xml";
            request.ContentLength = messageBytes.Length;

            request.Headers.Add("X-MessageID", Guid.NewGuid().ToString());

            if(notificationType == NotificationType.Toast)
            {
                    request.Headers["X-WindowsPhone-Target"] = "toast";
                    request.Headers.Add("X-NotificationClass",((int)BatchingInterval.ToastImmediately).ToString());
            }
            else
            {

                    request.Headers.Add("X-NotificationClass", ((int)BatchingInterval.RawImmediately).ToString());
            }

            using (var requestStream = request.GetRequestStream())
            {
                requestStream.Write(messageBytes, 0, messageBytes.Length);
            }

         }
    }
}

Web.config file including endpoint settings for the service.

img3

 

NotificationSender Project:

img4

This WPF project sends text lines to service which are sent either as toast notifications or raw notifications.

MainWindow.xaml

img5

Code behind for MainWindow.xaml.cs

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void SendtoastNotification_Click(object sender, RoutedEventArgs e)
        {
            var toastService = new NotificationSenderReference.Service1Client();
            toastService.SendToastNotification(txtToastMessage.Text);
        }

        private void SendRawNotification_Click(object sender, RoutedEventArgs e)
        {
            var rawService = new NotificationSenderReference.Service1Client();
            rawService.SendRawNotification(txtRawMessage.Text);
        }
    }

 

NotificationConsumer Project:

img6

MainPage.xaml: XAML Code for the above design. All messages are added as items in Listbox.

<Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!–TitlePanel contains the name of the application and page title–>
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">
            <TextBlock x:Name="ApplicationTitle" Text="PUSH NOTIFICATION SAMPLE" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="UPDATES" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!–ContentPanel – place additional content here–>
        <Grid x:Name="ContentGrid" Grid.Row="1" Background="Gray" >

            <ListBox x:Name="lstOffers">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                            <TextBlock Text="{Binding}" FontFamily="Segoe WP Light"  FontSize="20"/>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
    </Grid>

MainPage.xaml.cs code:

public partial class MainPage : PhoneApplicationPage
   {
       private HttpNotificationChannel _channel;
       private const string ChannelName = "Notifications.Phone.NotificationChannel";
       private Guid _deviceId;

       public MainPage()
       {
           InitializeComponent();
           if (DesignerProperties.IsInDesignTool)
               return;

           if (IsolatedStorageSettings.ApplicationSettings.Contains("DeviceId"))
           {
               _deviceId = (Guid)IsolatedStorageSettings.ApplicationSettings["DeviceId"];
           }
           else
           {
               _deviceId = Guid.NewGuid();
               IsolatedStorageSettings.ApplicationSettings["DeviceId"] = _deviceId;
           }

           SetupNotificationChannel();
       }

       private void SetupNotificationChannel()
       {
           _channel = HttpNotificationChannel.Find(ChannelName);

           if (_channel == null)
           {
               _channel = new HttpNotificationChannel(ChannelName);
               _channel.ChannelUriUpdated += ChannelUriUpdated;
               _channel.ErrorOccurred += (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => ErrorOccurred(e));
               _channel.Open();
           }
           else
           {
               RegisterForNotifications();
           }
       }

       private void RegisterForNotifications()
       {
           RegisterWithNotificationService();
           _channel.ShellToastNotificationReceived += (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => ToastReceived(e));
           _channel.HttpNotificationReceived += (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => HttpNotificationReceived(e));
           _channel.ErrorOccurred += (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => ErrorOccurred(e));
       }

       private void HttpNotificationReceived(HttpNotificationEventArgs e)
       {
           var reader = new StreamReader(e.Notification.Body);
           var message = reader.ReadToEnd();
           .Items.Add("Raw notification : " + message);
           reader.Close();
       }

       private void RegisterWithNotificationService()
       {
           var svc = new NotificationServiceReference.Service1Client();

           svc.SubscribeCompleted += (s, e) =>
           {
               if (e.Error != null)
               {
                   Debug.WriteLine("Error registering with notification service");
               }
           };

           svc.SubscribeAsync(_deviceId, _channel.ChannelUri.ToString());
       }

       private void ToastReceived(NotificationEventArgs e)
       {
           lstOffers.Items.Add("Toast Recevied : "+ e.Collection["wp:Text1"]);
        }

       private void ErrorOccurred(NotificationChannelErrorEventArgs e)
       {

           lstOffers.Items.Add(e.Message);
           Debug.WriteLine("ERROR:" + e.Message);
       }

       private void ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
       {
           _channel = HttpNotificationChannel.Find(ChannelName);

           if (!_channel.IsShellToastBound)
           {
               _channel.BindToShellToast();
           }

           RegisterForNotifications();
       }
   }

 

Now let’s run the project:

First

1) Run the NotificationService, to start the service.

2) Start a new instance of NotificationSender application .

3) Start the Windows Phone 7 application to receive notifications.

Output:

img7

 

img8

 

So that was a simple demo on Push Notifications on Windows Phone 7. For receiving Tile notifications you can check below links and more information:

Excellent blogs:

http://www.thisisfanzoo.com/Blog/JeffF/archive/2010/08/02/a-really-long-post-about-the-windows-phone-7-push.aspx

http://chris.59north.com/post/Using-Windows-Phone-7-Push-Notifications.aspx

MSDN Links:

http://msdn.microsoft.com/en-us/library/ff402537%28v=VS.92%29.aspx

Follow

Get every new post delivered to your Inbox.

Join 42 other followers