rviceworker消息推送
⾸先下载源码:
git /GoogleChrome/push-notifications.git
设置如下选项⽅便开发:
开始
注册之后记录sw实例:
ister('sw.js')
.then(function(swReg) {
console.log('Service Worker is registered', swReg);
swRegistration = swReg;
})
⽣成key:
然后把public key记录到 applicationServerPublicKey变量上。
判断当前sw是否已经订阅过消息推送了:
Subscription()
.then(function(subscription) {
isSubscribed = !(subscription === null);
if (isSubscribed) {
console.log('Ur IS subscribed.');
} el {
console.log('Ur is NOT subscribed.');
}
});
使⽤之前⽣成的public key来订阅消息推送:
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
// subscribe 会给推送服务器发送⼀个⽹络请求
swRegistration.pushManager.subscribe({
urVisibleOnly: true, // ⽤于显⽰请求权限的界⾯,所以这个值基本必须为true,否则获取不到权限的话,当前promi会被reject
applicationServerKey: applicationServerKey
}).then(function (subscription) {
// 订阅成功。subscription 就是推送服务器返回的信息
console.log('Ur is subscribed.');
updateSubscriptionOnServer(subscription); // 在这个⾃定义函数中,我们应该把订阅信息发送给后端
isSubscribed = true;
}).catch(function (err) {
console.log('Failed to subscribe the ur: ', err);
});
// ⼯具函数|
function urlB64ToUint8Array(ba64String) {
const padding = '='.repeat((4 - ba64String.length % 4) % 4);
const ba64 = (ba64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(ba64);
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事件,来接收服务器发来的消息推送:
lf.addEventListener('push', function(event) {
console.log('[Service Worker] Push Received.');
console.log(`[Service Worker] Push had this data: "${()}"`);
南沙旅游
const title = 'Push Codelab';
const options = {
body: 'Yay it works.',
icon: 'images/icon.png',
badge: 'images/badge.png' //仅仅⽤在安卓
};
// showNotification ⽤于显⽰⼀个通知
// waitUntil :使sw等待直⾄这个promi被处理,否则有可能这个promi没被处理,sw 就被浏览器终⽌了
event.istration.showNotification(title, options));
});
测试:在这⾥点击push:
屏幕左下⾓就会看到这个通知:
但是点击这个通知是没什么响应的,需要我们去注册⼀个点击事件:
lf.addEventListener('notificationclick', function(event) {
console.log('[Service Worker] Notification click Received.');
event.waitUntil(
clients.openWindow('/web/') // 打开⼀个标签
);
海南西线旅游景点
土石方施工方案
});
发送消息推送
同理在实际应⽤中,我们后端也需要这个subscription信息来发送消息推送。步骤如下(使⽤):
创建fireba项⽬,⾥⾯的key为(⽤来作为GCM API key):
接着来订阅消息推送:
function urlB64ToUint8Array(ba64String) {
const padding = '='.repeat((4 - ba64String.length % 4) % 4);
const ba64 = (ba64String + padding)
.replace(/\-/g, '+')
送医院锦旗.replace(/_/g, '/');
const rawData = window.atob(ba64);
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 subscribeUr() {
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
urVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then(function(subscription) {
console.log('Ur is subscribed.');
updateSubscriptionOnServer(subscription);
isSubscribed = true;
updateBtn();
})
.catch(function(err) {
console.log('Failed to subscribe the ur: ', err);
updateBtn();
});
}
node服务器来发送消息推送:
const webpush = require('web-push');
// VAPID keys should only be generated only once.
// const vapidKeys = ateVAPIDKeys();
吩咐拼音
webpush.tGCMAPIKey('AIzaSyAPNqXa931TMPdEx5im92uDQmWQKfKFJNo');
webpush.tVapidDetails(
'mailto:',
"BP0bPsBFRO4JI4WPI-0Hztl49AX2mjfPxr5SAmiu9i1C4T1X2EFQvuoCekow-JD9Gs3aHlkxstVm9UTndHA0YM8",
"Y23-foXK_oHtxOA5whmR61RBbyqqm9Sxnl-bapZPghQ"
);
// This is the same output of calling JSON.stringify on a PushSubscription
const pushSubscription = {
endpoint: '/fcm/nd/fN0CygRBHVo:APA91bH4FB9bkE6RjD6v758TaNoHIx4IhUxdSm_bcFMPRRnyY4IcTlID9md6AwAdhUhqE7HzbL76WY6Wzak7MGmtrJ5InYAwYP31B-mc-TXRCnKQwUKxjIPe1Kv6-U_S672rG_8j keys: {
auth: 'uOxqcnlXYQIyDucqXeWeeA==',
p256dh: 'BFoO1hMB5kpWA4lPx2fKZGiyw3Qd-3n9afeE3jrJ62Bna66LsHQmCSIjo0Q9t2UF6MZdzyqe6cNkNbSGpNpmX6I='
}
};
webpush.ndNotification(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 }
查看之后,发现有⼈针对这个问题提交了⼀个PR,但是没有被应⽤,即master分⽀上还是存在这个问题。
取消订阅
Subscription()
.then(function(subscription) {
if (subscription) {
// TODO: Tell application rver to delete subscription
return subscription.unsubscribe();
}
})
.catch(function(error) {
console.log('Error unsubscribing', error);
})
并且要记得通知后端,不要往这个subscription推送消息了。