公告:由于博客https升级,原博客引用http链接失效,预览及部分图片效果请查看源代码!

【系列三】h5的Notification 、web Push介绍

3196次浏览

前言

本文是客户端和服务器端通信最后一个系列,主要介绍h5的桌面通知和web push,h5的Notification主要用于向用户展示通知,而web push 主要用于订阅推送消息。

h5的Notification

关于h5的Notification已经不是什么新的技术,但是最新chrome浏览器也是只有在https协议下面才有效。下面简单介绍一下Notification

语法

let myNotification = new Notification(title, options);

参数

一、title

定义一个通知的标题,当它被触发时,它将显示在通知窗口的顶部。

二、options 可选 options对象包含应用于通知的任何自定义设置选项。选项有:

dir: 显示通知的方向。默认是auto,跟随浏览器语言设置行为,你也可以通过设置ltr和rtl的值来覆盖该行为(虽然大多数浏览器似乎忽略这些设置)
lang: 通知的语言,如使用代表一个BCP 47语言标签的  DOMString 指定的。请参阅Sitepoint ISO 2字母语言代码页面,以获得简单的参考。
badge: 一个 USVString 包含用于表示通知的图像的URL, 当没有足够的空间来显示通知本身时。
body: 一个 DOMString 表示通知的正文,将显示在标题下方。
tag:  一个 DOMString 代表通知的 一个识别标签。
icon:  一个 USVString 包含要在通知中显示的图标的URL。
image: 一个 USVSTring包含要在通知中显示的图像的URL。
data: 您想要与通知相关联的任意数据。这可以是任何数据类型。
vibrate: 一个振动模式 vibration pattern 设备的振动硬件在通知触发时发出。
renotify: 一个 Boolean 指定在新通知替换旧通知后是否应通知用户。默认值为false,这意味着它们不会被通知。
requireInteraction: 表示通知应保持有效,直到用户点击或关闭它,而不是自动关闭。默认值为false。

以下选项列在最新规范中,但是目前浏览器可能尚未支持,大家可以随时尝试!

silent: 一个 Boolean 指明通知是否应该是无声的,即,不需要发出声音或振动,无论设备设置如何。默认值为false,这意味着它不会保持静默。
sound:一个 USVString 包含通知触发时要播放的音频文件的URL。
noscreen: 一个 Boolean 指定通知触发是否应启用设备的屏幕。 默认值为false,这意味着它将启用屏幕。
sticky: 一个 Boolean 指明通知是否应该是“粘”, 即不易被用户清理。默认值为false,这意味着它不会粘。

案例

function spawnNotification(theBody,theIcon,theTitle) {
  var options = {
      body: theBody,
      icon: theIcon
  }
  var n = new Notification(theTitle,options);
}

web push

用户订阅了一个站点的 Web Push 服务后,即使用户关闭了浏览器,一旦站点主动发送推送消息,用户都能收到,只要你的电脑是开着的。这是目前谷歌和苹果在 Chrome 和 Safari 上都力推的一种全新推送服务,Firefox最近也加入了这个阵营。

web push 优点

一、可以完美替代原来的Email订阅服务,因为 Email 订阅这个动作要用户主动发起,不管你在页面内放了多显眼的订阅标志,都得用户去主动点击,填写自己 Email 地址才行。而且,如果不使用邮件客户端,很多订阅的 Email 发出去犹如石沉大海,到达率很低。

Web Push 完全由浏览器开发商的标准协议发起,一旦用户访问开通了 Web Push 的站点 ,浏览器就会主动询问你是否要订阅,弹出的订阅框也都是浏览器开发者的标准规范。首先,它增加了用户订阅的可能性。

二,一旦用户点阅,只要你打开电脑,就会收到推送通知,没有邮件订阅时用户主动去查收邮件的问题,大大增加了订阅推送到达率。

三,Web Push 让站点为主,APP 为辅的网站可以摆脱 APP 安装量少的困扰,访问你站点的人,只有一小部分会安装你的 APP,而Web Push 不需要安装任何 APP 在电脑上,只要用户点击一次Allow来订阅消息即可。

web push 国内使用少的原因

1、Web Push 使用了 GCM 服务,而 GCM 在国内基本上很难连通,国内用户除非翻了,否则压根不可能订阅成功 Chrome 的 Web Push。

