首先是用java来实现简单的Server端(http的请求内容格式可以参考msdn:http://msdn.microsoft.com/zh-cn/library/hh202945(v=vs.92)):
/**
* 推送toast通知
* @param uriString 推送服务通知uri
* @param title toast标题
* @param content toast内容
* @param param 页面跳转参数
* @return 推送通知服务响应码
* @throws IOException
*/
public static int pushToastNotifications(String uriString, String title, String content, String param) throws IOException{
String toastMsg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<wp:Notification xmlns:wp=\"WPNotification\">" +
"<wp:Toast>" +
"<wp:Text1>" + title + "</wp:Text1>" +
"<wp:Text2>" + content + "</wp:Text2>" +
"<wp:Param>"+ param +"</wp:Param>" +
"</wp:Toast>" +
"</wp:Notification>";
URL url = null;
HttpURLConnection http = null;
try{
url = new URL(uriString);
http = (HttpURLConnection)url.openConnection();
http.setDoOutput(true);
http.setRequestMethod("POST");
http.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
http.setRequestProperty("X-WindowsPhone-Target", "toast");
http.setRequestProperty("X-NotificationClass", "2");
http.setRequestProperty("Content-Length", "1024");
http.getOutputStream().write(toastMsg.getBytes());
// 刷新对象输出流,将任何字节都写入潜在的流中
http.getOutputStream().flush();
// 关闭输出流
http.getOutputStream().close();
}
catch(Exception e) {
e.printStackTrace();
}
finally{
if(http != null){
http.disconnect();
}
}
return http.getResponseCode();
}
服务端的测试数据:
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
System.in.read();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// 该uri是客户端运行并创建通道之后获得的
String urls = "http://db3.notify.live.net/throttledthirdparty/01.00/AAHGO5Q4sO3ZQa1cBCWwx4X9AgAAAAADAQAAAAQUZm52OjIzOEQ2NDJDRkI5MEVFMEQ";
String text1 = "中文";
String text2 = "English";
String param = "/NotificationPage.xaml?NavigatedFrom = ToastNotification&uri=http://baike.baidu.com/"; // 推送负载中,& 要转换写为&
try {
int code = pushToastNotifications(urls, text1, text2, param);
System.out.println("Response code : "+code);
}
catch (IOException e) {
e.printStackTrace();
}
}
接着是手机客户端的消息接收模块:
这里主要是为了演示当程序不在前台运行时Toast消息到达并点击Toast,来实现跳转到指定页面的效果。在客户端程序中本次demo会实现两个页面:MainPage.xaml和NotificationPage.xaml;MainPage.xaml用于获得通道uri,NotificationPage.xaml用于实现接收Toast时的指定跳转页面。
(1)a. MainPage.xaml
<phone:PhoneApplicationPage
x:Class="PushNotificationDemo.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"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent" Height="800" Width="480">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="200"/>
<RowDefinition Height="200"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="推送通知服务" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="推送通知" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Button x:Name="linkButton" Content="连接" Height="72" HorizontalAlignment="Left" Margin="83,82,0,0" VerticalAlignment="Top" Width="281" Click="linkButton_Click" />
</Grid>
<TextBlock x:Name="msgTextBlock" Grid.Row="2" Width="450" TextWrapping="Wrap"/>
<Button Grid.Row="3" Click="OnNavigateToWebBrowser" Content="下一个视图" Height="100" Width="300"/>
</Grid>
</phone:PhoneApplicationPage>
b. MainPage.xaml.cs
using System;
using System.Windows;
using Microsoft.Phone.Controls;
///引用通知服务命名空间
using Microsoft.Phone.Notification;
using System.Diagnostics;
using System.IO;
namespace PushNotificationDemo
{
public partial class MainPage : PhoneApplicationPage
{
private HttpNotificationChannel httpChannel;
private const string channelName = "ToastNotificationChannel";
// Constructor
public MainPage()
{
InitializeComponent();
}
private void linkButton_Click(object sender, RoutedEventArgs e)
{
httpChannel = HttpNotificationChannel.Find(channelName);
if (httpChannel == null)
{
httpChannel = new HttpNotificationChannel(channelName, "NotificationServer");
//注册URI
httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated);
//发生错误的事件
httpChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(httpChannel_ErrorOccurred);
//toast 推送通知服务事件
httpChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(httpChannel_ShellToastNotificationReceived);
//打开连接
httpChannel.Open();
//绑定toast 推送服务
httpChannel.BindToShellToast();
}
else
{
//注册URI
httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated);
//发生错误的事件
httpChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(httpChannel_ErrorOccurred);
//toast 推送通知服务事件
httpChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(httpChannel_ShellToastNotificationReceived);
linkButton.IsEnabled = false;
msgTextBlock.Text = "connected";
}
}
private void OnNavigateToWebBrowser(object sender, EventArgs e)
{
NavigationService.Navigate(new Uri("/NotificationPage.xaml", UriKind.Relative));
}
void httpChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
{
string msg = string.Empty;
foreach (var key in e.Collection.Keys)
{
msg += key + " : " + e.Collection[key] + Environment.NewLine;
}
Dispatcher.BeginInvoke(() =>
{
msgTextBlock.Text = msg;
});
}
void httpChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
{
//子线程中更新UI
Dispatcher.BeginInvoke(() =>
{
msgTextBlock.Text = e.Message;
linkButton.IsEnabled = true;
});
}
void httpChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{
Debug.WriteLine("CahnnelUri:{0}", e.ChannelUri);
Dispatcher.BeginInvoke(() =>
{
linkButton.IsEnabled = false;
});
}
}
}
(2)a. NotificationPage.xaml
<phone:PhoneApplicationPage
x:Class="PushNotificationDemo.NotificationPage"
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="800" d:DesignWidth="480"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="推送通知" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="Notification" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" Background="Transparent">
<phone:WebBrowser x:Name="Browser" IsScriptEnabled="True" ScriptNotify="OnScriptNotify"/>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
b. NotificationPage.xaml.cs
using System;
using Microsoft.Phone.Controls;
namespace PushNotificationDemo
{
public partial class NotificationPage : PhoneApplicationPage
{
#region Constants
private const string DefaultUrl = "http://www.baidu.com/";
private string m_UriString = string.Empty;
#endregion
public NotificationPage()
{
InitializeComponent();
Browser.Navigate(new Uri(DefaultUrl));
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
try
{
m_UriString = NavigationContext.QueryString["uri"];
Browser.Navigate(new Uri(m_UriString));
}
catch
{
}
}
private void OnScriptNotify(object sedner, NotifyEventArgs args)
{
}
}
}
最后就是实验证明了。运行的效果图如下:
点击跳转后效果图: