重新想象 Windows 8 Store Apps (67) - 后台任务: 推送通知
作者:webabcd
介绍
重新想象 Windows 8 Store Apps 之 后台任务
- 推送通知
示例
1、客户端
BackgroundTask/PushNotification.xaml
<Page
x:Class="XamlDemo.BackgroundTask.PushNotification"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XamlDemo.BackgroundTask"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Grid Background="Transparent">
<StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" /> <Button Name="btnCreateChannel" Content="create the channel" Margin="0 10 0 0" Click="btnCreateChannel_Click" /> <TextBox Name="txtUri" Margin="0 10 10 0" /> <Image Source="wns.png" Margin="0 10 0 0" HorizontalAlignment="Left" Width="800" /> </StackPanel>
</Grid>
</Page>
BackgroundTask/PushNotification.xaml.cs
/*
* 演示如何接收推送通知
*
* 注:
* 需要在 Package.appxmanifest 中增加后台任务声明,并勾选“推送通知”
* 在 win8 商店创建了应用后,需要将此 app 的商店中的 identity 复制到 Package.appxmanifest 的 identity 节点
* 不能在模拟器中运行
* 每次新建的 channel 有效期为 30 天
*
* 另:
* WNS - Windows Push Notification Service
* 推送通知的服务端参见:WebServer/PushNotification 内的文件
*/ using System;
using Windows.ApplicationModel.Background;
using Windows.Networking.PushNotifications;
using Windows.UI.Notifications;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; namespace XamlDemo.BackgroundTask
{
public sealed partial class PushNotification : Page
{
public PushNotification()
{
this.InitializeComponent();
} private async void btnCreateChannel_Click(object sender, RoutedEventArgs e)
{
// 当收到推送的 raw 通知时,如果 app 在锁屏,则可以触发后台任务以执行相关的逻辑(PushNotificationTrigger)
BackgroundAccessStatus status = BackgroundExecutionManager.GetAccessStatus();
if (status == BackgroundAccessStatus.Unspecified)
{
status = await BackgroundExecutionManager.RequestAccessAsync();
}
if (status == BackgroundAccessStatus.Denied)
{
await new MessageDialog("请先将此 app 添加到锁屏").ShowAsync();
return;
} // 创建一个推送通知信道,每个新建的 channel 有效期为 30 天,所以建议每次进入 app 后都重新建一个 channel(但是需要注意间隔较短的话,则会复用之前的 channel)
PushNotificationChannel channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
// 接收到通知后所触发的事件
channel.PushNotificationReceived += channel_PushNotificationReceived; // channel.Close(); // 关闭 channel
// channel.ExpirationTime; // channel 的过期时间,此时间过后 channel 则失效 // channel 的 uri 地址,服务端通过此 uri 向此 app 推送通知
txtUri.Text = channel.Uri.ToString();
} void channel_PushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs args)
{
switch (args.NotificationType)
{
case PushNotificationType.Badge: // badge 通知
BadgeUpdateManager.CreateBadgeUpdaterForApplication().Update(args.BadgeNotification);
break;
case PushNotificationType.Raw: // raw 通知
// 当收到推送的 raw 通知时,如果 app 在锁屏,则可以触发后台任务以执行相关的逻辑(PushNotificationTrigger)
string msg = args.RawNotification.Content;
break;
case PushNotificationType.Tile: // tile 通知
TileUpdateManager.CreateTileUpdaterForApplication().Update(args.TileNotification);
break;
case PushNotificationType.Toast: // toast 通知
ToastNotificationManager.CreateToastNotifier().Show(args.ToastNotification);
break;
default:
break;
} args.Cancel = true;
}
}
}
Package.appxmanifest
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
<!--以下借用“贪吃的蛇”的 Identity,以便演示推送通知-->
<!--Identity Name="10437webabcd.173815756DD78" Publisher="CN=27514DEC-C708-4EDB-BFEA-F956384483D0" Version="1.0.0.0" /-->
<Identity Name="webabcd.win8.XamlDemo" Publisher="CN=wanglei" Version="1.0.0.0" />
</Package>
2、服务端
WebServer/PushNotification/OAuthToken.cs
/*
* 用于反序列化从 https://login.live.com/accesstoken.srf 获取到的结果
*/ using System.Runtime.Serialization; namespace WebServer.PushNotification
{
[DataContract]
public class OAuthToken
{
[DataMember(Name = "access_token")]
public string AccessToken { get; set; }
[DataMember(Name = "token_type")]
public string TokenType { get; set; }
}
}
WebServer/PushNotification/OAuthHelper.cs
/*
* https://login.live.com/accesstoken.srf 的 OAuth 验证的帮助类
*/ using System;
using System.IO;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Text; namespace WebServer.PushNotification
{
public class OAuthHelper
{
/// <summary>
/// 获取 https://login.live.com/accesstoken.srf 的 OAuth 验证的 access-token
/// </summary>
/// <param name="secret">在 win8 商店创建 app 后获取到的 “客户端密钥”</param>
/// <param name="sid">在 win8 商店创建 app 后获取到的 “程序包安全标识符(SID)”</param>
/// <returns></returns>
public OAuthToken GetAccessToken(string secret, string sid)
{
var urlEncodedSecret = UrlEncode(secret);
var urlEncodedSid = UrlEncode(sid);
var body = String.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=notify.windows.com",
urlEncodedSid,
urlEncodedSecret); string response;
using (WebClient client = new WebClient())
{
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
response = client.UploadString("https://login.live.com/accesstoken.srf", body);
}
return GetOAuthTokenFromJson(response);
} private OAuthToken GetOAuthTokenFromJson(string jsonString)
{
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
{
var ser = new DataContractJsonSerializer(typeof(OAuthToken));
var oAuthToken = (OAuthToken)ser.ReadObject(ms);
return oAuthToken;
}
} private static string UrlEncode(string str)
{
StringBuilder sb = new StringBuilder();
byte[] byStr = System.Text.Encoding.UTF8.GetBytes(str);
for (int i = ; i < byStr.Length; i++)
{
sb.Append(@"%" + Convert.ToString(byStr[i], ));
} return (sb.ToString());
}
}
}
WebServer/PushNotification/Push.aspx.cs
/*
* 演示如何向 app 推送通知
*
* 注:
* 关于推送通知服务请求和响应头的详细说明参见:http://msdn.microsoft.com/zh-cn/library/windows/apps/hh465435.aspx
*/ using System;
using System.IO;
using System.Net;
using System.Text; namespace WebServer.PushNotification
{
public partial class Push : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// 向某个 app 推送通知的 channel 地址
string notifyUrl = "https://sin.notify.windows.com/?token=AgYAAABQnraWSMQXRveiofxSXGKMHaPB84FLMhFa3D6TQZRHzRSPeByl%2f1O%2frPAcc3ipjpT2cQXfivh589zEV8AOYkR%2fLwXoT2esZnC3hS%2fN7q94ZzJFLnpQsDsYNolFiEAhbHQ%3d"; // 在 win8 商店创建 app 后获取到的 “程序包安全标识符(SID)”
string sid = "ms-app://s-1-15-2-1530173461-470787880-3155417234-2904423500-2475821181-4070965884-3773336209";
// 在 win8 商店创建 app 后获取到的 “客户端密钥”
string secret = "bs08Acs1RG7jB7pkGVMh8EmGKCG3pH+3"; OAuthHelper oAuth = new OAuthHelper();
OAuthToken token = oAuth.GetAccessToken(secret, sid); try
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(notifyUrl); // toast, tile, badge 为 text/xml; raw 为 application/octet-stream
myRequest.ContentType = "text/xml";
// 推送消息的类型:wns/toast | wns/badge | wns/tile | wns/raw
myRequest.Headers.Add("X-WNS-Type", "wns/toast");
// 设置 access-token
myRequest.Headers.Add("Authorization", String.Format("Bearer {0}", token.AccessToken)); // 注:app 通过 toast 激活后可以通过 OnLaunched() 中的 args.Arguments 来获取此处 launch 指定的值
string toastMessage = "<toast launch='param'><visual version='1'><binding template='ToastText01'><text id='1'>推送通知:" + DateTime.Now.ToString("mm:ss") + "</text></binding></visual></toast>";
byte[] buffer = Encoding.UTF8.GetBytes(toastMessage); myRequest.ContentLength = buffer.Length;
myRequest.Method = "POST"; using (Stream stream = myRequest.GetRequestStream())
{
stream.Write(buffer, , buffer.Length);
} using (HttpWebResponse webResponse = (HttpWebResponse)myRequest.GetResponse())
{
/*
* 响应代码说明
* 200 - OK,WNS 已接收到通知
* 400 - 错误的请求
* 401 - 未授权,token 可能无效
* 403 - 已禁止,manifest 中的 identity 可能不对
* 404 - 未找到
* 405 - 方法不允许
* 406 - 无法接受
* 410 - 不存在,信道不存在或过期
* 413 - 请求实体太大,限制为 5000 字节
* 500 - 内部服务器错误
* 503 - 服务不可用
*/
Response.Write(webResponse.StatusCode.ToString()); //如果成功应该是返回 200 ok
}
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
}
}
}
OK
[源码下载]
重新想象 Windows 8 Store Apps (67) - 后台任务: 推送通知的更多相关文章
- 重新想象 Windows 8 Store Apps (64) - 后台任务: 开发一个简单的后台任务
[源码下载] 重新想象 Windows 8 Store Apps (64) - 后台任务: 开发一个简单的后台任务 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后 ...
- 重新想象 Windows 8 Store Apps (65) - 后台任务: 音乐的后台播放和控制
[源码下载] 重新想象 Windows 8 Store Apps (65) - 后台任务: 音乐的后台播放和控制 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台 ...
- 重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传
[源码下载] 重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台任务 后台 ...
- 重新想象 Windows 8 Store Apps (68) - 后台任务: 控制通道(ControlChannel)
[源码下载] 重新想象 Windows 8 Store Apps (68) - 后台任务: 控制通道(ControlChannel) 作者:webabcd 介绍重新想象 Windows 8 Store ...
- 重新想象 Windows 8 Store Apps 系列文章索引
[源码下载][重新想象 Windows 8.1 Store Apps 系列文章] 重新想象 Windows 8 Store Apps 系列文章索引 作者:webabcd 1.重新想象 Windows ...
- 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationContext, CoreDispatcher, ThreadLocal, ThreadStaticAttribute
[源码下载] 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationCont ...
- 重新想象 Windows 8 Store Apps (59) - 锁屏
[源码下载] 重新想象 Windows 8 Store Apps (59) - 锁屏 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 锁屏 登录锁屏,获取当前程序的锁 ...
- 重新想象 Windows 8 Store Apps (61) - 通信: http, oauth
[源码下载] 重新想象 Windows 8 Store Apps (61) - 通信: http, oauth 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通信 ...
- 重新想象 Windows 8 Store Apps (13) - 控件之 SemanticZoom
原文:重新想象 Windows 8 Store Apps (13) - 控件之 SemanticZoom [源码下载] 重新想象 Windows 8 Store Apps (13) - 控件之 Sem ...
随机推荐
- 同时大量连接导致的DDOS攻击,导致收发器宕机,用户大面积超时掉线
前段时间一个客户改成电信网通自动路由后(当然和这个没有关系,但是客户一般没有分析能力,会多想),用户经常大面积掉线,用户才180多个,在线最多也才120多,十分苦恼,原先帮其维护的技术人员,只是远程诊 ...
- arcgis ERROR:000824 该工具未获得许可
当时上面还说点击000824进入帮助文档,它说是由于扩展功能未勾选,于是我勾上,结果还是不行,后来它说可能是没有许可,于是我把license重新授权了一遍,结果,还是不行 其实,解决方法是在catal ...
- html5开发之viewport使用
随着高端手机(Andriod,Iphone,Ipod,WinPhone等)的盛行,移动互联应用开发也越来越受到人们的重视,用html5开发移动应用是最好的选择.然而,每一款手机有不同的分辨率,不同屏幕 ...
- 查询反模式 - GroupBy、HAVING的理解
为了最简单地说明问题,我特地设计了一张这样的表. 一.GROUP BY单值规则 规则1:单值规则,跟在SELECT后面的列表,对于每个分组来说,必须返回且仅仅返回一个值. 典型的表现就是跟在SELEC ...
- WPF之DataGrid
1.WPF 4 DataGrid 控件(基本功能篇) 基本使用,绑定数据展示 2.WPF 4 DataGrid 控件(自定义样式篇) 定义行,列,头,单元格等样式 3.WPF 4 DataGrid 控 ...
- Github的基本配置与使用
第一步:尝试创建SSH key ssh-keygen -t rsa -C xxxxx@gmail.com 默认在~/.ssh目录生成id_rsa与id_rsa.pub. -t代表密钥类型,常见的类型有 ...
- 那些年做过的 .NET Web 项目和 iOS 之路的一些思考
从2010年3月份出来工作到2015年初,做过的大大小小的 .NET Web 项目如下: (1)售楼系统产品 「Role: Team Member」 (2)中弘合同管理系统 「Role: ...
- HTTP 错误 500.19 - Internal Server Error(Windows Server 2012)
错误页面: 解决办法:重新添加角色和功能web服务器(IIS),选择应用程序开发下的相关.net4.5的选项
- Cobbler批量安装Ubuntu/CentOS系统
2013-07-25 一.安装和修改cobbler配置 1. Cobbler不在CentOS的基本源中,需要导入EPEL源升级软件包, 确保epel-release包的版本为最新,当前最新版本为 ...
- java nio 网络框架实现
maven项目 https://github.com/solq360/common 链式编/解码 链路层链式处理 管道管理socket 多协议处理非常方便 仿netty NioEventLoop 单线 ...