2、谷歌要求 Chrome 的 Web Push 必须用 https 加密传输,国内目前很多网站还在使用http协议。

所以目前国内web push 使用较少。

web push 流程

1、客户端完成请求订阅一个用户的逻辑
2、服务端调用遵从web push协议的接口,传送消息推送(push message)到推送服务器(该服务器由浏览器决定,开发者所能做的只有控制发送的数据)
3、推送服务器将该消息推送至对应的浏览器,用户收到该推送

web push实现细节

首先注册一个Service Worker,若注册成功,返回的Promise为resolve状态,如下:

function registerServiceWorker() {
  return navigator.serviceWorker.register('service-worker.js')
  .then(function(registration) {
    console.log('Service worker successfully registered.');
    return registration;
  })
  .catch(function(err) {
    console.error('Unable to register service worker.', err);
  });
}

关于Service Worker,我之前文章有提及,但是没有关于这方面的详细文章,大家可以自行网上搜索。

随后测试window环境下是否有Notification对象,测试成功,调用Notification.requestPermission请求用户授权发送推送,若授权成功,将会返回'granted'。

接下来要做的就是使用注册好的Service Worker对象,调用pushManager.subscribe方法,从客户端获得刚刚所说的PushScription对象。

function subscribeUserToPush() {
  return navigator.serviceWorker.register('service-worker.js')
  .then(function(registration) {
    const subscribeOptions = {
      userVisibleOnly: true,
      applicationServerKey: urlBase64ToUint8Array(
        'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U'
      )
    };

    return registration.pushManager.subscribe(subscribeOptions);
  })
  .then(function(pushSubscription) {
    console.log('Received PushSubscription: ', JSON.stringify(pushSubscription));
    return pushSubscription;
  });
}

解释:

1、userVisibleOnly是为了保证推送对用户可见,

2、application server key则如前文所说,是推送服务器用以识别应用服务器的密钥,这里的密钥包含了公钥和私钥,传输的是公钥。

3、PushScription的endpoint也是在这个过程中生成的,生成公钥和私钥可以使用web-push库。

这里再次说明一下推送服务器的不可选择性,在调用subscribe生成PushScription时,浏览器会向它指定的中转服务器发送请求来生成endpoint和其余部分,这是没法控制的。

4、PushScription中的auth和p256dh是用来控制带载荷的push message的。

获取到PushScription对象后,将其发往应用服务器,此处简化了存储,使用nedb存下PushScription并返回Promise:

function saveSubscriptionToDatabase(subscription) {
  return new Promise(function(resolve, reject) {
    db.insert(subscription, function(err, newDoc) {
      if (err) {
        reject(err);
        return;
      }
      resolve(newDoc._id);
    });
  });
};

存储完毕后,接下来就是开发后台管理逻辑,使得管理员能够触发向用户推送消息的事件,应用服务器所做的逻辑就是遍历在数据库中存储的所有PushScription并推送消息,以下是使用web-push库完成配置密钥及联系邮箱的示例:

web-push请参见github: https://github.com/web-push-libs/web-push

const vapidKeys = {
  publicKey:
'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
  privateKey: 'UUxI4O8-FbRouAevSmBQ6o18hgE4nSG3qwvJTfKc-ls'
};

webpush.setVapidDetails(
  'mailto:web-push-book@haorooms.com',
  vapidKeys.publicKey,
  vapidKeys.privateKey
);

不要忘了配置你在谷歌云服务(例如FCM)申请到的GCMApiKey:

webpush.setGCMAPIKey('<Your GCM API Key Here>');

配置完成后,就可以将subscription发送出去,使用web-push的sendNotification接口:

webpush.sendNotification(pushSubscription, 'Your Push Payload Text');

参考

NotificationAPI : https://developer.mozilla.org/en-US/docs/Web/API/notification/Notification

Push API : https://developer.mozilla.org/en-US/docs/Web/API/Push_API

Push API(Working Draft): https://www.w3.org/TR/push-api/

Web Push Protocol(Internet Draft): https://tools.ietf.org/html/draft-ietf-webpush-protocol-12

Notification(Recommendation): https://www.w3.org/TR/notifications/

Tags: 连接web push通知

相关文章: