[源码下载]

背水一战 Windows 10 (121) - 后台任务: 推送通知

作者:webabcd

介绍
背水一战 Windows 10 之 后台任务

  • 推送通知

示例
演示如何接收推送通知
/WebApi/PushNotificationController.cs

/*
* 演示如何向 app 推送通知
* 由于本例没有上商店,所以本例是无法演示的,需要看演示效果的话运行一下自己写的“打字通”的 /TypingGame/PushNotification/Sample.xaml,然后用其生成的 channel 地址在 /WebApi/Controllers/PushNotificationController.cs 推送通知
*
*
* 注:
* 关于推送通知服务请求和响应头的详细说明参见:https://msdn.microsoft.com/zh-cn/library/windows/apps/hh465435.aspx
*/ using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Threading.Tasks; namespace WebApi.Controllers
{
public class PushNotificationController : ApiController
{
[HttpGet]
public async Task<HttpResponseMessage> Get()
{
// 向某个 app 推送通知的 channel 地址(通过客户端的 PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync() 方法生成)
string notifyUrl = "https://hk2.notify.windows.com/?token=AwYAAAANZzLsCX%2fl1aavCSQhi%2fdEBO5wdplj7S4a3o4t8wGSGo05hRE6VC7xEMCFtGDrVuV%2f9J2ItuVri1F4Z0YNjtbuCqf6LQvov0UE3%2flD1sP1poaS1Qp30UQ%2fWVKVUBCjPFuWFLuyuq7UuuTvJcCcQzey"; // 在商店后台的 dashboard 中的“Package SID”中可以找到此值(可以在 https://apps.dev.microsoft.com/ 中查找)
string sid = "ms-app://s-1-15-2-1792688850-3283391166-**********-**********-**********-1809961044-230289451";
// 在商店后台的 dashboard 中的“Application Secrets”中可以找到此值(可以在 https://apps.dev.microsoft.com/ 中查找)
string secret = "koghs4zz*************S+5sEoqoNb4"; OAuthHelper oAuth = new OAuthHelper();
OAuthToken token = oAuth.GetAccessToken(secret, sid); HttpResponseMessage result = null; try
{
HttpClient httpClient = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, notifyUrl); // 推送消息的类型:wns/toast | wns/badge | wns/tile | wns/raw
request.Headers.Add("X-WNS-Type", "wns/toast");
// 设置 access-token
request.Headers.Add("Authorization", String.Format("Bearer {0}", token.AccessToken)); // 需要推送的 toast 通知的内容
string toastXml = $@"
<toast activationType='foreground' launch='PushNotification-Toast-Arguments'>
<visual>
<binding template='ToastGeneric'>
<text>toast - title</text>
<text>toast - content {DateTime.Now.ToString("mm:ss")}</text>
</binding>
</visual>
</toast>"; // toast, tile, badge 为 text/xml; raw 为 application/octet-stream
request.Content = new StringContent(toastXml, Encoding.UTF8, "text/xml"); HttpResponseMessage response = await httpClient.SendAsync(request);
/*
* 响应代码说明
* 200 - OK,WNS 已接收到通知
* 400 - 错误的请求
* 401 - 未授权,token 可能无效
* 403 - 已禁止,manifest 中的 identity 可能不对
* 404 - 未找到
* 405 - 方法不允许
* 406 - 无法接受
* 410 - 不存在,信道不存在或过期
* 413 - 请求实体太大,限制为 5000 字节
* 500 - 内部服务器错误
* 503 - 服务不可用
*/
HttpStatusCode statusCode = response.StatusCode;
result = new HttpResponseMessage
{
Content = new StringContent(statusCode.ToString(), Encoding.UTF8, "text/html")
};
}
catch (Exception ex)
{
result = new HttpResponseMessage
{
Content = new StringContent(ex.ToString(), Encoding.UTF8, "text/html"),
StatusCode = HttpStatusCode.InternalServerError
};
} return result;
}
} /*
* 用于反序列化从 https://login.live.com/accesstoken.srf 获取到的结果
*/
[DataContract]
public class OAuthToken
{
[DataMember(Name = "access_token")]
public string AccessToken { get; set; }
[DataMember(Name = "token_type")]
public string TokenType { get; set; }
} /*
* 用于从 https://login.live.com/accesstoken.srf 做 OAuth 验证的帮助类
*/
public class OAuthHelper
{
/// <summary>
/// 获取 https://login.live.com/accesstoken.srf 的 OAuth 验证的 access-token
/// </summary>
/// <param name="secret">在商店后台的 dashboard 中的“Application Secrets”中可以找到此值(可以在 https://apps.dev.microsoft.com/ 中查找)</param>
/// <param name="sid">在商店后台的 dashboard 中的“Package SID”中可以找到此值(可以在 https://apps.dev.microsoft.com/ 中查找)</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());
}
}
}

BackgroundTask/PushNotification.xaml

<Page
x:Class="Windows10.BackgroundTask.PushNotification"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Windows10.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="10 0 10 10"> <TextBlock Name="lblMsg" Margin="5" /> <Button Name="btnCreateChannel" Content="create the channel" Margin="5" Click="btnCreateChannel_Click" /> <TextBox Name="txtUri" Margin="5" /> <TextBlock Margin="5">
<Run>1、应用为推送通知通道向通知客户端平台发送请求。</Run>
<LineBreak />
<Run>2、通知客户端平台要求 WNS 创建通知通道。此通道以统一资源标识符 (URI) 的形式返回到调用设备。</Run>
<LineBreak />
<Run>3、通知通道 URI 由 Windows 返回到应用。</Run>
<LineBreak />
<Run>4、你的应用将 URI 发送到你自己的云服务。此回调机制是你自己的应用和你自己的服务之间的接口。使用安全的 Web 标准实现此回调是你的责任。</Run>
<LineBreak />
<Run>5、当你的云服务有要发送的更新时,它使用通道 URI 通知 WNS。通过安全套接字层 (SSL) 发送 TTP POST 请求(包括通知负载)来执行此操作。此步骤需要身份验证。</Run>
<LineBreak />
<Run>6、WNS 接收请求,并将通知路由到相应的设备。</Run>
</TextBlock>
<Image Source="wns.png" Margin="5" HorizontalAlignment="Left" Width="800" /> </StackPanel>
</Grid> </Page>

BackgroundTask/PushNotification.xaml.cs

/*
* 演示如何接收推送通知
* 由于本例没有上商店,所以本例是无法演示的,需要看演示效果的话运行一下自己写的“打字通”的 /TypingGame/PushNotification/Sample.xaml,然后用其生成的 channel 地址在 /WebApi/Controllers/PushNotificationController.cs 推送通知
*
*
* 注:
* 1、在商店后台的 dashboard 中找到你的 app 的“包名”和“发布者”并替换你的 Package.appxmanifest 中的相关节点,类似如下
* <Identity Name="10437webabcd.**********E91" Publisher="CN=27514DEC-****-****-****-F956384483D0" Version="1.0.0.0" />
* 也可以直接访问 https://apps.dev.microsoft.com/ 来查找这些信息
* 最简单也是推荐的做法是:“选中项目”->“右键”->“应用商店”->“将应用程序与应用商店关联”,按提示操作后会自动将商店信息同步到你的项目中
* 2、需要在 Package.appxmanifest 中增加后台任务声明,并勾选“推送通知”(经测试发现不做这一步也可以,但是为了保险还是加上吧)
* 3、每次新建的 channel 有效期为 30 天
*
*
* 另:
* WNS - Windows Push Notification Service
* 推送通知的服务端参见:/WebApi/Controllers/PushNotificationController.cs
*/ using System;
using Windows.Networking.PushNotifications;
using Windows.UI.Notifications;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; namespace Windows10.BackgroundTask
{
public sealed partial class PushNotification : Page
{
public PushNotification()
{
this.InitializeComponent();
} private async void btnCreateChannel_Click(object sender, RoutedEventArgs e)
{
// 创建一个推送通知信道,每个新建的 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;
}
}
}

OK
[源码下载]

背水一战 Windows 10 (121) - 后台任务: 推送通知的更多相关文章

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

    [源码下载] 重新想象 Windows 8 Store Apps (67) - 后台任务: 推送通知 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台任务 推送通 ...

  2. 背水一战 Windows 10 (118) - 后台任务: 后台下载任务(任务分组,并行或串行执行,组完成后通知)

    [源码下载] 背水一战 Windows 10 (118) - 后台任务: 后台下载任务(任务分组,并行或串行执行,组完成后通知) 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 ...

  3. 背水一战 Windows 10 (114) - 后台任务: 后台任务的 Demo(与 app 不同进程), 后台任务的 Demo(与 app 相同进程)

    [源码下载] 背水一战 Windows 10 (114) - 后台任务: 后台任务的 Demo(与 app 不同进程), 后台任务的 Demo(与 app 相同进程) 作者:webabcd 介绍背水一 ...

  4. 背水一战 Windows 10 (120) - 后台任务: 后台上传任务

    [源码下载] 背水一战 Windows 10 (120) - 后台任务: 后台上传任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台上传任务 示例演示 uwp 的后台上 ...

  5. 背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务)

    [源码下载] 背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务) 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台下 ...

  6. 背水一战 Windows 10 (117) - 后台任务: 后台下载任务

    [源码下载] 背水一战 Windows 10 (117) - 后台任务: 后台下载任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台下载任务 示例演示 uwp 的后台下 ...

  7. 背水一战 Windows 10 (116) - 后台任务: 前台程序激活后台任务

    [源码下载] 背水一战 Windows 10 (116) - 后台任务: 前台程序激活后台任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 前台程序激活后台任务 示例演示后 ...

  8. 背水一战 Windows 10 (115) - 后台任务: 通过 toast 激活后台任务, 定时激活后台任务

    [源码下载] 背水一战 Windows 10 (115) - 后台任务: 通过 toast 激活后台任务, 定时激活后台任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 通 ...

  9. 与众不同 windows phone (10) - Push Notification(推送通知)之推送 Tile 通知, 推送自定义信息

    原文:与众不同 windows phone (10) - Push Notification(推送通知)之推送 Tile 通知, 推送自定义信息 [索引页][源码下载] 与众不同 windows ph ...

随机推荐

  1. Ireport启动错误

    问题描述:cannot find java.exe Neither (null)\jre\bin\java.exe nor (null)\bin\java.exe exits 解决办法: 打开Irep ...

  2. 通过ssh StrictHostKeyChecking解决自动化git项目问题

    SSH 公钥检查是一个重要的安全机制,可以防范中间人劫持等黑客攻击.但是在特定情况下,严格的 SSH 公钥检查会破坏一些依赖 SSH 协议的自动化任务,就需要一种手段能够绕过 SSH 的公钥检查. 首 ...

  3. 一篇文章说清楚mysql索引

    索引是什么? 索引是为了加速对表中数据行的检索而创建的一种分散的数据存储结构 为什么要使用索引? 索引能极大的减少数据存储引擎需要需要扫描的数据量: 索引能够把随机IO变为数序IO: 索引能够帮助我们 ...

  4. 7C - 折线分割平面

    我们看到过很多直线分割平面的题目,今天的这个题目稍微有些变化,我们要求的是n条折线分割平面的最大数目.比如,一条折线可以将平面分成两部分,两条折线最多可以将平面分成7部分,具体如下所示.  Input ...

  5. go的包下载失败解决方案

    包被墙的方案 1 翻啊的墙 2 gopm 3 https://github.com/golang/net 4 使用国内网站打包 5 export GOPROXY=https://goproxy.io

  6. ASCII,Unicode 和 UTF-8

    ASCII: 英文的编码方式,规定了128个字符的编码,使用了一个字节的后七位表示. Unicode : 每个国家的字符集都不同,世界上所有的字符远远超过128个.Unicode,就是一种所有符号的编 ...

  7. python写注册

    # coding = UTF-8 注释格式 import datetime 引用日期 today = datetime.datetime.today().strftime("%Y-%m-%d ...

  8. rn下的弹性布局

    重点: 1]react native 下的弹性布局名字叫:flexDirection 2]flexDirection的默认值是column而不是row,而flex也只能指定一个数字值. 3]使用fle ...

  9. selenium中maven的使用

    一.maven的下载.解压以及环境变量配置 1.下载maven: 官网下载地址:http://maven.apache.org/download.cgi 在Files下面下载对应的maven版本(官网 ...

  10. Windows多线程学习随笔

    自学Windows多线程知识,例程如下: #include <iostream> #include <windows.h> #include <process.h> ...