• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
dnso
博客园    首页    新随笔    联系   管理    订阅  订阅

推送通知服务

概述

  Windows Phone 中的Microsoft Push Notification Service向第三方开发人员提供了一个弹性,专注,而且持续的渠道,使得开发人员可以从web service向移动应用程序发送信息和更新。

  过去移动应用程序需要经常主动去调查其相应的Web服务,以了解是否有任何等待处理的通知。这样做虽然有效,但是会导致手机的无线设备频繁打开,从而对电池续航时间带来负面影响. 使用推送通知的方式取代主动调查,web service能够提醒应用程序获取所需要的重要更新。

 

                      图 1  推送 Notifications

  当一个Web service有信息要发送到应用程序,它先发送一个通知到Push Notification Service,该服务随后将通知路由到应用程序。根据推送通知的格式和装载量,信息作为原始数据传递到应用程序,应用程序的标题明显地更新或显示一个Toast通知。然后如果需要的话应用程序可以使用自己的协议联系web service以获取更新。

  Push Notification Service在推送通知发送后向你的web service发送一个回复码.然而,Push Notification Service不能为你的推送提醒是否成功传递到应用程序提供端到端的确认.了解更多信息,请参考 Push Notification Service Response Codes for Windows Phone


推送消息过程:

 

          图 2

  1. WP设备到MSNS注册PN服务,并得到唯一的服务URI
  2. WP设备把服务URI传递给Cloud服务,并注册
  3. 当有更新消息发送时,Cloud服务往MSNS服务发送更新消息
  4. MSNS把更新消息发送到WP设备
  5. 需要时WP设备往Cloud服务读取更多的数据

 

推送通知服务类型:

  • Raw Notification
    • 可以发送任何格式的数据
    • 应用程序可以根据需要加工数据
    • 应用程序相关(Application-specific)的通知消息
    • 只有在应用程序运行时,才发送
  • Toast Notification
    • 发送的数据为指定的XML格式
    • 如果应用程序正在运行,内容发送到应用程序中
    • 如果应用程序不在运行,弹出Toast消息框显示消息
      • App图标加上2个文本描述
      • 打断用户当前操作,但这是临时的
      • 用户可以点击进行跟踪
  • Title Notification
    • 发送的数据为指定的XML格式
    • 不会往应用程序进行发送
    • 如果用户把应用程序pin to start,那么更新数据发送到start screen的titile里
      • 包含三个属性,背景,标题和计算器
      • 每个属性都有固定的格式与位置
      • 可以使用其中的属性,不一定三个属性一起使用

示例1:(摘自Webcast)

首先建立服务端Windows窗体程序,相当于图2中的Your Cloud Application,界面如下

 

 加入“发送”按钮事件:

View Code
private void button1_Click(object sender, EventArgs e)
        {
            
string msg = String.Format("{0}{1}, {2}度", LocationComboBox.Text,
                    WeatherComboBox.Text, TemperatureTextBox.Text);
            
string type = NotificationTypeComboBox.Text as string;
            
if (type == "Raw")
            {
                
byte[] strBytes = new UTF8Encoding().GetBytes(msg);
                SendRawNotification(strBytes);
            }
            
else if (type == "Toast")
            {
                
string toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                        
"<wp:Notification xmlns:wp=\"WPNotification\">" +
                           
"<wp:Toast>" +
                              
"<wp:Text1>天气更新</wp:Text1>" +
                              
"<wp:Text2>" + msg + "</wp:Text2>" +
                           
"</wp:Toast>" +
                        
"</wp:Notification>";
                
byte[] strBytes = new UTF8Encoding().GetBytes(toastMessage);
                SendToastNotification(strBytes);
            }
            
else if (type == "Tile")
            {
                
string tileMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                    
"<wp:Notification xmlns:wp=\"WPNotification\">" +
                       
"<wp:Tile>" +
                          
"<wp:BackgroundImage>/Images/" + WeatherComboBox.Text + ".png</wp:BackgroundImage>" +
                          
"<wp:Count>" + TemperatureTextBox.Text + "</wp:Count>" +
                          
"<wp:Title>" + LocationComboBox.Text + "</wp:Title>" +
                       
"</wp:Tile> " +
                    
"</wp:Notification>";
                
byte[] strBytes = new UTF8Encoding().GetBytes(tileMessage);
                SendTileNotification(strBytes);
            }
        }

加入Raw Notification的方法:

View Code
private void SendRawNotification(byte[] Payload)
        {
            
// The URI that the Push Notification Service returns to the Push Client when creating a notification channel.
            HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(NotificationUriTextBox.Text);

            
// HTTP POST is the only allowed method to send the notification.
            sendNotificationRequest.Method = WebRequestMethods.Http.Post;

            
// The optional custom header X-MessageID uniquely identifies a notification message. If it is present, the 
            
// same value is returned in the notification response. It must be a string that contains a UUID.
            sendNotificationRequest.Headers["X-MessageID"] = Guid.NewGuid().ToString();

            
// Sets raw notification
            sendNotificationRequest.ContentType = "text/xml; charset=utf-8";
            sendNotificationRequest.Headers.Add(
"X-NotificationClass", "3");
            
// Possible batching interval values:
            
// 3: The message is delivered by the Push Notification Service immediately.
            
// 13: The message is delivered by the Push Notification Service within 450 seconds.
            
// 23: The message is delivered by the Push Notification Service within 900 seconds.

            
// Sets the web request content length.
            sendNotificationRequest.ContentLength = Payload.Length;

            
// Sets the notification payload to send.
            byte[] notificationMessage = Payload;

            
// Sends the notification.
            using (Stream requestStream = sendNotificationRequest.GetRequestStream())
            {
                requestStream.Write(notificationMessage, 
0, notificationMessage.Length);
            }

            
// Gets the response.
            HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();
            
string notificationStatus = response.Headers["X-NotificationStatus"];
            
string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
            
string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];
            MsgLabel.Text 
= String.Format("通知状态:{0},管道状态:{1},设备状态:{2}",
                notificationStatus, notificationChannelStatus, deviceConnectionStatus);
        }

加入Toast Notification类型的方法:

View Code
private void SendToastNotification(byte[] Payload)
        {
            
// The URI that the Push Notification Service returns to the Push Client when creating a notification channel.
            HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(NotificationUriTextBox.Text);

            
// HTTP POST is the only allowed method to send the notification.
            sendNotificationRequest.Method = WebRequestMethods.Http.Post;

            
// The optional custom header X-MessageID uniquely identifies a notification message. If it is present, the 
            
// same value is returned in the notification response. It must be a string that contains a UUID.
            sendNotificationRequest.Headers["X-MessageID"] = Guid.NewGuid().ToString();

            
// Sets toast notification
            sendNotificationRequest.ContentType = "text/xml; charset=utf-8";
            sendNotificationRequest.Headers.Add(
"X-WindowsPhone-Target", "toast");
            sendNotificationRequest.Headers.Add(
"X-NotificationClass", "2");
            
// Possible batching interval values:
            
// 2: The message is delivered by the Push Notification Service immediately.
            
// 12: The message is delivered by the Push Notification Service within 450 seconds.
            
// 22: The message is delivered by the Push Notification Service within 900 seconds.

            
// Sets the web request content length.
            sendNotificationRequest.ContentLength = Payload.Length;

            
// Sets the notification payload to send.
            byte[] notificationMessage = Payload;

            
// Sends the notification.
            using (Stream requestStream = sendNotificationRequest.GetRequestStream())
            {
                requestStream.Write(notificationMessage, 
0, notificationMessage.Length);
            }

            
// Gets the response.
            HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();
            
string notificationStatus = response.Headers["X-NotificationStatus"];
            
string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
            
string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];
            MsgLabel.Text 
= String.Format("通知状态:{0},管道状态:{1},设备状态:{2}",
                notificationStatus, notificationChannelStatus, deviceConnectionStatus);
        }

 加入Tile Notification类型的方法:

View Code
private void SendTileNotification(byte[] Payload)
        {
            
// The URI that the Push Notification Service returns to the Push Client when creating a notification channel.
            HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(NotificationUriTextBox.Text);

            
// HTTP POST is the only allowed method to send the notification.
            sendNotificationRequest.Method = WebRequestMethods.Http.Post;

            
// The optional custom header X-MessageID uniquely identifies a notification message. If it is present, the 
            
// same value is returned in the notification response. It must be a string that contains a UUID.
            sendNotificationRequest.Headers["X-MessageID"] = Guid.NewGuid().ToString();

            
// Sets toast notification
            sendNotificationRequest.ContentType = "text/xml; charset=utf-8";
            sendNotificationRequest.Headers.Add(
"X-WindowsPhone-Target", "token");
            sendNotificationRequest.Headers.Add(
"X-NotificationClass", "1");
            
// Possible batching interval values:
            
// 1: The message is delivered by the Push Notification Service immediately.
            
// 11: The message is delivered by the Push Notification Service within 450 seconds.
            
// 21: The message is delivered by the Push Notification Service within 900 seconds.

            
// Sets the web request content length.
            sendNotificationRequest.ContentLength = Payload.Length;

            
// Sets the notification payload to send.
            byte[] notificationMessage = Payload;

            
// Sends the notification.
            using (Stream requestStream = sendNotificationRequest.GetRequestStream())
            {
                requestStream.Write(notificationMessage, 
0, notificationMessage.Length);
            }

            
// Gets the response.
            HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();
            
string notificationStatus = response.Headers["X-NotificationStatus"];
            
string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
            
string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];
            MsgLabel.Text 
= String.Format("通知状态:{0},管道状态:{1},设备状态:{2}",
                notificationStatus, notificationChannelStatus, deviceConnectionStatus);
        }

 

 

新建Windows Phone Application,界面如下图所示:

 

在MainPage.xaml.cs类中添加字段代码

View Code
private HttpNotificationChannel httpChannel;
        
private const string channelName = "Channel1";

添加 “连接”按钮事件代码

View Code
private void button1_Click(object sender, RoutedEventArgs e)
        {
            httpChannel 
= HttpNotificationChannel.Find(channelName);
            
//Delete the Channel if exists
            if (httpChannel != null)
            {
                httpChannel.Close();

                httpChannel.Dispose();
            }
            
//Create the channel
            httpChannel = new HttpNotificationChannel(channelName, "NotificationService");

            
//Register to UriUpdated event - occurs when channel successfully opens
            
//WP设备到MSNS注册PN服务,并得到唯一的服务URI 
            httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated);

            
//general error handling for push channel
            httpChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(httpChannel_ErrorOccurred);

            
//Subscribed to Raw Notification
            httpChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(httpChannel_HttpNotificationReceived);

            
//subscrive to toast notification when running app
            
//程序运行时收到消息
            httpChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(httpChannel_ShellToastNotificationReceived);
            
            
//Open the channel
            httpChannel.Open();

            
//subscrive to toast notification
            
//程序没有运行时,消息会在WP设备顶部弹出显示
            httpChannel.BindToShellToast();

            
//subscrive to tile notification            
            httpChannel.BindToShellTile();
        }

添加事件代码

View Code
void httpChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
        {
            
string msg = "";
            
foreach (var key in e.Collection.Keys)
            {
                msg 
+= key + ": " + e.Collection[key] + Environment.NewLine;
            }
            Dispatcher.BeginInvoke(() 
=>
            {
                MsgTextBlock.Text 
= msg;
            });
        }

        
void httpChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
        {
            
using (var reader = new StreamReader(e.Notification.Body))
            {
                
string msg = reader.ReadToEnd();
                Dispatcher.BeginInvoke(() 
=>
                {
                    MsgTextBlock.Text 
= msg;
                });
            }
        }

        
void httpChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
        {
            Dispatcher.BeginInvoke(() 
=>
            {
                MsgTextBlock.Text 
= e.Message;
            });
        }

        
void httpChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
        {
            Debug.WriteLine(
"ChannelUri: {0}", e.ChannelUri);
        }


示例1代码 


示例2:

本示例演示了Toast Notification的使用。示例包含3个项目:

1.WCF服务应用程序,模拟Cloud Application

IService1.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfService1
{
    [ServiceContract]
    
public interface IService1
    {
        [OperationContract]
        
void Subscribe(string uri);

        [OperationContract]
        
void SendToast(string title, string message);
    }

}
Service1.svc.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

using System.Net;

namespace WcfService1
{
    
public class Service1 : IService1
    {
        
private static Uri uri;

        
public void Subscribe(string subscriberUri)
        {
            uri 
= new Uri(subscriberUri);
        }

        
public void SendToast(string title, string message)
        {
            
string toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                
"<wp:Notification xmlns:wp=\"WPNotification\">" +
                   
"<wp:Toast>" +
                      
"<wp:Text1>" + title + "</wp:Text1>" +
                      
"<wp:Text2>" + message + "</wp:Text2>" +
                   
"</wp:Toast>" +
                
"</wp:Notification>";

            
byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(toastMessage);
            SendMessage(uri, messageBytes);
        }


        
private static void SendMessage(Uri uri, byte[] message)
        {
            HttpWebRequest request 
= (HttpWebRequest)WebRequest.Create(uri);
            request.Method 
= WebRequestMethods.Http.Post;
            request.ContentType 
= "text/xml";
            request.ContentLength 
= message.Length;

            request.Headers.Add(
"X-MessageID", Guid.NewGuid().ToString());

            request.Headers[
"X-WindowsPhone-Target"] = "toast";
            request.Headers.Add(
"X-NotificationClass", "2");

            var requestStream 
= request.GetRequestStream();
            requestStream.Write(message, 
0, message.Length);
        }
    }


}

2.WPF应用程序,消息推送触发程序

MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
        xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
        Title
="MainWindow" Height="350" Width="525">
    
<Grid>
        
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="218,101,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
    
</Grid>
</Window>
MainWindow.xaml.cs
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;

namespace WpfApplication1
{
    
/// <summary>
    
/// Interaction logic for MainWindow.xaml
    
/// </summary>
    public partial class MainWindow : Window
    {
        
public MainWindow()
        {
            InitializeComponent();
        }

        
private void button1_Click(object sender, RoutedEventArgs e)
        {
            ServiceReference1.Service1Client svc 
= new ServiceReference1.Service1Client();
            svc.SendToast(
"Check app", "new data has arrived");

        }
    }
}
app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
<system.serviceModel>
        
<bindings>
            
<basicHttpBinding>
                
<binding name="BasicHttpBinding_IService1" closeTimeout="00:01:00"
                    openTimeout
="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    allowCookies
="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferSize
="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding
="Text" textEncoding="utf-8" transferMode="Buffered"
                    useDefaultWebProxy
="true">
                    
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead
="4096" maxNameTableCharCount="16384" />
                    
<security mode="None">
                        
<transport clientCredentialType="None" proxyCredentialType="None"
                            realm
="" />
                        
<message clientCredentialType="UserName" algorithmSuite="Default" />
                    
</security>
                
</binding>
            
</basicHttpBinding>
        
</bindings>
        
<client>
            
<endpoint address="http://localhost:10317/Service1.svc" binding="basicHttpBinding"
                bindingConfiguration
="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
                name
="BasicHttpBinding_IService1" />
        
</client>
    
</system.serviceModel>
</configuration>

3.Windows Phone Application,手机接收程序

MainPage.xaml
<phone:PhoneApplicationPage 
    x:Class
="WindowsPhoneApplication1.MainPage"
    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:DesignWidth="480" d:DesignHeight="768"
    shell:SystemTray.IsVisible
="True">

    
<!--LayoutRoot contains the root grid where all other page content is placed-->
    
<Grid x:Name="LayoutRoot" Background="Transparent">
        
<Grid.RowDefinitions>
            
<RowDefinition Height="Auto"/>
            
<RowDefinition Height="*"/>
        
</Grid.RowDefinitions>

        
<!--TitlePanel contains the name of the application and page title-->
        
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">
            
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
            
<TextBlock x:Name="PageTitle" Text="page name" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        
</StackPanel>

        
<!--ContentPanel - place additional content here-->
        
<Grid x:Name="ContentGrid" Grid.Row="1">
            
<TextBlock Height="276" HorizontalAlignment="Left" Margin="48,108,0,0" Name="textBlock1" Text="TextBlock" VerticalAlignment="Top" Width="350" />
        
</Grid>
    
</Grid>
</phone:PhoneApplicationPage>
MainPage.xaml.cs
using System;
using System.Windows;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Notification;

namespace WindowsPhoneApplication1
{
    
public partial class MainPage : PhoneApplicationPage
    {
        
private HttpNotificationChannel channel;
        
private const string ChannelName = "MyChannel";

        
public MainPage()
        {
            InitializeComponent();

            SetupNotificationChannel();
        }

        
private void SetupNotificationChannel()
        {
            channel 
= HttpNotificationChannel.Find(ChannelName);

            
if (channel == null)
            {
                channel 
= new HttpNotificationChannel(ChannelName);
                channel.ChannelUriUpdated 
+= new EventHandler<NotificationChannelUriEventArgs>(channel_ChannelUriUpdated);
                channel.Open();
            }
            
else
            {
                RegisterForNotifications();
            }
        }

        
void channel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
        {
            channel 
= HttpNotificationChannel.Find(ChannelName);
            channel.BindToShellToast();
            RegisterForNotifications();
        }

        
private void RegisterForNotifications()
        {
            ServiceReference1.Service1Client svc 
= new ServiceReference1.Service1Client();
            svc.SubscribeAsync(channel.ChannelUri.ToString());

            channel.ShellToastNotificationReceived 
+= (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => ToastReceived(e));
        }

        
private void ToastReceived(NotificationEventArgs e)
        {
            textBlock1.Text 
= string.Format("Title: " + e.Collection["wp:Text1"] + "\nMessage: " + e.Collection["wp:Text2"]);
        }
    }

}

 

示例3:Windows Phone 7 SDK

微软提供的SDK示例,可以访问参考链接4 ,查看完整的示例代码。

 

参考链接:

1.Windows Phone 7 in 7: Push Notifications
http://www.msdev.com/Directory/Description.aspx?eventId=1885
 

2.Code Download 

http://blogs.itmentors.com/nancy
 
3.MSDN Webcast - Silverlight for Windows Phone 开发系列课程(12):推送通知服务
https://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032473761&EventCategory=3&culture=en-US&CountryCode=US
 
4.使用 Push Notifications实验文档和代码
http://msdn.microsoft.com/zh-cn/Windowsphone/default.aspx 

 

Receive Push Notifications in an Application for Windows Phone 
http://msdn.microsoft.com/en-us/library/ff402556%28v=VS.92%29.aspx
 

 

 

 

 

 

posted @ 2011-02-25 17:44  dnso  阅读(9044)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3