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

Advertisements

5 Responses to “Push Notification in Windows Phone 7”

  1. Vijay Says:

    Nice one..! I understand that when we say Windows 7 doesn’t support multitasking, it does mean that no more than one Application can be scheduled for execution and it does mean that, if you start second application then first application would be context switched and put in dormant state and can only be rescheduled on “External” event like “Push Notification” and/or you yourself relauch the same application.. is that so?
    Note: Windows 7 does support multitasking for the internal apps and not for third party apps.

    • Pradnya Says:

      Hi Vijay ,
      There is no dormant state. The application is completely terminated.(deactivated)……. BUT..
      Instead of u relaunching the app , and for better navigation functionality
      If an application takes over ur current running app, the prev app gets tombstoned.
      A tombstoned application’s process gets terminated , but WP7 stores a trace or record of application state in a back-stack(it is like a journal)..
      Incase you press the back button, you go back to last page of the tombstoned application……
      The best link you can refer for more information is
      Windows Team Blog

  2. Hardik Shah [Guru] Says:

    Cool ! Pradnya … I’m getting into the knack of understanding WP7’s working and what I understand is that it’s a phone for which Internet is indispensable !

    Assuming an App is running when Internet is not available, can I store some messages/data offline and when online I can sent it to the destination VIA the cloud … ?

    Regards,
    H.

    • Pradnya Says:

      WP7 device has got Isolated storage. U can save your data in isolated storage
      and wen u connect online you can code to update your data.

  3. Karthikeyan Anbarasan Says:

    Nice article… I am begineer to WP7… Good to see articles on WP7… Hope to seee more!!!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s