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:[email protected]‘,
    "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推送消息了 。

原文地址:https://www.cnblogs.com/hellohello/p/8441188.html

时间: 2024-10-16 09:55:16

service worker 消息推送的相关文章

iOS消息推送原理

推送相关概念,如下图1-1: 1.Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provider可以理解为服务端[消息的发起者]): 2.APNS:Apple Push Notification Service[苹果消息推送服务器]: 3.iPhone:用来接收APNS下发下来的消息: 4.Client App:IOS设备上的应用程序,用来接收iphone传递APNS下发的消息到制定的一个客户端 app[消息的最终响应者]: 上图

IOS 消息推送原理及实现总结

一.消息推送原理: 在实现消息推送之前先提及几个于推送相关概念,如下图1-1: 1-1 1.              Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provider可以理解为服务端[消息的发起者]): 2.              APNS:Apple Push Notification Service[苹果消息推送服务器]: 3.              iPhone:用来接收APNS下发下来的消息: 4.

iOS消息推送原理和实现总结

一.消息推送原理: 在实现消息推送之前先提及几个于推送相关概念,如下图:1. Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provider可以理解为服务端[消息的发起者]):2. APNS:Apple Push Notification Service[苹果消息推送服务器]:3. iPhone:用来接收APNS下发下来的消息:4. Client App:IOS设备上的应用程序,用来接收iphone传递APNS下发的消息到制定的一

APNS消息推送实现

转自:http://blog.csdn.net/biaobiaoqi/article/details/8058503 一.消息推送原理: 在实现消息推送之前先提及几个于推送相关概念,如下图1-1: 1. Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provider可以理解为服务端[消息的发起者]): 2. APNS:Apple Push Notification Service[苹果消息推送服务器]: 3. iPhone:用来接

Android消息推送:手把手教你集成小米推送

前言 在Android开发中,消息推送功能的使用非常常见. 为了降低开发成本,使用第三方推送是现今较为流行的解决方案. 今天,我将手把手教大家如何在你的应用里集成小米推送 该文档基于小米推送官方Demo,并给出简易推送Demo 看该文档前,请先阅读我写的另外两篇文章: 史上最全解析Android消息推送解决方案 Android推送:第三方消息推送平台详细解析 目录 1. 官方Demo解析 首先,我们先对小米官方的推送Demo进行解析. 请先到官网下载官方Demo和SDK说明文档 1.1 Demo

AngularJS+ASP.NET MVC+SignalR实现消息推送

原文:http://www.mincoder.com/article/4565.shtml 背景 OA管理系统中,员工提交申请单,消息实时通知到相关人员及时进行审批,审批之后将结果推送给用户. 技术选择 最开始发现的是firebase,于是很兴奋的开始倒腾起来.firebase用 起来倒是简单:引用一个js即可,按官网上的教程很快便应用到了项目中.第二天打开项目发现推送功能不好使了,这是为何?最后发现firebase官网打 不开了...难道firebase被google收了也会被天朝给墙掉?也许

Shuttle ESB实现局域网消息推送

ESB全称Enterprise Service Bus,即企业服务总线.它是传统中间件技术与XML.Web服务等技术结合的产物. ESB的出现改变了传统的软件架构,可以提供比传统中间件产品更为廉价的解决方案,同时它还可以消除不同应用之间的技术差异,让不同的应用服务器协调运作,实现了不同服务之间的通信与整合. 看吧,ESB的功能是如此强大.在java中常用的是Mule ESB,而到了.Net,Shuttle ESB作为一种新生的ESB正在慢慢的被人们所接受.下面通过一个实例讲解Shuttle ES

IOS 基于APNS消息推送原理与实现(JAVA后台)--转

Push的原理: Push 的工作机制可以简单的概括为下图 图中,Provider是指某个iPhone软件的Push服务器,这篇文章我将使用.net作为Provider. APNS 是Apple Push Notification Service(Apple Push服务器)的缩写,是苹果的服务器. 上图可以分为三个阶段. 第一阶段:Push服务器应用程序把要发送的消息.目的iPhone的标识打包,发给APNS. 第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的

转:IOS 基于APNS消息推送原理与实现(JAVA后台)

Push的原理: Push 的工作机制可以简单的概括为下图 图中,Provider是指某个iPhone软件的Push服务器,这篇文章我将使用.net作为Provider. APNS 是Apple Push Notification Service(Apple Push服务器)的缩写,是苹果的服务器. 上图可以分为三个阶段. 第一阶段:Push服务器应用程序把要发送的消息.目的iPhone的标识打包,发给APNS. 第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的