且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

OpenXLive Push Notification Hosting服务开发指南

更新时间:2022-09-23 08:07:18

Download

Windows Phone上支持Push Notification,用户可以使用微软的推送服务器(MPNS)向安装了自己软件的Windows Phone设备上推送三种不同的通知消息。

Push Notification的机制大致是这样的:

1. 运行在Windows Phone设备端的应用注册一个Push Notification Channel,获得一个唯一标识这个Channel的URI;

2. 将URI传回到开发者自己的服务器;

3. 当开发者需要发送Push Notification消息时,将规定格式的数据发送到之前获得的URI上;

4. 微软的推送服务器(MPNS)获得开发者发送的请求后,会通知到对应的Windows Phone设备上。

整个过程如下图所示:

OpenXLive Push Notification Hosting服务开发指南

在整个过程中,对于开发者来说,有一个难点很难克服——必须有自己的服务器,否则无法接收从Windows Phone应用中发送过来的URI。这个问题对于那些没有自己服务器的Windows Phone开发者来说,他们只能放弃在自己的应用中加入Push Notification的功能。

OpenXLive为了解决这个问题,为开发者提供了Push Notification Hosting服务(OpenXLive Push Notification Hosting Server,简称OPNHS),允许开发者将OpenXLive的服务器作为自己的Push Notification服务器。只要开发者调用OpenXLive SDK中的API,就可以让OpenXLive的服务器来保存URI,当开发者需要发送Push Notification消息时,只需要登录OpenXLive开发者后台就可以发送了。

Silverlight应用中添加Push Notification

接下来,我们以Silverlight for Windows Phone应用为例,看看如何使用OpenXLive Push Notification Hosting功能,向 Silverlight应用发送三种不同的Push Notification。

1. 添加OpenXLive功能

首先,我们要为创建好的Silverlight应用添加OpenXLive引用。如果没有安装OpenXLive SDK的话,请在下面的链接中下载SDK。请注意,只有在0.9.8及其以上版本中,才包含OpenXLive Push Notification Hosting功能。

http://developer.openxlive.net/sdk/download/

如果您已经安装了OpenXLive SDK,可以在安装路径(默认为C:\Program Files (x86)\Fulcrum Mobile Networks, Inc\OpenXLiveSDK\Bin\Silverlight)下找到OpenXLive.dll和OpenXLive.Silverlight.dll。

找到这两个DLL后,我们需要将其拷贝到Silverlight应用的目录下,否则会产生一个访问异常。

在Visual Studio的Solution Explorer中,选择Add References,添加OpenXLive.dll和OpenXLive.Silverlight.dll的引用。

OpenXLive Push Notification Hosting服务开发指南

然后,打开App.xaml.cs文件,添加下面的代码:

using OpenXLive;

using OpenXLive.Features;

private void Application_Launching(object sender, LaunchingEventArgs e)

{

if (XLiveGameManager.CurrentSession == null)

{

GameSession session = XLiveGameManager.CreateSession("enMQ3rEC5jsw8XygdFHuGpfk");

session.CreateSessionCompleted += new AsyncEventHandler(session_CreateSessionCompleted);

session.Open();

}

}

void session_CreateSessionCompleted(object sender, AsyncEventArgs e)

{

AsyncProcessResult result = e.Result;

if (!result.ReturnValue)

{

// TODO: Error Handler

}

}

private void Application_Activated(object sender, ActivatedEventArgs e)

{

XLiveGameManager.Activated();

}

private void Application_Deactivated(object sender, DeactivatedEventArgs e)

{

XLiveGameManager.Deactivated();

}

private void Application_Closing(object sender, ClosingEventArgs e)

{

if (XLiveGameManager.CurrentSession != null)

{

XLiveGameManager.CurrentSession.Close();

}

}

代码具体的解释可以参考《在Windows Phone应用中添加OpenXLive数据分析功能》,链接如下:http://www.cnblogs.com/aawolf/archive/2011/10/03/2198607.html

当OpenXLive的引用和功能调用添加完成后,我们就可以添加Push Notification代码了。

2. 发送Tile Notification

为了保证足够的灵活性,所以,开发者仍然调用Push Notification的API来注册Push Notification的Channel。我们首先来演示,如何创建并发送Tile Notification。关于Tile Notification的详细信息,可以参考MSDN上的文章:

http://msdn.microsoft.com/en-us/library/hh202970(VS.92).aspx

在Visual Studio中打开MainPage.xaml,添加三个ToggleSwitch控件,分别对应三种不同的Notification类型,选中控件添加Checked事件处理函数,然后进入代码编辑界面,添加如下的代码来创建Push Notification的Channel。

首先在MainPage.xaml.cs文件的顶部,添加引用:

using Microsoft.Phone.Notification;

using OpenXLive;

接下来,在与Tile Notification对应的ToggleSwitch控件Checked事件中,添加创建Push Notification Channel的代码:

// The name of our push channel.

string channelName = "OpenXLivePushNotificationHostingChannel";

private void toggleSwitchTile_Checked(object sender, RoutedEventArgs e)

{

// Try to find the push channel.

HttpNotificationChannel pushChannel = HttpNotificationChannel.Find(channelName);

// If the channel was not found, then create a new connection to the push service.

if (pushChannel == null)

{

pushChannel = new HttpNotificationChannel(channelName);

// Register for all the events before attempting to open the channel.

pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);

pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);

pushChannel.Open();

// Bind this new channel for Tile events.

if (pushChannel != null && !pushChannel.IsShellTileBound)

{

var allowedDomains = new Collection<Uri> { new Uri("http://picture.openxlive.com/") };

pushChannel.BindToShellTile(allowedDomains);

}

}

else

{

// The channel was already open, so just register for all the events.

pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);

pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);

}

RegisterNotificationUri(pushChannel.ChannelUri);

}

创建Push Notification Channel的代码与MSDN上的一致,三种不同的Notification在创建时其实是一样的,只是在创建之后进行了不同的操作,所以才会分成不同的Notification。比如,Tile Notification就需要在创建后,调用BindToShellTile方法,将其绑定到Tile上;在关闭Notification Channel前,还要记得调用UnbindToShellTile方法,解除绑定。

特别要强调的是,如果您的背景图片是放在OpenXLive服务器上的话,需要在调用BindToShellTile方法之前,首先将OpenXLive的图片服务器(picture.openxlive.com)添加到允许访问的域名列表中。当然,如果您的图片来自其他域名的服务器,您也要将对应的域名加入这个列表中。

接下来,我们来看将Notification Channel的Uri注册到OpenXLive服务器上的代码:

private void RegisterNotificationUri(Uri uri)

{

// Send Channel Uri to OpenXLive Hosting Server

if (OpenXLive.XLiveGameManager.CurrentSession != null

&&

OpenXLive.XLiveGameManager.CurrentSession.IsValid

&&

uri != null)

{

OpenXLive.XLiveGameManager.CurrentSession.RegistNotificationUriCompleted

+= new OpenXLive.Features.AsyncEventHandler(CurrentSession_RegistNotificationUriCompleted);

OpenXLive.XLiveGameManager.CurrentSession.RegisterNotificationUri(uri);

}

}

void CurrentSession_RegistNotificationUriCompleted(object sender, OpenXLive.AsyncEventArgs e)

{

OpenXLive.Features.AsyncProcessResult result = e.Result;

if (result.ReturnValue)

{

Debug.WriteLine("Channel Uri has been send to OpenXLive Hosting Server");

}

else

{

Debug.WriteLine(result.ErrorMessage);

}

}

调用OpenXLive Push Notification Hosting的方法非常简单,首先判断一下XLiveGameManager对象中CurrentSession属性中的GameSession对象是否有效,如果有效则首先添加RegistNotificationUriCompleted事件处理方法,然后调用GameSession的RegisterNotificationUri方法,将Push Notification Channel的Uri传递到OpenXLive Notification Hosting服务器(OPNHS)上即可。OPNHS没有提供解除绑定的方法,因为Notification Channel在解除绑定后会自动失效,OPNHS会将失效的Uri自动抛弃,所以客户端引用就没有必要解除绑定了。

还有两个需要提示的***实践:因为Push Notification Channel的注册需要GameSession有效,所以,在XLiveGameManager的CreateSession方法的CreateSessionCompleted事件处理函数中创建Push Notification Channel,并将其注册到OPNHS中,是最为安全的。

另外,由于HttpNotificationChannel创建Notification Channel本身也是一个异步调用,在某些情况下,如果我们在创建Notification Channel之后,马上注册到OPNHS上,Uri可能为空。所以,我们必须在HttpNotificationChannel的ChannelUriUpdated事件处理函数中增加注册代码,防止注册处理被漏掉。

好了,接下来看一下HttpNotificationChannel的ChannelUriUpdated事件处理函数的代码:

void PushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)

{

if (e.ChannelUri != null)

{

RegisterNotificationUri(e.ChannelUri);

}

Dispatcher.BeginInvoke(() =>

{

// Display the new URI for testing purposes. Normally, the URI would be passed back to your web service at this point.

System.Diagnostics.Debug.WriteLine(e.ChannelUri.ToString());

});

}

虽然有一些Push Notification Channel创建的代码没有完整展示,这部分代码不影响OPNHS的使用,您可以在示例代码中看到完整的代码。

好了,到这里,我们就完成了客户端的代码工作,接下来就可以看一下运行的效果了。在客户端代码运行前,您必须确认已经在OpenXLive的开发者网站上创建了OpenXLive的游戏/应用,并且已经取得了有效的API Secrecy Key,具体的做法您可以参考《在开发者网站上创建OpenXLive游戏》:

http://wiki.openxlive.net/Tutorial-4-Create-OpenXLive-Game-in-website.ashx

客户端程序开始运行之后,我们会看到下面的界面,并打开Tile Notification对应的ToggleSwitch控件:

OpenXLive Push Notification Hosting服务开发指南

然后点击模拟器上的Windows键,回到主界面,并切换到应用程序列表界面,将我们的示例程序pin到主界面上来显示:

 OpenXLive Push Notification Hosting服务开发指南OpenXLive Push Notification Hosting服务开发指南

好了,我们现在已经打开了Tile Notification的Channel,并且将其注册到了OPNHS上,而且把应用程序的Tile pin到主界面上。客户端的工作就完成了。

作为开发者,想向客户端发送Tile Notification的时候,只需要登录到OpenXLive的开发者网站,在开发者后台的控制面板中选择对应的游戏/应用,然后在右侧的功能选项中,选择“推送通知”(Push Notification),在二级菜单中,选择“Tile推送通知”,我们会看到如下界面:

OpenXLive Push Notification Hosting服务开发指南

Tile Notification一共能够传递六个参数,分为两组。前景部分,是标题(Title)、数字(Count)和前景图片(BackgroundImage),需要指出的是,数字的现实范围是0-99之间的整形数字;而背景组,是背景标题(BackTitle)、内容(BackContent)和背景图片(BackBackgroundImage)。Tile显示的布局与基本样式无法修改,如下图所示:

OpenXLive Push Notification Hosting服务开发指南

背景图片即可以是应用程序内部的资源图片,也可以是来自网络的图片。所以,OpenXLive的服务器也提供了图片上传的功能,开发者可以将Tile图片上传至OpenXLive服务器,然后再推送至Windows Phone手机。

如果使用应用程序内部的资源图片,在BackgroundImage栏输入图片在xap包中的相对路径即可。将图片添加到程序中作为背景图片,可以按以下步骤操作:

1. 右键项目,单击 添加,然后再单击 添加现有项

2. 选中要添加的图片,单击 打开

3. 鼠标右键单击添加的图片,然后选择 

4. 找到 属性 对话框中的 生成操作 属性,并设置为 

5. 将 复制到输出目录 设置为 如果较新则复

发送Tile Notification 时,要使用该图片只需在BackgroundImage栏输入图片名称(包括后缀名)即可。如果图片不在根目录下则输入 Folder/Image.jpg。

目前OPNHS的功能相对简单,每次发送Push Notification时,开发者只能登录OpenXLive服务器,手工发送,还没有实现定时发送的功能。复杂功能会随着开发者的要求,在后续的版本中逐步实现。

好了,当您填写好Tile Notification的内容后,点击“发送”按钮。在Windows Phone的主界面上,您很快就可以看到推送过来的Tile内容了。

OpenXLive Push Notification Hosting服务开发指南

3. 发送Toast Notification

第二个推送通知类型是Toast Notification,当程序运行在后台时,Toast Notification会在屏幕的最上端显示一个提示条,和来短信、发现无线网络的系统提示一致。Toast Notification一般用在需要唤醒应用程序的时候,比如应用程序现在有新的内容等。

需要指出的是,每个应用程序最多支持打开一个Notification Channel,在示例程序中,我们并没有做几个Notification Channel的互斥,打开一个新的Channel前,应该关闭另外的Channel,否则会引发异常。

我们先来看一下表示Toast的ToggleSwitch控件的Checked和Unchecked事件处理函数:

private void toggleSwitchToast_Checked(object sender, RoutedEventArgs e)

{

// Try to find the push channel.

HttpNotificationChannel pushChannel = HttpNotificationChannel.Find(ToastChannelName);

// If the channel was not found, then create a new connection to the push service.

if (pushChannel == null)

{

pushChannel = new HttpNotificationChannel(ToastChannelName);

// Register for all the events before attempting to open the channel.

pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);

pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);

// Register for this notification only if you need to receive the notifications while your application is running.

pushChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(PushChannel_ShellToastNotificationReceived);

pushChannel.Open();

// Bind this new channel for Tile events.

pushChannel.BindToShellToast();

}

else

{

// The channel was already open, so just register for all the events.

pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);

pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);

// Register for this notification only if you need to receive the notifications while your application is running.

pushChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(PushChannel_ShellToastNotificationReceived);

}

// Send Channel Uri to OpenXLive Hosting Server

RegisterNotificationUri(pushChannel.ChannelUri);

}

private void toggleSwitchToast_Unchecked(object sender, RoutedEventArgs e)

{

// Try to find the push channel.

HttpNotificationChannel pushChannel = HttpNotificationChannel.Find(ToastChannelName);

if (pushChannel != null)

{

pushChannel.UnbindToShellToast();

// Remove push notification channel

pushChannel.Close();

}

}

大部分代码与之前的Tile Notification相同,只是增加了Notification Channel的ShellToastNotificationReceived事件处理函数,并且调用BindToShellToast方法,将Notification Channel绑定到Toast上。

接下来,我们要处理两种情况:第一种,接收到Toast Notification时,应用程序正在运行;第二种,接收到Toast Notification时,应用程序在后台。当程序运行在后台时,Toast提示条会显示,当用户点击时,会跳转到Toast Notification中包括的命令行所指定的应用程序页面中。如果应用在前台,我们就要处理Notification Channel的ShellToastNotificationReceived事件处理函数,代码如下:

void PushChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)

{

StringBuilder message = new StringBuilder();

string relativeUri = string.Empty;

message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString());

// Parse out the information that was part of the message.

foreach (string key in e.Collection.Keys)

{

message.AppendFormat("{0}: {1}\n", key, e.Collection[key]);

if (string.Compare(

key,

"wp:Param",

System.Globalization.CultureInfo.InvariantCulture,

System.Globalization.CompareOptions.IgnoreCase) == 0)

{

relativeUri = e.Collection[key];

}

}

// Display a dialog of all the fields in the toast.

Dispatcher.BeginInvoke(() => MessageBox.Show(message.ToString()));

}

为了处理第二种情况,我们要创建一个新的页面,命名为Page2.xaml。我们要在Page2的OnNavigatedTo方法中增加一段代码,以显示导航来源是哪里:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)

{

base.OnNavigatedTo(e);

textBlockFrom.Text = "Navigated here from " + this.NavigationContext.QueryString["NavigatedFrom"];

}

好了,到这里,我们客户端的代码写完了。我们运行代码示例,并且打开Toast Notification的开关,然后将应用切换到后台。

然后,我们打开OpenXLive的开发者后台,切换至“推送消息”界面的“Toast推送消息”中。界面截图如下:

OpenXLive Push Notification Hosting服务开发指南

Toast Notification有三个参数:Text1,是Toast消息的标题;Text2,是副标题;Param,是需要传递给应用程序的命令行参数,所以必须保证这个参数能够被应用程序解析,否则会引起应用程序崩溃,如果不填,则默认打开应用程序的主界面。

好了,接下来看运行效果如何了。当应用程序在后台的情况下,首先会显示Toast提示条,点击提示条后,会进入命令行指定的应用程序页面。

 OpenXLive Push Notification Hosting服务开发指南OpenXLive Push Notification Hosting服务开发指南

在应用程序运行在前台的情况下,我们会用一个MessageBox来显示收到的消息:

OpenXLive Push Notification Hosting服务开发指南

好了,我们完成了第二个Toast Notification的全部工作。

4. 发送Raw Notification

Raw Notification是三种推送通知中用的比较少的一种,因为Raw Notification只有在应用程序在前台的情况下才有用。在这种情况下,一般的开发者会倾向于使用自己更加能够掌控的Pull方式,而不是由服务器端发起的Push方式。无所谓了,反正对于Raw Notification,我们是要介绍的。

首先还是客户端的代码,已经是轻车熟路了:

private void toggleSwitchRaw_Checked(object sender, RoutedEventArgs e)

{

// Try to find the push channel.

HttpNotificationChannel pushChannel = HttpNotificationChannel.Find(RawChannelName);

// If the channel was not found, then create a new connection to the push service.

if (pushChannel == null)

{

pushChannel = new HttpNotificationChannel(RawChannelName);

// Register for all the events before attempting to open the channel.

pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);

pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);

pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);

pushChannel.Open();

}

else

{

// The channel was already open, so just register for all the events.

pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);

pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);

pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);

// Display the URI for testing purposes. Normally, the URI would be passed back to your web service at this point.

System.Diagnostics.Debug.WriteLine(pushChannel.ChannelUri.ToString());

MessageBox.Show(String.Format("Channel Uri is {0}",

pushChannel.ChannelUri.ToString()));

}

// Send Channel Uri to OpenXLive Hosting Server

RegisterNotificationUri(pushChannel.ChannelUri);

}

void PushChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)

{

string message;

using (System.IO.StreamReader reader = new System.IO.StreamReader(e.Notification.Body))

{

message = reader.ReadToEnd();

}

Dispatcher.BeginInvoke(() =>

MessageBox.Show(String.Format("Received Notification {0}:\n{1}",

DateTime.Now.ToShortTimeString(), message))

);

}

private void toggleSwitchRaw_Unchecked(object sender, RoutedEventArgs e)

{

// Try to find the push channel.

HttpNotificationChannel pushChannel = HttpNotificationChannel.Find(RawChannelName);

// If the channel was not found, then create a new connection to the push service.

if (pushChannel != null)

{

pushChannel.Close();

}

}

唯一需要多说的是,增加了Notification Channel的HttpNotificationReceived事件处理方法,我们从e.Notification.Body中获取到发送的Raw消息,然后使用StreamReader将其读取为文本,还可以继续进行进一步的处理。

运行客户端程序,打开Raw Notification的选项,将应用程序保持在运行状态。登录OpenXLive开发者后台,“推送消息”界面的“Raw推送消息”中,将想要发送的文本粘贴到文本框中,点击“发送”按钮。

手机客户端的运行效果如下:

OpenXLive Push Notification Hosting服务开发指南

好了,到这里,我们就将OpenXLive Push Notification Hosting Server(OPNHS)的功能,如何发送三种Push Notification,以及在Silverlight for Windows Phone应用中如何创建Notification Channel、注册到OPNHS中和接收推送通知等。

XNA游戏中添加Push Notification

接下来,我们会介绍,如何在XNA游戏中实现与Silverlight应用中相同的功能。其实,XNA中绝大部分功能与Silverlight类似,只是XNA是一个事件驱动的应用程序框架,而Silverlight是事件驱动,所以在选择创建Notification Channel的时间点上略有差异。

1. 添加OpenXLive功能

首先,我们还是首先添加OpenXLive的引用,在OpenXLive SDK的安装路径(默认为C:\Program Files (x86)\Fulcrum Mobile Networks, Inc\OpenXLiveSDK\Bin\XNA)下找到OpenXLive.dll和OpenXLive.Form.dll。这两个DLL是在XNA程序中使用的。

XNA游戏中,我们必须首先在Solution Explorer中打开Properties目录下的WMAppManifest.xml文件,找到下面这句代码,Publisher的名字不能为空,否则无法正确获得Push Notification的消息:

<App xmlns="" ProductID="{aee39b6f-5faf-41e6-a992-5055fdf3a13e}" Title="PushDemoXNA" RuntimeType="XNA" Version="1.0.0.0" Genre="Apps.Normal" Author="" Description="" Publisher="OpenXLive">

我们打开Game1.cs文件,首先,在文件顶部添加引用:

using OpenXLive;

using OpenXLive.Features;

using OpenXLive.Forms;

using Microsoft.Phone.Notification;

然后,声明一个XLiveFormManger变量,该对象主要是用来控制XNA中所有的UI Framework,如果不需要显示OpenXLive的XNA UI,该变量也可以不加:

XLiveFormManager manager;

接下来,定位到Initialize方法,接下来添加下面的代码:

protected override void Initialize()

{

// TODO: Add your initialization logic here

if (XLiveGameManager.CurrentSession == null)

{

GameSession session = XLiveGameManager.CreateSession("enMQ3rEC5jsw8XygdFHuGpfk");

session.CreateSessionCompleted += new AsyncEventHandler(session_CreateSessionCompleted);

manager = new XLiveFormManager(this, session);

session.Open();

Components.Add(manager);

}

base.Initialize();

}

在OpenXLive SDK 0.9.8及以上版本中,我们修改了创建XNA UI框架的方法,您可以先创建GameSession对象,然后再将GameSession对象传递给XLiveFormManger,这样可以保证Silverlight和XNA调用方式的基本一致。如果您的游戏中只适用了OpenXLive的逻辑代码,而没有使用UI代码的话,也可以不必创建XLiveFormManger对象。但是,调用GameSession的Open方法是必须的。然后,将XLiveFormManger对象作为Game Compoent添加到系统中,也能够保证OpenXLive的XNA UI系统能够被系统释放掉。

好了,短短几句话,我们就可以将OpenXLive加入到我们的XNA游戏中了。接下来,我们就要在GameSession创建成功的事件处理函数中添加Push Notification的代码了。

void session_CreateSessionCompleted(object sender, AsyncEventArgs e)

{

AsyncProcessResult result = e.Result;

if (result.ReturnValue)

{

// TODO: Error Handler

CreateNotificationChannel();

}

}
2. 发送Tile Notification

由于XNA的UI控制代码写起来比较费事,所以,我们就在这里简化了调用流程,每次运行程序,只能创建一种Push Notification,代码如下:

private void CreateNotificationChannel()

{

CreateTileNotification();

//CreateToastNotification();

//CreateRawNotification();

}

而创建Notification Channel的代码与Silverlight版本是一模一样的:

private void CreateTileNotification()

{

if (XLiveGameManager.CurrentSession != null && XLiveGameManager.CurrentSession.IsValid)

{

// Try to find the push channel.

HttpNotificationChannel pushChannel = HttpNotificationChannel.Find(TileChannelName);

// If the channel was not found, then create a new connection to the push service.

if (pushChannel == null)

{

pushChannel = new HttpNotificationChannel(TileChannelName);

// Register for all the events before attempting to open the channel.

pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);

pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);

pushChannel.Open();

// Bind this new channel for Tile events.

if (pushChannel != null && !pushChannel.IsShellTileBound)

{

var allowedDomains = new Collection<Uri> { new Uri("http://picture.openxlive.com/") };

pushChannel.BindToShellTile(allowedDomains);

}

}

else

{

// The channel was already open, so just register for all the events.

pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);

pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);

}

RegisterNotificationUri(pushChannel.ChannelUri);

}

}

void PushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)

{

if (e.ChannelUri != null)

{

RegisterNotificationUri(e.ChannelUri);

}

// Display the new URI for testing purposes. Normally, the URI would be passed back to your web service at this point.

System.Diagnostics.Debug.WriteLine(e.ChannelUri.ToString());

}

void PushChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)

{

// Error handling logic for your particular application would be here.

MessageBox.Show(String.Format("A push notification {0} error occurred. {1} ({2}) {3}",

e.ErrorType, e.Message, e.ErrorCode, e.ErrorAdditionalData));

}

需要提示的是,这里的MessageBox是OpenXLive封装的MessageBox,用法和Silverlight中系统提供的一致。

最后,也是最核心的代码是注册Uri的部分代码:

private void RegisterNotificationUri(Uri uri)

{

// Send Channel Uri to OpenXLive Hosting Server

if (OpenXLive.XLiveGameManager.CurrentSession != null

&&

OpenXLive.XLiveGameManager.CurrentSession.IsValid

&&

uri != null)

{

OpenXLive.XLiveGameManager.CurrentSession.RegistNotificationUriCompleted

+= new OpenXLive.Features.AsyncEventHandler(CurrentSession_RegistNotificationUriCompleted);

OpenXLive.XLiveGameManager.CurrentSession.RegisterNotificationUri(uri);

}

}

void CurrentSession_RegistNotificationUriCompleted(object sender, OpenXLive.AsyncEventArgs e)

{

OpenXLive.Features.AsyncProcessResult result = e.Result;

if (result.ReturnValue)

{

Debug.WriteLine("Channel Uri has been send to OpenXLive Hosting Server");

}

else

{

Debug.WriteLine(result.ErrorMessage);

}

}

好了,我们运行程序,然后将程序切换到后台,将游戏图标pin到主界面上,最后发送Tile Notification的效果如下:

OpenXLive Push Notification Hosting服务开发指南

3. 发送Toast Notification

发送Toast Notification的代码如下:

private void CreateToastNotification()

{

// Try to find the push channel.

HttpNotificationChannel pushChannel = HttpNotificationChannel.Find(ToastChannelName);

// If the channel was not found, then create a new connection to the push service.

if (pushChannel == null)

{

pushChannel = new HttpNotificationChannel(ToastChannelName);

// Register for all the events before attempting to open the channel.

pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);

pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);

// Register for this notification only if you need to receive the notifications while your application is running.

pushChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(PushChannel_ShellToastNotificationReceived);

pushChannel.Open();

// Bind this new channel for Tile events.

pushChannel.BindToShellToast();

}

else

{

// The channel was already open, so just register for all the events.

pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);

pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);

// Register for this notification only if you need to receive the notifications while your application is running.

pushChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(PushChannel_ShellToastNotificationReceived);

}

// Send Channel Uri to OpenXLive Hosting Server

RegisterNotificationUri(pushChannel.ChannelUri);

}

如果发送Toast Notification时,XNA游戏在运行,会调用下面的ShellToastNotificationReceived事件处理函数,显示MessageBox:

void PushChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)

{

StringBuilder message = new StringBuilder();

string relativeUri = string.Empty;

message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString());

// Parse out the information that was part of the message.

foreach (string key in e.Collection.Keys)

{

message.AppendFormat("{0}: {1}\n", key, e.Collection[key]);

if (string.Compare(

key,

"wp:Param",

System.Globalization.CultureInfo.InvariantCulture,

System.Globalization.CompareOptions.IgnoreCase) == 0)

{

relativeUri = e.Collection[key];

}

}

// Display a dialog of all the fields in the toast.

MessageBox.Show(message.ToString());

}

需要特别提示的是,在XNA游戏中,命令行是无效的,如果添加一个无效的命令行参数,会造成程序崩溃,建议将命令行设为空即可。OpenXLive服务器发送Toast Notification后,运行效果如下:

OpenXLive Push Notification Hosting服务开发指南

4. 发送Raw Notification

最后是Raw Notification,代码如下:

private void CreateRawNotification()

{

// Try to find the push channel.

HttpNotificationChannel pushChannel = HttpNotificationChannel.Find(RawChannelName);

// If the channel was not found, then create a new connection to the push service.

if (pushChannel == null)

{

pushChannel = new HttpNotificationChannel(RawChannelName);

// Register for all the events before attempting to open the channel.

pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);

pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);

pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);

pushChannel.Open();

}

else

{

// The channel was already open, so just register for all the events.

pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);

pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);

pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);

// Display the URI for testing purposes. Normally, the URI would be passed back to your web service at this point.

System.Diagnostics.Debug.WriteLine(pushChannel.ChannelUri.ToString());

MessageBox.Show(String.Format("Channel Uri is {0}",

pushChannel.ChannelUri.ToString()));

}

// Send Channel Uri to OpenXLive Hosting Server

RegisterNotificationUri(pushChannel.ChannelUri);

}

void PushChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)

{

string message;

using (System.IO.StreamReader reader = new System.IO.StreamReader(e.Notification.Body))

{

message = reader.ReadToEnd();

}

MessageBox.Show(String.Format("Received Notification {0}:\n{1}",

DateTime.Now.ToShortTimeString(), message)

);

}

运行效果如下:

OpenXLive Push Notification Hosting服务开发指南

写在最后

到这里,我们就介绍了OpenXLive Push Notification Hosting Server的全部功能,需要指出的是,OpenXLive并没有提供自己的Push Notification服务,我们仍旧使用微软提供的Push Notification机制。OpenXLive Push Notification Hosting Server只是帮助那些没有服务器、又希望能够使用Push Notification服务的开发者,来管理Push Notification Channel,给他们一个友好的Web界面,供他们来发送自己的Push Notification消息。

如果您还有任何的疑问,或者需要更详细的帮助,欢迎您访问OpenXLive的官方网站

英文版:http://www.openxlive.com/

中文版:http://www.openxlive.net/

中文论坛:http://bbs.openxlive.com/


本文转自马宁博客园博客,原文链接:http://www.cnblogs.com/aawolf/archive/2012/05/16/2505146.html,如需转载请自行联系原作者