Windows Phone開發(43):推播通知第一集——Toast推送

來源:互聯網
上載者:User

好像有好幾天沒更新了,抱歉抱歉,最近“光榮”地失業,先是忙於尋找新去處,唉,暫時沒有下文。而後又有一些瑣事要辦,不過不要緊,今天咱們繼續。

動畫的內容就告一段落,本系列文章只作簡單引導,不會覆蓋每一個細節,最終能不能學好,就完全看各位自己了。

 

從本節開始,我們將討論推播通知,這個東西不太好理解,而推播通知的原理和過程,如果你看MSDN的,相信你會有點暈,若不,我帖出給你看看。

 算了,不帖,不知怎麼回事,上傳不了圖片。

 

現補片。

 

那麼,我就說一個故事吧,希望能協助你理解何為推播通知。

上大學的時候,我很喜歡到圖書館借書,然後,晚上在宿舍裡看,一直看到累了就睡覺。有一回,我發現一本好書叫《中國式商道》,結果呢,去圖書館沒找著,但是查一下是有的,我很看這本書,就去問管理員,管理員說可能被別人借了。

這時候我心裡想:那就每天來看一下有沒有在書架上,有再借。

管理員似乎猜到了我的心思,他說:“這位同學,你可以留下借書證號和連絡方式,如果你真想看那本書,一旦有人來還書了,我馬上通知你,你不必天天來找。”

我連忙說謝謝。

 

比如,我開好了應用程式A,使用者B的手機正在使用我的應用程式,但有時候我會發一些通知給使用者B手機,例如,增加新功能或修複某些Bug,或者有公益活邀請使用者參加等。但是,使用者B上的應用程式如何才知道有新訊息呢?

 

按照傳統的做法,在應用程式中做一個定時“炸彈”,每隔一段時間通過網路訪問一下我的伺服器,檢索一下有沒有新訊息,然後把結果返回給用戶端應用程式。你想想,這樣做的缺點是什嗎?

經常訪問網路,增加網路流量,也會消耗一定的電量和資源,如果我用GPRS上網,那就倒黴了。

但是,如果我的用戶端從來不需要主動訪問網路呢,我也不必在應用程式中放置計時器,程式無須訪問網路,我的新訊息不是發送到使用者手機,而是發送到微軟的雲端服務器,然後由雲端服務器把訊息推送到使用者手機。這樣就好比前面的例子,我不用天天跑去圖書館找書,只要有那本書,圖書館管理員就把電話找我。你說,這樣是不是既省心也省力了?

 

推播通知有三種:Toast通知,磁帖通知和自訂通知。前面兩種都是死的,都是被硬性規定的,你不要問為什麼,記住就行了。而第三種即Raw通知,這種通知方式比較靈活,你可以自訂其格式和內容。

 

今天,我們來瞭解第一種通知——Toast。

這是什麼呢?

 

 

 本想截個圖的,但不知道啥事,就是上傳不了,沒反應,CSDN的部落格經常出問題。那沒辦法了,我用文字描述一下吧,Toast通知就是在應用程式沒有在前台運行時,如果收到Toast通知,會在螢幕最上方顯示一條提示資訊,就和我們收到簡訊時一樣。

 

微軟的雲端服務器會為我們的手機分配一個URL,就在侈的應用程式註冊推送通道後更新的,雲端服務器就是利用這個URL來找到你的手機並把通知發到手機上,就像前面例子中,我 留下借書證編號和電話號碼,到時候,管理員可以通過手機號碼來聯絡我。實際開發在,你可以通過各種方式把這個URL傳到你的伺服器上儲存,因為發送推播通知是需要這個URL的。

一般來說,如果你建有自己的伺服器,就應該會有一個固定的IP地址或網域名稱,你不妨通過HTTP方式把使用者手機的URL發送到你的伺服器儲存。

 

那麼,如何發送推播通知呢?不要被嚇倒,其實很簡單,就是平常我們熟悉的POST方式提交一個HTTP請求罷了,而提交的URL就是從雲端服務器中得到的URL。而POST的內容就是一個XML文檔。Toast推播通知的格式如下:

<?xml version="1.0" encoding="utf-8" ?><wp:Notification xmlns:wp="WPNotification">  <wp:Toast>    <wp:Text1>文本一</wp:Text1>    <wp:Text2>文本二</wp:Text2>    <wp:Param>參數</wp:Param>  </wp:Toast></wp:Notification>

這是固定的格式,不要問我為什麼,它就是死的。“文本一”指的是顯示Toast提示的標題,“本文二”自然就是本文了,文字盡量簡單,最好幾個字搞定。

而“參數”呢?它其它是一個URI,這個URI就是當使用者點擊了Toast訊息後啟動應用程式時導航到的頁面,這個與前面我們說到的“次要磁帖”是一樣的。舉幾個例子吧。

/MainPage.xaml

/MainPage.xa/Mml?v=12345

/MainPage.xaml?value1=123&amp;value2=abcd

 

最後一條其實就是value1=123&value2=abc,別忘了是XML文檔,字元&是要轉義的,記得前面有人提問,在導航那一節中,在XAML中設定導航頁面/myPage.xaml?t1=aaaa&t2=bbbb,時會報錯,要知道XAML其實就是XML擴充而來的,特殊字元記住要轉義。

 

例如,我要發一條Toast通知,標題為“你好”,內容為“想請你吃飯”,參數為“/MainPage.xmal”,那麼,我們POST的XML文檔應當為:

<?xml version="1.0" encoding="utf-8" ?><wp:Notification xmlns:wp="WPNotification">  <wp:Toast>    <wp:Text1>你好</wp:Text1>    <wp:Text2>想請你吃飯</wp:Text2>    <wp:Param>/MainPage.xaml</wp:Param>  </wp:Toast></wp:Notification>

 

知道這一點就好辦了,下面我們來做一個發送Toast訊息的伺服器端。

1、任你喜歡用哪個版本的VS,建立一個Windows應用程式,很熟悉了吧,就是WinForm。

2、接著是介面,暈了,上傳不了圖片。這樣吧,你隨便扔幾個TextBox上去,分別用來填RUI,第一個值,第二個值,參數,響應訊息。總共5個,最後一個用來顯示發送結果,內容較多,建議用多行。再放一個按鈕,觸發它的Click事件,點擊後立即發送。

 

好,我直接把所有代碼帖上,這東西不好講解,但相信你如果基礎學得好,肯定看得懂。

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Net;using System.IO;namespace SendToast{    public partial class Form1 : Form    {        public Form1()        {            InitializeComponent();        }        private void btnSend_Click(object sender, EventArgs e)        {            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(txtUrl.Text);            myRequest.ContentType = "text/xml";            myRequest.Headers.Add("X-WindowsPhone-Target", "toast");            /*             *   X-NotificationClass 處理間隔             *   2 - 立即發送             *   12 - 450秒內發送             *   22 - 900秒內發送             */            myRequest.Headers.Add("X-NotificationClass", "2");            // 要發送的內容            string toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +            "<wp:Notification xmlns:wp=\"WPNotification\">" +                "<wp:Toast>" +                    "<wp:Text1>" + txtValue1.Text + "</wp:Text1>" +                    "<wp:Text2>" + txtValue2.Text + "</wp:Text2>" +                    "<wp:Param>" + txtParam.Text + "</wp:Param>" +                "</wp:Toast>" +            "</wp:Notification>";            byte[] buffer = Encoding.UTF8.GetBytes(toastMessage);            myRequest.ContentLength = buffer.Length;            myRequest.Method = "POST";            using (Stream stream = myRequest.GetRequestStream())            {                stream.Write(buffer, 0, buffer.Length);            }            // 接收回應            HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();            string headers= "";            foreach (var hd in myResponse.Headers.AllKeys)            {                headers += hd + " : " + myResponse.Headers[hd] + " | ";            }            headers += "\r\n";            string msg = "";            using (Stream recStream = myResponse.GetResponseStream())            {                StreamReader reader = new StreamReader(recStream, Encoding.UTF8);                msg = reader.ReadToEnd();                reader.Close();            }            msg += "\r\n\r\n";            txtResult.AppendText(headers + msg);        }    }}

 

接下來,到WP用戶端,同樣隨便你用什麼版本的VS,建立一個Silverlight for Windows Phone應用程式,有些人腦子比較敏感,看到Silverlight字樣不知發生什麼事。其實,只是瞭解它的人不多而已,Silverlight其實有很多優點的,慢慢體會吧,用客觀公正的視角去體會吧。

 

介面布局就好辦了,我直接上XAML,如果你看不懂,回去複習WPF。

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">            <TextBlock Name="txtInfo" TextWrapping="Wrap"/>        </Grid>

後台代碼也照帖了。

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;namespace WPApp{    public partial class MainPage : PhoneApplicationPage    {        // 建構函式        public MainPage()        {            HttpNotificationChannel myChannel = null;            // 推送通道的名字,隨便取一個就行了            string ChannelName = "ToastChannel";            InitializeComponent();            // Find靜態方法可以根據名字尋找通道            myChannel = HttpNotificationChannel.Find(ChannelName);            // 如果找不到,就要建立一個了            if (myChannel == null)            {                myChannel = new HttpNotificationChannel(ChannelName);                // 註冊事件                myChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(myChannel_ChannelUriUpdated);                myChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(myChannel_ErrorOccurred);                myChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(myChannel_ShellToastNotificationReceived);                // 開啟通道                myChannel.Open();                // 綁定Toast通知,這樣在程式不在前台時才會顯示                // 螢幕上方的通知提示條                myChannel.BindToShellToast();            }            else            {                // 如果存在,還要註冊一次事件,因為在程式被扔到後台後可能會刪除事件綁定                myChannel.ChannelUriUpdated+=new EventHandler<NotificationChannelUriEventArgs>(myChannel_ChannelUriUpdated);                myChannel.ErrorOccurred+=new EventHandler<NotificationChannelErrorEventArgs>(myChannel_ErrorOccurred);                myChannel.ShellToastNotificationReceived+=new EventHandler<NotificationEventArgs>(myChannel_ShellToastNotificationReceived);                                // 在“輸出”窗輸出URL,因為我們只是測試,這樣一來方便一點                System.Diagnostics.Debug.WriteLine("通道URI為:{0}", myChannel.ChannelUri.ToString());            }        }        void myChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)        {            string msg = "";            foreach (string key in e.Collection.Keys)            {                msg += key + " : " + e.Collection[key] + "\r\n";            }            Dispatcher.BeginInvoke(() =>                {                    this.txtInfo.Text = msg;                });        }        void myChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)        {            Dispatcher.BeginInvoke(() => MessageBox.Show(e.Message));        }        void myChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)        {            // 當URL發生改變後,還要輸出一次            // 保證我們得到的是最新版本的URI            Dispatcher.BeginInvoke(() =>            {                System.Diagnostics.Debug.WriteLine("通道URI:{0}", e.ChannelUri.ToString());            });        }        // 這個方法不用我多介紹了        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)        {            base.OnNavigatedTo(e);            if (NavigationContext.QueryString.ContainsKey("toastmsg"))            {                this.txtInfo.Text = NavigationContext.QueryString["toastmsg"];            }        }    }}

 

好了,那麼,如何測試呢,毫無疑問,兩個程式要同時運行,從VS的“輸出”視窗中把RUI複製到發送程式對應的文字框中,填好幾個參數,如標題本文等,然後,你回到WP模擬器,點擊[開始] 按鈕,讓應用程式不在最前台。

 

再回到伺服器端,點擊發送按鈕,等一會兒,你在模擬器中會看到Toast提示條的出現了。

沒辦法上傳圖片,只能這樣了。

 

下面,總結一下,推播通知其實不難的,其本質就是HTTP通訊,而且三種方式有兩種是固定格式的,開啟MSDN的樣本,照抄就行了,一樣的。

 

但要理解它不是那麼容易,記住要多練,學編程沒什麼捷徑,最快的捷徑就是動手幹活。你可能會問:你是怎麼熟悉這些技術的?

那我告訴你吧,這幾個推播通知的代碼,我已經寫了十幾二十遍了,你說我會不理解嗎?不信你也寫上十遍看看。

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.