天天看點

Windows Phone 7 不溫不火學習之《推送通知服務》

 Windows Phone 中的 Microsoft Push Notification Service 向第三方開發人員提供了一個彈性,專注,而且持續的管道,使得開發人員可以從Web Service 向移動應用程式發送資訊和更新。

  過去移動應用程式需要經常主動通路相應的WEB服務,以了解是否有任何等待處理的通知。這樣做是有效的,但會導航手機無線裝置頻繁打開,進而對電池續航時間或者使用者的流量帶來負面 影響。使用推送通知的方式取代主動調查,Web Service 能夠提醒應用程式擷取所需要的重要理更新。

  當一個Web Service 有資訊要發送到應用程式,它先發送一個通知到Push Notification Service ,該服務随後将通知應用程式,應用程式的标題明顯地更新或者顯示一個Toast 通知。然後,如果需要的話,應用程式可以使用自己的的協定聯系Web service 以擷取更新。

  關于推送通知服務,看了Jake Lin 的視訊他說的“好萊塢原則”己經說得很清楚了,不過我自己從現實中的淘寶購物也産生了一定的了解,下面跟大家分享一下,給出圖示:

  如上圖,我們可以把推送通知了解成,一部手機就相當于我們一個使用者,在淘寶注冊了帳号并填寫了送貨位址(URI),在購買完自己需要的物品後,通知淘寶商家發貨了,這時淘寶商家接收到我們給出的URI,就把貨品打包,可以使用萬能打包把什麼東西都放進去(Raw)或者根據我們的要求要打包成禮品的樣子(Tokens或者Toast 需要的XML格式 ),之後通知快遞公司(微軟--》不同的是,微軟是免費的幫我們快遞 ) 。而當我們收到快遞公司給予我們的通知後,如打電話說:“先生,你的貨品己經到達,請接收”,之後我們就根據打包方式進行接收啦。

  大意的了解是這樣的。

Push notification 發送方式

  如上一段文字出現了幾個英文單詞就是Push notification 的三種發送方式,分别為:

  •  Raw Notification

    1.可以發送任何格式的資料

    2.應用程式可以根據需要加工資料

    3.應用程式相關(application-specific)通知消息

    4.隻有在應用程式運作時,才發送。

  • Toast Notification

    1.發送的資料為指定的XML 格式

    2.如果應用程式正在運作,内容發送到應用程式中

    3.如果應用程式沒有運作,彈出Toast 消息框顯示消息

       3.1App 圖示加上兩個描述文本

      3.2打斷使用者目前操作,但是是臨時的

      3.3使用者可以點選進行跟蹤

  • Tokens (Tile) Notification

    1.發送的資料為指定的XML格式

    2.不會往應用程式進行發送

    3.如果使用者把應用程式PIN TO START ,那麼更新資料發送到start screen 的tile 裡面

      3.1包含三個屬性,背景,标題和電腦

      3.2每個屬性都有固定的格式與位置

      3.3可以使用其中的屬性,不一定三個屬性一起使用

Push Notification使用規範

  • 目前版本的Windows Phone 隻支援最多15 個第三方應用程式使用推送服務通知服務
  • 應用程式必須内置詢問使用者是否使用推送通知服務的功能
  • 應用程式必須内置使用者可以取消推送通知服務的功能

Demo 示範

關于Push Notification 的事件為如下:

 //注冊URI

            httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated);

            //發生錯誤的事件

            httpChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(httpChannel_ErrorOccurred);

            //Raw 推送通知服務事件

            httpChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(httpChannel_HttpNotificationReceived);

            //toast 推送通知服務事件

            httpChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(httpChannel_ShellToastNotificationReceived);

我們可以在需要注冊的地方使用,Windows Phone 的大緻使用代碼為如下:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

using Microsoft.Phone.Controls;

///引用通知服務命名空間

using Microsoft.Phone.Notification;

using System.Diagnostics;

using System.IO;

namespace PushNotificationDemo

{

    public partial class MainPage : PhoneApplicationPage

    {

        private HttpNotificationChannel httpChannel;

        private const string channelName = "Channel";

        // Constructor

        public MainPage()

        {

            InitializeComponent();

        }

        private void linkButton_Click(object sender, RoutedEventArgs e)

            httpChannel = HttpNotificationChannel.Find(channelName);

            //如果存在就删除

            if (httpChannel!=null)

            {

                httpChannel.Close();

                httpChannel.Dispose();

            }

            httpChannel = new HttpNotificationChannel(channelName, "NotificationServer");

            //注冊URI

            //打開連接配接

            httpChannel.Open();

            //綁定toast 推送服務

            httpChannel.BindToShellToast();

            //綁定Tokens (tile) 推送服務 

            httpChannel.BindToShellTile();

        void httpChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)

            string msg = string.Empty;

            foreach (var key in e.Collection.Keys)

                msg += key + " : " + e.Collection[key] + Environment.NewLine;

            Dispatcher.BeginInvoke(() => 

                msgTextBlock.Text = msg;

            });

        void httpChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)

            //Raw 支援任意格式資料

            using (var reader=new StreamReader(e.Notification.Body))

                string msg = reader.ReadToEnd();

                Dispatcher.BeginInvoke(() =>

                {

                    msgTextBlock.Text = msg;

                });

        void httpChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)

            //子線程中更新UI

                msgTextBlock.Text = e.Message;

            } );

        void httpChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)

            Debug.WriteLine("CahnnelUri:{0}",e.ChannelUri);

            Dispatcher.BeginInvoke(() =>

                linkButton.IsEnabled = false;

    }

}

之後,我們建立一個Windows Form 應用程式,做為Cloud server 。

首先,建立一個枚舉,建立三個枚舉項為如下:

 public enum notificationType 

            raw,

            toast,

            tokens

然後編寫發送通知服務通用方法體:

 void sendNotificationType(byte[] payLoad,notificationType type)

            // The URI that the Push Notification Service returns to the Push Client when creating a notification channel.

            HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(NotificationUriTextBox.Text);

            // HTTP POST is the only allowed method to send the notification.

            sendNotificationRequest.Method = WebRequestMethods.Http.Post;

            // The optional custom header X-MessageID uniquely identifies a notification message. If it is present, the 

            // same value is returned in the notification response. It must be a string that contains a UUID.

            sendNotificationRequest.Headers["X-MessageID"] = Guid.NewGuid().ToString();

            if (type==notificationType.raw)

                // Sets raw notification

                sendNotificationRequest.ContentType = "text/xml; charset=utf-8";

                sendNotificationRequest.Headers.Add("X-NotificationClass", "3");

                // Possible batching interval values:

                // 3: The message is delivered by the Push Notification Service immediately.

                // 13: The message is delivered by the Push Notification Service within 450 seconds.

                // 23: The message is delivered by the Push Notification Service within 900 seconds.

            else if (type == notificationType.tokens)

                // Sets toast notification

                sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "token");

                sendNotificationRequest.Headers.Add("X-NotificationClass", "1");

                // 1: The message is delivered by the Push Notification Service immediately.

                // 11: The message is delivered by the Push Notification Service within 450 seconds.

                // 21: The message is delivered by the Push Notification Service within 900 seconds.

            else if (type==notificationType.toast)

            { 

                sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "toast");

                sendNotificationRequest.Headers.Add("X-NotificationClass", "2");

                // 2: The message is delivered by the Push Notification Service immediately.

                // 12: The message is delivered by the Push Notification Service within 450 seconds.

                // 22: The message is delivered by the Push Notification Service within 900 seconds.

            // Sets the web request content length.

            sendNotificationRequest.ContentLength = payLoad.Length;

            // Sets the notification payload to send.

            byte[] notificationMessage = payLoad;

            // Sends the notification.

            using (Stream requestStream = sendNotificationRequest.GetRequestStream())

                requestStream.Write(notificationMessage, 0, notificationMessage.Length);

            // Gets the response.

            HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();

            string notificationStatus = response.Headers["X-NotificationStatus"];

            string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];

            string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];

            MsgLabel.Text = String.Format("通知狀态:{0},管道狀态:{1},裝置狀态:{2}",

                notificationStatus, notificationChannelStatus, deviceConnectionStatus);

設定點選後,請求微軟做推送服務:

private void button1_Click(object sender, EventArgs e)

            string msg = String.Format("{0}{1}, {2}度", LocationComboBox.Text,

                    WeatherComboBox.Text, TemperatureTextBox.Text);

            string type = NotificationTypeComboBox.Text as string;

            if (type == "Raw")

                byte[] strBytes = new UTF8Encoding().GetBytes(msg);

                sendNotificationType(strBytes,notificationType.raw);

            else if (type == "Toast")

                string toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +

                        "<wp:Notification xmlns:wp=\"WPNotification\">" +

                           "<wp:Toast>" +

                              "<wp:Text1>天氣更新</wp:Text1>" +

                              "<wp:Text2>" + msg + "</wp:Text2>" +

                           "</wp:Toast>" +

                        "</wp:Notification>";

                byte[] strBytes = new UTF8Encoding().GetBytes(toastMessage);

                sendNotificationType(strBytes,notificationType.toast);

            else if (type == "Tile")

                string tileMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +

                    "<wp:Notification xmlns:wp=\"WPNotification\">" +

                       "<wp:Tile>" +

                          "<wp:BackgroundImage>/Images/" + WeatherComboBox.Text + ".png</wp:BackgroundImage>" +

                          "<wp:Count>" + TemperatureTextBox.Text + "</wp:Count>" +

                          "<wp:Title>" + LocationComboBox.Text + "</wp:Title>" +

                       "</wp:Tile> " +

                    "</wp:Notification>";

                byte[] strBytes = new UTF8Encoding().GetBytes(tileMessage);

                sendNotificationType(strBytes, notificationType.tokens);

注:本篇URI是通過列印得到。然後指派給Windows Form 應用程式,如下圖:

例子運作效果如下圖:

上圖為Raw notification運作效果

運作時的Toast

不運作時的Taost

Tokens 運作效果

×××:

繼續閱讀