service worker 消息推送
https://developers.google.com/web/fundamentals/codelabs/push-notifications/?hl=en
首先下载源码:
git clone https://github.com/GoogleChrome/push-notifications.git
设置如下选项方便开发:

开始
注册之后记录sw实例:
navigator.serviceWorker.register('sw.js')
.then(function(swReg) {
console.log('Service Worker is registered', swReg);
swRegistration = swReg;
})
生成key:
https://web-push-codelab.glitch.me/。生成了一个相互对应的public key 与 private key

然后把public key记录到 applicationServerPublicKey变量上。
判断当前sw是否已经订阅过消息推送了:
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
isSubscribed = !(subscription === null); if (isSubscribed) {
console.log('User IS subscribed.');
} else {
console.log('User is NOT subscribed.');
}
});
使用之前生成的public key来订阅消息推送:
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey); // subscribe 会给推送服务器发送一个网络请求
swRegistration.pushManager.subscribe({
userVisibleOnly: true, // 用于显示请求权限的界面,所以这个值基本必须为true,否则获取不到权限的话,当前promise会被reject
applicationServerKey: applicationServerKey }).then(function (subscription) {
// 订阅成功。subscription 就是推送服务器返回的信息
console.log('User is subscribed.');
updateSubscriptionOnServer(subscription); // 在这个自定义函数中,我们应该把订阅信息发送给后端
isSubscribed = true; }).catch(function (err) {
console.log('Failed to subscribe the user: ', err);
}); // 工具函数|
function urlB64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/'); const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length); for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
执行订阅的时候,界面上会有如下弹框来请求消息推送的显示权限:

点击同意的话,则订阅成功。但如果用户点击了拒绝,则app没办法再次显示这个弹框而且没有消息推送,以下这个值会为true:
Notification.permission === 'denied'
手动点击这里(ask),可以撤销权限,使弹窗再次弹出来,方便开发测试:

处理消息推送
我们需要在sw中监听push事件,来接收服务器发来的消息推送:
self.addEventListener('push', function(event) {
console.log('[Service Worker] Push Received.');
console.log(`[Service Worker] Push had this data: "${event.data.text()}"`);
const title = 'Push Codelab';
const options = {
body: 'Yay it works.',
icon: 'images/icon.png',
badge: 'images/badge.png' //仅仅用在安卓
};
// showNotification 用于显示一个通知
// waitUntil :使sw等待直至这个promise被处理,否则有可能这个promise没被处理,sw 就被浏览器终止了
event.waitUntil(self.registration.showNotification(title, options));
});
测试:在这里点击push:

屏幕左下角就会看到这个通知:

但是点击这个通知是没什么响应的,需要我们去注册一个点击事件:
self.addEventListener('notificationclick', function(event) {
console.log('[Service Worker] Notification click Received.');
event.notification.close(); // 关闭这个通知
event.waitUntil(
clients.openWindow('https://developers.google.com/web/') // 打开一个标签
);
});
发送消息推送
以上订阅成功后返回的subscription,将它 JSON.stringify(subscription) 后的字符串粘贴到 https://web-push-codelab.glitch.me/ 就可以发送用于测试的消息推送了(注意要用页面所在的key来订阅才可以)。
同理在实际应用中,我们后端也需要这个subscription信息来发送消息推送。步骤如下(使用 web-push):
创建firebase项目,里面的key为(用来作为GCM API key):

然后在https://web-push-codelab.glitch.me/ 中生成的public/private key为(其实也可以用webpush.generateVAPIDKeys来生成):

接着来订阅消息推送:
function urlB64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
const applicationServerPublicKey = 'BP0bPsBFRO4JI4WPI-0Hztl49AX2mjfPxr5SAmiu9i1C4T1X2EFQvuoCekow-JD9Gs3aHlkxstVm9UTndHA0YM8';
function subscribeUser() {
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then(function(subscription) {
console.log('User is subscribed.');
updateSubscriptionOnServer(subscription);
isSubscribed = true;
updateBtn();
})
.catch(function(err) {
console.log('Failed to subscribe the user: ', err);
updateBtn();
});
}
node服务器来发送消息推送:
const webpush = require('web-push');
// VAPID keys should only be generated only once.
// const vapidKeys = webpush.generateVAPIDKeys();
webpush.setGCMAPIKey('AIzaSyAPNqXa931TMPdEx5im92uDQmWQKfKFJNo');
webpush.setVapidDetails(
'mailto:947133297@qq.com',
"BP0bPsBFRO4JI4WPI-0Hztl49AX2mjfPxr5SAmiu9i1C4T1X2EFQvuoCekow-JD9Gs3aHlkxstVm9UTndHA0YM8",
"Y23-foXK_oHtxOA5whmR61RBbyqqm9Sxnl-bapZPghQ"
);
// This is the same output of calling JSON.stringify on a PushSubscription
const pushSubscription = {
endpoint: 'https://fcm.googleapis.com/fcm/send/fN0CygRBHVo:APA91bH4FB9bkE6RjD6v758TaNoHIx4IhUxdSm_bcFMPRRnyY4IcTlID9md6AwAdhUhqE7HzbL76WY6Wzak7MGmtrJ5InYAwYP31B-mc-TXRCnKQwUKxjIPe1Kv6-U_S672rG_8jVmpJ',
keys: {
auth: 'uOxqcnlXYQIyDucqXeWeeA==',
p256dh: 'BFoO1hMB5kpWA4lPx2fKZGiyw3Qd-3n9afeE3jrJ62Bna66LsHQmCSIjo0Q9t2UF6MZdzyqe6cNkNbSGpNpmX6I='
}
};
webpush.sendNotification(pushSubscription, 'Your Push Payload Text').then(()=>{
console.log("发送完成")
}).catch((err)=>{
console.log("被拒绝")
console.log(err)
})
因为在中国被墙的原因,以上代码运行会报错:
被拒绝
{ Error: connect ETIMEDOUT 172.217.160.106:443
at Object._errnoException (util.js:1024:11)
at _exceptionWithHostPort (util.js:1046:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1182:14)
code: 'ETIMEDOUT',
errno: 'ETIMEDOUT',
syscall: 'connect',
address: '172.217.160.106',
port: 443 }
查看issue之后,发现有人针对这个问题提交了一个PR,但是没有被应用,即master分支上还是存在这个问题。
取消订阅
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
// TODO: Tell application server to delete subscription
return subscription.unsubscribe();
}
})
.catch(function(error) {
console.log('Error unsubscribing', error);
})
并且要记得通知后端,不要往这个subscription推送消息了 。
service worker 消息推送的更多相关文章
- IOS - 消息推送原理和实现
一.消息推送原理: 在实现消息推送之前先提及几个于推送相关概念,如下图1-1: 1.Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Pr ...
- iOS 消息推送原理及实现Demo
一.消息推送原理: 在实现消息推送之前先提及几个于推送相关概念,如下图1-1: 1.Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Pr ...
- iOS 消息推送原理
一.消息推送原理: 在实现消息推送之前先提及几个于推送相关概念,如下图: 1. Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Prov ...
- iOS 消息推送原理及实现总结
在实现消息推送之前先提及几个于推送相关概念,如下图:1. Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provider可以理解为服务 ...
- iOS 消息推送原理及实现总结 分类: ios技术 2015-03-01 09:22 70人阅读 评论(0) 收藏
在实现消息推送之前先提及几个于推送相关概念,如下图: 1. Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provider可以理解为服 ...
- iOS开发消息推送原理
转载自:http://www.cnblogs.com/cdts_change/p/3240893.html 一.消息推送原理: 在实现消息推送之前先提及几个于推送相关概念,如下图1-1: 1.Prov ...
- iOS消息推送原理
推送相关概念,如下图1-1: 1.Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provider可以理解为服务端[消息的发起者]): ...
- APNS消息推送实现
转自:http://blog.csdn.net/biaobiaoqi/article/details/8058503 一.消息推送原理: 在实现消息推送之前先提及几个于推送相关概念,如下图1-1: 1 ...
- iOS消息推送原理和实现总结
一.消息推送原理: 在实现消息推送之前先提及几个于推送相关概念,如下图:1. Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provi ...
随机推荐
- 上传到git
https://blog.csdn.net/Lucky_LXG/article/details/77849212
- Devc++贪吃蛇
使用Devc++写的一个简单版贪吃蛇程序,不过,在未配置之前,是不包含图形库的,所以需要自己配置新的环境 ----------------------------------------------- ...
- sQL存储过程的优缺点
目前具体的项目中没有使用sql存储过程,都用的封装好的框架,简单说下存储过程的优缺点. 优点: 1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般 SQL 语句每执行一次就编 ...
- Codeforces Round #402 (Div. 2) A
Description In Berland each high school student is characterized by academic performance — integer v ...
- js验证textarea里面是否有换行符
var reg = /[\r\n]+/g;if(reg.test(reason)){ PopAlert("不能有换行符!"); return;}
- mysql join操作
join的类型 1. 内联结:将两个表中存在联结关系的字段符合联结关系的那些记录形成记录集的联结. 2. 外联结:分为外左联结和外右联结. 案例背景 create table java (name ...
- asp.net网页跳转
1.Response.Redirect("http://www.bcbbs.net",false); 目标页面和原页面可以在2个服务器上,可输入网址或相对路径.后面的bool ...
- LINQ查询返回DataTable类型[轉]與将DataTable序列化为Json格式【轉】
(原文地址:http://xuzhihong1987.blog.163.com/blog/static/26731587201101853740294/) LINQ查询返回DataTable类型 在使 ...
- vscode设置html默认浏览器
Vscode版本:1.30.2,设置方法:file→preference→settings,剩余设置如下图.
- Android 视频录制 java.lang.RuntimeException: start failed.
//mRecorder.setVideoSize(320, 280); // mRecorder.setVideoFrameRate(5); mRecorder.setOutputFile(viodF ...