與眾不同 windows phone (9) - Push Notification(推送通知)之概述, 推送 Toast 通知
作者:webabcd
介紹
與眾不同 windows phone 7.5 (sdk 7.1) 之推送通知
- 概述
- 推送 Toast 通知
示例
1、概述
Summary.xaml
<phone:PhoneApplicationPage x:Class="Demo.PushNotification.Summary" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray.IsVisible="True"> <StackPanel Orientation="Vertical"> <TextBlock Text="推送通知模型" /> <Image Source="/PushNotification/Summary.jpg" /> <TextBlock TextWrapping="Wrap" Margin="0 15 0 0"> <Run>推送通知概述</Run> <LineBreak /> <LineBreak /> <Run>1、每個程序的推送通知 channel 只能有一個,每個設備最多只能有 30 個推送通知 channel</Run> <LineBreak /> <Run>2、推送通知的 Http Header 最大 1 KB,內容最大 3 KB</Run> <LineBreak /> <Run>3、對 web 服務做身份驗證(即 https 協議),參考:http://msdn.microsoft.com/en-us/library/ff941099(v=vs.92)</Run> <LineBreak /> <Run>4、對於已驗證的 web 服務,MPNS 可以支持在設備轉到活動狀態或非活動狀態時,回調指定的已驗證的 web 服務,參考:http://msdn.microsoft.com/en-us/library/ff402554(v=vs.92)</Run> </TextBlock> </StackPanel> <!-- 推送信息中需要編碼的字符 < - < > - > & - & ' - ' " - " --> </phone:PhoneApplicationPage>
2、推送 Toast 通知
客戶端
PushToast.xaml
<phone:PhoneApplicationPage x:Class="Demo.PushNotification.PushToast" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray.IsVisible="True"> <StackPanel Orientation="Vertical"> <Button Name="btnRegister" Content="Get Channel Uri" Click="btnRegister_Click" /> <TextBox Name="txtUrl" /> <TextBlock Name="lblMsg" TextWrapping="Wrap" /> </StackPanel> </phone:PhoneApplicationPage>
PushToast.xaml.cs
/* * 演示推送 Toast 通知(Toast 的顯示時間大約是 10 秒) * * HttpNotificationChannel - 推送通知 channel * HttpNotificationChannel.Find(string channelName) - 查找並返回 channel,一個 app 只能有一個 channel * * ChannelUri - 推送通知的 channel URI * ChannelName - channel 的名稱 * ConnectionStatus - channel 的連接狀態,ChannelConnectionStatus.Connected 或 ChannelConnectionStatus.Disconnected * * ChannelUriUpdated - 獲取到了 channel URI 后所觸發的事件 * ErrorOccurred - 發生異常時所觸發的事件 * ConnectionStatusChanged - 連接狀態發生改變時所觸發的事件 * ShellToastNotificationReceived - 程序運行中如果收到 Toast 是不會顯示的,但是會觸發此事件。 * 什么叫運行中:程序在前台顯示,且調用了 HttpNotificationChannel.Find(channelName)(沒有則創建一個),同時 channel 是在連接的狀態 * HttpNotificationReceived - 接收到自定義信息通知后所觸發的事件(僅在程序運行中才能接收到此信息) * * Open() - 打開 channel * Close() - 關閉 channel * * BindToShellToast() - 將此 channel 綁定到 Toast 通知 * BindToShellTile() - 將此 channel 綁定到 Tile 通知,只能引用本地資源 * BindToShellTile(Collection<Uri> baseUri) - 將此 channel 綁定到 Tile 通知,允許引用遠程資源(當使用遠程圖像時,不能是https,要小於80KB,必須30秒內下載完) * baseUri - 允許引用的遠程資源的域名集合(最大 256 個字符) * IsShellToastBound - 此 channel 是否綁定到了 Toast 通知 * IsShellTileBound - 此 channel 是否綁定到了 Tile 通知 */ 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.Text; using System.Diagnostics; namespace Demo.PushNotification { public partial class PushToast : PhoneApplicationPage { public PushToast() { InitializeComponent(); } protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { if (NavigationContext.QueryString.Count > 0) { lblMsg.Text = "參數 param 的值為:" + this.NavigationContext.QueryString["param"]; lblMsg.Text += Environment.NewLine; lblMsg.Text += "參數 param2 的值為:" + this.NavigationContext.QueryString["param2"]; } base.OnNavigatedTo(e); } private void btnRegister_Click(object sender, RoutedEventArgs e) { // 在當前應用程序中查找指定的 channel string channelName = "myChannel"; HttpNotificationChannel channel = HttpNotificationChannel.Find(channelName); if (channel == null) // 未發現則創建一個 channel { channel = new HttpNotificationChannel(channelName); channel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(channel_ChannelUriUpdated); channel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(channel_ErrorOccurred); channel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(channel_ShellToastNotificationReceived); channel.Open(); channel.BindToShellToast(); } else // 已存在則使用這個已存在的 channel { channel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(channel_ChannelUriUpdated); channel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(channel_ErrorOccurred); channel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(channel_ShellToastNotificationReceived); if (channel.ConnectionStatus == ChannelConnectionStatus.Disconnected) channel.Open(); if (!channel.IsShellToastBound) channel.BindToShellToast(); // 獲取通知 uri txtUrl.Text = channel.ChannelUri.ToString(); Debug.WriteLine(channel.ChannelUri.ToString()); } } void channel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e) { Dispatcher.BeginInvoke(() => { // 獲取通知 uri txtUrl.Text = e.ChannelUri.ToString(); Debug.WriteLine(e.ChannelUri.ToString()); }); } void channel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e) { Dispatcher.BeginInvoke(() => MessageBox.Show(e.Message)); } // 運行中的程序如果收到 Toast 的話,則會執行此事件(不會顯示 Toast) // 什么叫運行中:程序在前台顯示,且調用了 HttpNotificationChannel.Find(channelName)(沒有則創建一個),同時 channel 是在連接的狀態 void channel_ShellToastNotificationReceived(object sender, NotificationEventArgs e) { StringBuilder msg = new StringBuilder(); foreach (string key in e.Collection.Keys) { msg.Append(key); msg.Append(" - "); msg.Append(e.Collection[key]); msg.Append(Environment.NewLine); } // 顯示 Toast 原始信息 Dispatcher.BeginInvoke(() => lblMsg.Text = msg.ToString()); } } }
服務端
SendToastNotification.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="SendToastNotification.aspx.cs" Inherits="Web.PushNotification.SendToastNotification" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> 通知 url: <asp:TextBox ID="txtUrl" runat="server"></asp:TextBox> </div> <div> Toast 標題: <asp:TextBox ID="txtTitle" runat="server" Text="Toast 標題"></asp:TextBox> </div> <div> Toast 子標題: <asp:TextBox ID="txtContent" runat="server" Text="Toast 內容"></asp:TextBox> </div> <div> 回應信息: <asp:TextBox ID="txtMsg" runat="server" TextMode="MultiLine" Rows="20" Columns="100"></asp:TextBox> </div> <div> <asp:Button ID="btnSend" runat="server" Text="發送 Toast 通知" OnClick="btnSend_Click" /> </div> </form> </body> </html>
SendToastNotification.aspx.cs
/* * 演示服務端如何推送 Toast 通知 */ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Text; using System.Net; using System.IO; namespace Web.PushNotification { public partial class SendToastNotification : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void btnSend_Click(object sender, EventArgs e) { try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(txtUrl.Text); request.Method = "POST"; // 構造用於推送 Toast 信息的 xml string toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<wp:Notification xmlns:wp=\"WPNotification\">" + "<wp:Toast>" + "<wp:Text1>" + txtTitle.Text + "</wp:Text1>" + // Toast 的標題 "<wp:Text2>" + txtContent.Text + "</wp:Text2>" + // Toast 的內容 "<wp:Param>/PushNotification/PushToast.xaml?param=abc&param2=xyz</wp:Param>" + // 需要導航到的地址 "</wp:Toast> " + "</wp:Notification>"; byte[] requestMessage = Encoding.UTF8.GetBytes(toastMessage); // 推送 Toast 信息時的 Http Header 信息 request.ContentLength = requestMessage.Length; request.ContentType = "text/xml"; request.Headers.Add("X-WindowsPhone-Target", "toast"); request.Headers.Add("X-NotificationClass", "2"); // 2 - 立即發送;12 - 450秒內發送;22 - 900秒內發送 using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(requestMessage, 0, requestMessage.Length); } // 處理 MPNS 的回應信息 HttpWebResponse response = (HttpWebResponse)request.GetResponse(); string notificationStatus = response.Headers["X-NotificationStatus"]; string notificationChannelStatus = response.Headers["X-SubscriptionStatus"]; string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"]; txtMsg.Text = "Http Status Code: " + response.StatusCode + Environment.NewLine + "X-NotificationStatus: " + notificationStatus + Environment.NewLine + "X-SubscriptionStatus: " + deviceConnectionStatus + Environment.NewLine + "X-DeviceConnectionStatus: " + notificationChannelStatus; // 各個狀態的具體描述信息,詳見如下地址 // http://msdn.microsoft.com/en-us/library/ff941100(v=vs.92) } catch (Exception ex) { txtMsg.Text = ex.ToString(); } } } }
OK
[源碼下載]
