Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
confidence68 opened this issue May 6, 2018 · 0 comments
Open

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

confidence68 opened this issue May 6, 2018 · 0 comments

Comments

@confidence68
Copy link
Owner

前言

本文是客户端和服务器端通信最后一个系列,主要介绍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/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant