Windows Phone開發(fā)(45):推送通知大結(jié)局之Raw通知
為什么叫大結(jié)局呢?因?yàn)橥扑屯ㄖ?wù)就只有三種,前面扯了兩種,就剩下一種——Raw通知。
前面我們通過(guò)兩節(jié)的動(dòng)手實(shí)驗(yàn),相信大家都知道了,推送通知其實(shí)并不復(fù)雜,為什么呢?你看到了的,不管是哪種方式,使用方法基本一樣,如果你不愿意寫代碼的話,完全可以把代碼Copy幾下就完事了,三種推送通知的實(shí)現(xiàn)代碼是一樣的,而僅僅是發(fā)送的內(nèi)容不同罷了。
Raw推送通知比起前面兩種更簡(jiǎn)單,因?yàn)樗鼪]有規(guī)范的格式,只要你向指定URI POST一個(gè)字節(jié)流數(shù)組就OK,也就是說(shuō),只要能變成byte[]的東西都可以發(fā)送。不過(guò),不應(yīng)該發(fā)送過(guò)大的數(shù)據(jù),一般用于發(fā)送一些簡(jiǎn)短的文本信息就行了,別想著用來(lái)發(fā)送文件??!
嚴(yán)重提醒:要接收Raw通知,你的WP應(yīng)用程序必須在前臺(tái)運(yùn)行,不然是收不到的,之與Toast通知可不一樣,如果你的程序不在前臺(tái)運(yùn)行,推送的通知就會(huì)被XX掉。
好了,F(xiàn)話就不說(shuō)了,開始操練吧。
先做發(fā)送通知的服務(wù)器端,這回就用WPF來(lái)做吧,界面我先截個(gè)TU。
這就是用WPF的好處,截圖中大家未必能看到窗口上用到哪些控件,設(shè)置了哪些屬性,但是,如果我把XAML一貼,我想大家就懂了。
- <Window x:Class="RawNtfServer.MainWindow"
 - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 - Title="Raw通知服務(wù)器端" Height="350" Width="525">
 - <Grid>
 - <Grid.RowDefinitions>
 - <RowDefinition Height="Auto" />
 - <RowDefinition />
 - <RowDefinition />
 - </Grid.RowDefinitions>
 - <Grid Grid.Row="0">
 - <Grid.ColumnDefinitions>
 - <ColumnDefinition Width="auto"/>
 - <ColumnDefinition Width="*"/>
 - <ColumnDefinition Width="auto"/>
 - </Grid.ColumnDefinitions>
 - <TextBlock Grid.Column="0" Text="目標(biāo)URI:" VerticalAlignment="Center"/>
 - <TextBox Name="txtUri" Grid.Column="1" Margin="2" Background="#FFD8E4E4"/>
 - <Button Grid.Column="2" Padding="8,3,8,3" Margin="7,2,3,2" Content="發(fā)送" Click="OnSend"/>
 - </Grid>
 - <GroupBox Grid.Row="1" Header="發(fā)送內(nèi)容">
 - <TextBox VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" Name="txtMsg" Background="#FFECF4D7" />
 - </GroupBox>
 - <GroupBox Grid.Row="2" Header="回應(yīng)內(nèi)容">
 - <TextBox Name="txtResp" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" Background="#FFC9EDFA" />
 - </GroupBox>
 - </Grid>
 - </Window>
 
好,前臺(tái)干好了,去搞搞后臺(tái)吧。
- using System;
 - using System.Collections.Generic;
 - using System.Linq;
 - using System.Text;
 - using System.Windows;
 - using System.Windows.Controls;
 - using System.Windows.Data;
 - using System.Windows.Documents;
 - using System.Windows.Input;
 - using System.Windows.Media;
 - using System.Windows.Media.Imaging;
 - using System.Windows.Navigation;
 - using System.Windows.Shapes;
 - using System.Net;
 - using System.IO;
 - using System.Net.Mime;
 - namespace RawNtfServer
 - {
 - /// <summary>
 - /// MainWindow.xaml 的交互邏輯
 - /// </summary>
 - public partial class MainWindow : Window
 - {
 - public MainWindow()
 - {
 - InitializeComponent();
 - }
 - private void OnSend(object sender, RoutedEventArgs e)
 - {
 - if (txtUri.Text==""||txtMsg.Text=="")
 - {
 - MessageBox.Show("請(qǐng)輸入必備的參數(shù)。"); return;
 - }
 - HttpWebRequest request = (HttpWebRequest)WebRequest.Create(txtUri.Text);
 - request.Method = WebRequestMethods.Http.Post;
 - request.ContentType = MediaTypeNames.Text.Plain;
 - // HTTP標(biāo)頭:
 - // X-NotificationClass:3
 - // 3:立即發(fā)送
 - // 13:450秒后發(fā)送
 - // 23:900秒后發(fā)送
 - request.Headers.Add("X-NotificationClass", "3");
 - byte[] buffer = Encoding.UTF8.GetBytes(txtMsg.Text);
 - request.ContentLength = buffer.Length;
 - using (Stream s = request.GetRequestStream())
 - {
 - s.Write(buffer, 0, buffer.Length);
 - }
 - // 接收響應(yīng)
 - HttpWebResponse response = (HttpWebResponse)request.GetResponse();
 - string hds = "";
 - foreach (string key in response.Headers.AllKeys)
 - {
 - hds += key + " : " + response.Headers.Get(key) + "\r\n";
 - }
 - txtResp.Text = hds;
 - }
 - }
 - }
 
有沒有覺得代碼很熟悉?和前兩節(jié)中的例子像不?
好了,服務(wù)器端Done,下面輪到WP客戶端了。
布局不用TU了,放心,無(wú)圖有真相。上XAML。
- <!--ContentPanel - 在此處放置其他內(nèi)容-->
 - <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
 - <ListBox Name="lbMsg"/>
 - </Grid>
 
簡(jiǎn)單吧,就一個(gè)控件——ListBox,待會(huì)兒我們接受到的通知,就扔到它里面。
OK,看看后臺(tái)的C#代碼。
- 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 WPClient
 - {
 - public partial class MainPage : PhoneApplicationPage
 - {
 - // 構(gòu)造函數(shù)
 - public MainPage()
 - {
 - InitializeComponent();
 - HttpNotificationChannel Channel = null;
 - string ChannelName = "raw";
 - Channel = HttpNotificationChannel.Find(ChannelName);
 - if (Channel==null)
 - {
 - Channel = new HttpNotificationChannel(ChannelName);
 - Channel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(Channel_ChannelUriUpdated);
 - Channel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(Channel_ErrorOccurred);
 - Channel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(Channel_HttpNotificationReceived);
 - Channel.Open();
 - }
 - else
 - {
 - Channel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(Channel_ChannelUriUpdated);
 - Channel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(Channel_ErrorOccurred);
 - Channel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(Channel_HttpNotificationReceived);
 - System.Diagnostics.Debug.WriteLine("URI: {0}", Channel.ChannelUri.ToString());
 - }
 - }
 - void Channel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
 - {
 - string msg = "";
 - using (System.IO.Stream stream=e.Notification.Body)
 - {
 - System.IO.StreamReader rd = new System.IO.StreamReader(stream, System.Text.Encoding.UTF8);
 - msg = rd.ReadToEnd();
 - }
 - Dispatcher.BeginInvoke(() =>
 - {
 - this.lbMsg.Items.Add(DateTime.Now.ToLongTimeString() + " " + msg);
 - });
 - }
 - void Channel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
 - {
 - Dispatcher.BeginInvoke(() =>
 - {
 - MessageBox.Show(e.Message);
 - });
 - }
 - void Channel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
 - {
 - Dispatcher.BeginInvoke(() =>
 - {
 - System.Diagnostics.Debug.WriteLine("URI: {0}",e.ChannelUri.ToString());
 - });
 - }
 - }
 - }
 
避免有朋友說(shuō)代碼看不懂,這回我是Ctrl + A后再貼出來(lái)的。
下面來(lái)執(zhí)行一下,首先運(yùn)行WP端,可以同時(shí)運(yùn)行,隨你喜歡。但至少要讓W(xué)P模擬器或手機(jī)收到云服務(wù)器分配的URI。
把這個(gè)URI復(fù)制,填到服務(wù)器端的窗口中,然后輸入你要發(fā)送的東東,點(diǎn)擊“發(fā)送”。
嗯,就是這樣用,應(yīng)該不復(fù)雜吧?
在收發(fā)消息的過(guò)程中,編碼時(shí)建議使用UTF-8,貌似這個(gè)不會(huì)有亂碼。
哈,牛就吹到這了,下一節(jié)我們玩一玩比較恐怖的東西——Socket。


















 
 
 


 
 
 
 