2012年7月2日星期一

与众不同 windows phone (9)

与众不同 windows phone (9)

[源码下载]


与众不同 windows phone (9) - Push Notification(推送通知)之概述, 推送 Toast 通知



作者:webabcd


介绍
与众不同 windows phone 7.5 (sdk 7.1) 之推送通知

  • 概述
  • 推送 Toast 通知



示例
1、概述
Summary.xaml

<phone:PhoneApplicationPage     x:    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    ="http://schemas.microsoft.com/winfx/2006/xaml"    ="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"    ="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"    ="http://schemas.microsoft.com/expression/blend/2008"    ="http://schemas.open    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>    <!--        推送信息中需要编码的字符            < - &lt;        > - &gt;        & - &amp;        ' - &apos;        " - &quot;    --></phone:PhoneApplicationPage>



2、推送 Toast 通知
客户端
PushToast.xaml

<phone:PhoneApplicationPage     x:    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    ="http://schemas.microsoft.com/winfx/2006/xaml"    ="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"    ="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"    ="http://schemas.microsoft.com/expression/blend/2008"    ="http://schemas.open    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 ="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 信息的                 string toastMessage = "<?" +                "<wp:Notification " +                   "<wp:Toast>" +                        "<wp:Text1>" + txtTitle.Text + "</wp:Text1>" + // Toast 的标题                        "<wp:Text2>" + txtContent.Text + "</wp:Text2>" + // Toast 的内容                        "<wp:Param>/PushNotification/PushToast.xaml?param=abc&amp;param2=xyz</wp:Param>" + // 需要导航到的地址                   "</wp:Toast> " +                "</wp:Notification>";                byte[] requestMessage = Encoding.UTF8.GetBytes(toastMessage);                // 推送 Toast 信息时的 Http Header 信息                request.ContentLength = requestMessage.Length;                request.ContentType = "text/";                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
[源码下载]


TAG: