Windows Phone开发(43):推送通知第一集——Toast推送

原文:Windows Phone开发(43):推送通知第一集——Toast推送

好像有好几天没更新了,抱歉抱歉,最近“光荣”地失业,先是忙于寻找新去处,唉,暂时没有下文。而后又有一些琐事要办,不过不要紧,今天咱们继续。

动画的内容就告一段落,本系列文章只作简单引导,不会覆盖每一个细节,最终能不能学好,就完全看各位自己了。

 

从本节开始,我们将讨论推送通知,这个东西不太好理解,而推送通知的原理和过程,如果你看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的示例,照抄就行了,一样的。

 

但要理解它不是那么容易,记住要多练,学编程没什么捷径,最快的捷径就是动手干活。你可能会问:你是怎么熟悉这些技术的?

那我告诉你吧,这几个推送通知的代码,我已经写了十几二十遍了,你说我会不理解吗?不信你也写上十遍看看。

 

 

 

时间: 2024-09-17 22:22:30

Windows Phone开发(43):推送通知第一集——Toast推送的相关文章

Windows Phone开发(44):推送通知第二集——磁贴通知

原文:Windows Phone开发(44):推送通知第二集--磁贴通知 前面我们说了第一个类型--Toast通知,这玩意儿不知大家是不是觉得很新鲜,以前玩.NET编程应该没接触过吧? 其实这东西绝对不复杂,只是刚接触的时候会有点莫名罢了,Toast通知和今天要说的磁贴通知,都有一个共同点,那就是格式都规定死了D. 本质就是向特定的URI地址POST一个XML文档罢了,相信很多人都会,如果你还不会,真的,要补一补基础课了.  多说无益,还是快点切入主题,开门见水吧. 首先,我们要知道我们在服务器

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

原文:与众不同 windows phone (9) - Push Notification(推送通知)之概述, 推送 Toast 通知 [索引页][源码下载] 与众不同 windows phone (9) - Push Notification(推送通知)之概述, 推送 Toast 通知 作者:webabcd 介绍与众不同 windows phone 7.5 (sdk 7.1) 之推送通知 概述 推送 Toast 通知 示例1.概述Summary.xaml <phone:PhoneApplica

Windows 8开发入门(三)第一个拆分布局应用程序修改Logo

在VS2012中新建一个拆分布局应用程序如下: 开发入门(三)第一个拆分布局应用程序修改Logo-cad在布局内拆分打印"> 然后我们看它的项目布局如下: 计算机入门第一个"> 在 这里我们可以看到项目结构内容以及意义如下: Assets文件夹:存放系统图片和资源 Common文 件夹:存放系统公共代码和通用文件 DataModel文件夹:存放数据层数据,在本实例中存放Sample数据 ItemsPage.xaml:主要内容列表呈现组界面 SplitPage.xaml:组内

iOS10推送通知开发教程_php实例

虽然通知经常被过度使用,但是通知确实是一种获得用户关注和通知他们需要更新或行动的有效方式.iOS 10有了新的通知,如新消息.商业信息和时间表的变化.在本教程中,我将向你展示如何使用通知在你的iOS应用程序,并且显示iOS 10引入了新特性.开发iOS 10推送通知你需要最新版本的Xcode,Xcode 8测试版,这些目前都是可下载的,在下载页面. 你可以去Github下载本教程的整个工程. 开始 在Xcode中启用推送通知是很容易的,但你需要几个步骤. 创建一个新的工程,给它起一个唯一的Bun

重新想象 Windows 8 Store Apps (67) - 后台任务: 推送通知

原文:重新想象 Windows 8 Store Apps (67) - 后台任务: 推送通知 [源码下载] 重新想象 Windows 8 Store Apps (67) - 后台任务: 推送通知 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台任务 推送通知 示例1.客户端BackgroundTask/PushNotification.xaml <Page x:Class="XamlDemo.BackgroundTask.PushNotificatio

Windows Phone开发(45):推送通知大结局——Raw通知

原文:Windows Phone开发(45):推送通知大结局--Raw通知 为什么叫大结局呢?因为推送通知服务就只有三种,前面扯了两种,就剩下一种--Raw通知. 前面我们通过两节的动手实验,相信大家都知道了,推送通知其实并不复杂,为什么呢?你看到了的,不管是哪种方式,使用方法基本一样,如果你不愿意写代码的话,完全可以把代码Copy几下就完事了,三种推送通知的实现代码是一样的,而仅仅是发送的内容不同罢了. Raw推送通知比起前面两种更简单,因为它没有规范的格式,只要你向指定URI POST一个字

Windows Azure中使用推送通知、SMS和电子邮件的最佳做法

在十月份我们为Mobile Services交付了iOS 客户端库以后,许多人询问什么时候支持iOS推送通知.正如Scott Guthrie周三宣布的那样,Mobile Services现在支持发送iOS推送通知!通过添加一种更简单的登陆方法,我们改善了iOS Client API:现在配置用户身份认证只需要单行的http://www.aliyun.com/zixun/aggregation/79237.html">Objective-C代码. 使用此更新,现在Mobile Service

Windows Azure移动服务增加APNS推送通知的新支持

几周前,我发表了一篇有关Windows http://www.aliyun.com/zixun/aggregation/13357.html">Azure 移动服务的若干改进的博文.其中之一就是增加一个Objective-C客户端 SDK来允许 iOS 开发人员方便地使用移动服务处理数据和身份验证.今天我很兴奋地宣布几项对我们的 iOS SDK 的改进,最重要的还是我们通过APNS(苹果推送通知服务)推送通知的新支持.这使得它非常简单地从 Windows Azure 移动服务的脚本中推送通

Windows 10如何关闭推送通知?

1.Windows 10 升级通知有人程序补丁来进行判断了,这个补丁为:KB3035583,我们只要删除它就可以了,打开"开始菜单,然后找到"控制面板 -- 程序和功能 -- 查看已安装的更新"如下图所示: 2.在程序管理中我们找到 KB3035583 的更新,点击卸载即可(需要重启),如图: 3.注意:KB3035583 是系统自动安装了,如果我们系统更新开启了,windows会自动在后台再次安装KB3035583 补丁了,所以我们可以把更设置一下,我们同样在"控