安卓web应用推送通知_如何为Web应用程序构建推送通知

安卓web应用推送通知

This article was originally published on Sencha. Thank you for supporting the partners who make SitePoint possible.

本文最初发表在Sencha上 感谢您支持使SitePoint成为可能的合作伙伴。

Progressive Web Applications have become a viable alternative to native applications: they can be installed, used to work offline, and have access to device hardware. In this article, I'll show you how to make your existing web applications even better than before by adding native-like notifications. I'll explain the concept of Web Push Notifications and show you how to add them to your existing web apps. Lastly, I'll cover the state of specifications and browser support.

渐进式Web应用程序已成为本机应用程序的可行替代方案:它们可以安装,用于脱机工作并可以访问设备硬件。 在本文中,我将向您展示如何通过添加类似本机的通知使现有的Web应用程序比以前更好。 我将解释Web推送通知的概念,并向您展示如何将其添加到现有Web应用程序中。 最后,我将介绍规格和浏览器支持的状态。

Web推送通知协议 (Web Push Notifications Protocol)

The Web Push Notifications protocol is relatively new. It gives web applications the ability to act as native applications and receive messages pushed to them from a server at any time even when the web app is not active or not currently loaded in a browser. This lets you engage users with urgent and relevant notifications when they are not using your application and motivate them to return to the application.

Web推送通知协议相对较新。 它使Web应用程序能够充当本机应用程序,并随时接收从服务器推送到它们的消息,即使该Web应用程序未激活或当前未加载到浏览器中也是如此。 这样,您可以在用户不使用您的应用程序时为其发出紧急且相关的通知,并激励他们返回该应用程序。

Web Push Message

It makes clear the commercial value of implementing Web Push Notifications in your web apps. It increases user engagement. The overall value of your application increases too, because push notifications make your application more useful for your users. This improves the usability of web applications and moves us closer to developing a single web application for all platforms instead of having to develop a native application for every platform.

它明确了在Web应用程序中实现Web推送通知的商业价值。 它增加了用户参与度。 您的应用程序的整体价值也会增加,因为推送通知使您的应用程序对用户更有用。 这提高了Web应用程序的可用性,并使我们更接近为所有平台开发单个Web应用程序,而不必为每个平台开发本机应用程序。

Web推送与Web套接字 (Web Push vs Web Sockets)

Before going into the details of the technology, I would like to talk a bit about the differences between Web Push and Web Sockets. First, here is what they have in common. Web Push and Web Sockets are designed to implement real-time communication between the web application and application server, and to send real-time data and updates from the application server to your web application.

在详细介绍该技术之前,我想先谈一下Web Push和Web Sockets之间的区别。 首先,这是他们的共同点。 Web推送和Web套接字旨在实现Web应用程序与应用程序服务器之间的实时通信,并将实时数据和更新从应用程序服务器发送到Web应用程序。

Here are the differences:

区别如下:

  • Web Sockets can only be used when a web page is loaded and active. But the opposite is true of Web Push Notifications which can be used at any time, including when the application is active, inactive, or not loaded, and when the browser is not active or even closed.

    Web套接字只能在加载网页并处于活动状态时使用。 但是,Web推送通知则相反,它可以随时使用,包括应用程序处于活动状态,非活动状态或未加载时,以及浏览器处于非活动状态甚至关闭状态时。
  • Data sent using Web Push must be encrypted, and there is a size limit per message (it must not be larger than 4Kb). There's also a count limit for the number of messages you are allowed to send (the exact limit value depends on the browser). Some browsers (for example Chrome) may also require that a notification be displayed to the user every time a message is received. You don't have any of these limitations when you use Web Sockets: you can send any number of unencrypted messages of any size and handle them as you want; and you may display a notification or silently update the data in your application or even do nothing at all.

    使用Web Push发送的数据必须经过加密,并且每条消息都有大小限制(不得大于4Kb)。 允许发送的邮件数量也有一个计数限制(确切的限制值取决于浏览器)。 某些浏览器(例如Chrome)还可能要求每次接收到消息时向用户显示通知。 使用Web套接字时,您没有任何这些限制:您可以发送任意数量的任意大小的未加密消息,并根据需要进行处理; 并且您可能会显示通知或静默更新应用程序中的数据,甚至什么也不做。
  • The general rule is to use Web Sockets for sending ordinary data updates to your web app when a user is interacting with the application. Use Web Push Notifications for sending urgent and important messages to a user that have to be received immediately, whether or not the user is working with your application at that moment.

    一般规则是,当用户与应用程序进行交互时,使用Web套接字将常规数据更新发送到您的Web应用程序。 使用Web Push Notifications可以向用户发送紧急且重要的消息,无论该用户当时是否正在使用您的应用程序,都必须立即接收这些消息。

技术概念 (Technical Concepts)

Let's move to the technical details of the technology. I would like to explain the details using a game with special rules, players, and rounds. I'll start by describing the players of the game. There are 5 players involved in this game called Web Push Notifications:

让我们转到该技术的技术细节。 我想使用带有特殊规则,玩家和回合的游戏来解释细节。 我将从描述游戏玩家开始。 此游戏中涉及Web推送通知的有5位玩家:

  • Web Application

    Web应用程序
  • Service Worker

    服务人员
  • Browser

    浏览器
  • Application Server

    应用服务器
  • Push Server

    推送服务器

Push Server is a service that is implemented by the browser vendor; it is a communication bridge between your application server and a browser. It is responsible for delivering messages from your application server to the browser.

推送服务器是由浏览器供应商实施的服务。 它是您的应用程序服务器和浏览器之间的通信桥。 它负责将消息从应用程序服务器传递到浏览器。

使用游戏演示Web推送通知 (Using a Game to Demonstrate Web Push Notifications)

Using a game, I'll demonstrate how you can add web push notifications to your apps. The rules of this game are defined by several specifications provided by the World Wide Web Consortium and the Internet Engineering Task Force:

通过游戏,我将演示如何向您的应用程序添加Web推送通知。 此游戏的规则由万维网联盟和Internet工程任务组提供的几种规范定义:

  • Communications between the Browser and the web application or service worker associated with this application are described in the Push API specification.

    推送API规范中描述了浏览器与Web应用程序或与此应用程序关联的服务工作者之间的通信。

  • Displaying different types of Notifications as well as Notification handling are described in the Notifications API specification.

    在Notifications API规范中描述了显示不同类型的通知以及通知处理。

  • Communications between the Application Server and the Push Server are defined in the Web Push Protocol specification.

    Web推送协议规范中定义了应用程序服务器和推送服务器之间的通信。

  • There are also additional specifications describing push message encryption and application server identification that let your application server prove that it is allowed to send messages to your user.

    还有其他一些描述推送消息加密和应用程序服务器标识的规范,可以使您的应用程序服务器证明它被允许向您的用户发送消息。

Push API

游戏回合 (Game Rounds)

I have split the game into four rounds and will explain the concept and target of every round. Then, I'll show you how you can implement every round in your application.

我将游戏分为四个回合,并将解释每个回合的概念和目标。 然后,我将向您展示如何在应用程序中实施每一轮。

第一轮:服务人员注册 (Round 1: Service Worker Registration)

Web Push Notifications require Service Workers to handle push messages, so the first round will be to register your service worker. Only your web application and the browser are involved in this round. And this round occurs at the page load.

Web推送通知要求服务人员处理推送消息,因此第一轮将是注册服务人员。 此轮只涉及您的Web应用程序和浏览器。 而这一回合发生在页面加载时。

The web application sends a request to a browser to register a Service Worker and the browser replies with the ServiceWorkerRegistration object if the Service Worker was registered successfully.

Web应用程序向浏览器发送请求以注册Service Worker,并且如果Service Worker已成功注册,浏览器将使用ServiceWorkerRegistration对象进行回复。

Register

To implement this round, you need to add the following code to your web application:

要实施此回合,您需要将以下代码添加到您的Web应用程序:

if ('serviceWorker' in navigator) {

  if ('PushManager' in window) {

    navigator.serviceWorker.register('ServiceWorker.js').then(function(registration) {

      //state initializing

    })

    .catch(function() {

      //error handling

    });

  } else {

    //error handling

  }

} else {

  //error handling

}

First, we need to check if the browser supports Service Workers. Then, we need to check if the browser supports web push notifications. As browser support is growing, it's always a good idea to add both checks.

首先,我们需要检查浏览器是否支持Service Workers。 然后,我们需要检查浏览器是否支持Web推送通知。 随着浏览器支持的增长,添加两个检查始终是一个好主意。

If both are supported, we register our service worker. For this step, we call the navigator.serviceWorker.register() method and pass the path to our Service Worker file as a parameter. After this step, the browser will download this file and run it in a service worker environment. The Service Worker file is a standard JavaScript file, but the browser will "give it access" to the service worker APIs, including push.

如果两者都受支持,我们将注册我们的服务人员。 对于此步骤,我们调用navigator.serviceWorker.register()方法,并将路径作为参数传递到我们的Service Worker文件。 完成此步骤后,浏览器将下载此文件并在Service Worker环境中运行它。 Service Worker文件是标准JavaScript文件,但是浏览器将“允许它访问” Service Worker API,包括推送。

If everything ran correctly and there were no errors, the promise returned by register() will resolve. If there are errors of any kind, the promise is rejected, and we need to handle this case as well as the case when the browser doesn't support Service Workers. When register() does resolve, it returns a ServiceWorkerRegistration object that will be used in the next round.

如果一切正常运行,并且没有错误,那么register()返回的promise将得到解决。 如果存在任何类型的错误,则承诺将被拒绝,我们需要处理这种情况以及浏览器不支持Service Workers的情况。 当register()确实解析后,它将返回一个ServiceWorkerRegistration对象,该对象将在下一轮中使用。

第二轮:订阅 (Round 2: Subscription)

The second round handles the subscription for Web Push Notifications. This is when you ask the user if he wants to receive Web Push Notifications from your application, and if he agrees, you subscribe him. This round involves more players – Web Application, Browser, Application Server and Push Server and more communications.

第二轮处理Web推送通知的订阅。 这是当您询问用户是否要从您的应用程序接收Web推送通知时,如果他同意,则您订阅他。 这一轮涉及更多的参与者-Web应用程序,浏览器,Application Server和Push Server以及更多的通信。

This round should be played when a user is ready to subscribe. You should ask him to subscribe only when you are sure that it is relevant and meaningful for him, because you will only have one chance to ask. If the user blocks the request, then the browser will not permit you to ask this question again later. The only way to unblock an application is to change it in the browser settings. And as you can imagine, almost no user ever does this. So, you need to explain to the user what kind of Notifications he will receive and why. You may also offer to subscribe the user using a custom in-page message, and once the user clicks yes, then show him a system browser request.

用户准备订阅时,应进行此回合。 仅当您确定对他有意义且有意义时,才应要求他订阅,因为您只有一个机会问。 如果用户阻止了该请求,那么浏览器将不允许您稍后再问这个问题。 取消阻止应用程序的唯一方法是在浏览器设置中进行更改。 可以想象,几乎没有用户这样做。 因此,您需要向用户解释他将收到哪种通知以及原因。 您还可以使用自定义页内消息来订阅用户,一旦用户单击“是”,然后向他显示系统浏览器请求。

What happens in this round? Your web application asks the browser to subscribe the user to receive Web Push Notifications. If the user agrees, the browser sends a request to the Push Server to generate a push subscription. The Push Server replies to the browser with a push subscription object that the browser forwards to your web application. As the last step, your web application sends this push subscription object to your application server via an Ajax call, for example. And your application server saves it to use in the next round.

这回合会发生什么? 您的Web应用程序要求浏览器订阅用户以接收Web推送通知。 如果用户同意,则浏览器将请求发送到推送服务器以生成推送订阅。 推送服务器使用推送订阅对象回复浏览器,该对象将被浏览器转发到您的Web应用程序。 作为最后一步,您的Web应用程序例如通过Ajax调用将此推送订阅对象发送到您的应用程序服务器。 然后您的应用程序服务器将其保存以供下一轮使用。

alt

Your web application is the main actor in this round, so this code should be added to your web app:

您的Web应用程序是本轮的主要参与者,因此应将以下代码添加到您的Web应用程序中:

navigator.serviceWorker.ready.then(function(registration) {

  registration.pushManager.subscribe({

    userVisibleOnly: true,

    applicationServerKey: urlBase64ToUint8Array('...')

  })

  .then(function(subscription) {

    // The subscription was successful

    savePushSubscription(subscription);

  })

  .catch(function(e) {

    //error handling

  });

});

Once the service worker is ready, we can subscribe a user by calling the registration.pushManager.subscribe() method of the Service Worker registration object that we received in the previous round. The browser requests permission to show notifications to a user. If the user allows it, the promise will be resolved with a subscription object. The subscription object contains necessary information for sending a push notification to a user. Now, you will need to save this object on your application server.

服务工作者准备就绪后,我们可以通过调用上一轮中收到的服务工作者注册对象的registration.pushManager.subscribe()方法来订阅用户。 浏览器请求允许向用户显示通知的权限。 如果用户允许,则将使用订阅对象来解决承诺。 订阅对象包含用于将推送通知发送给用户的必要信息。 现在,您将需要将此对象保存在应用程序服务器上。

I won't go deeper into this process – it could just be a standard Ajax call to the server, or you could send this object as a JSON or a string and then the server would need to save this object in a database. I will not show this code, because it depends on how your App Server is implemented. If the user denies permission or any other error occurs, then the promise will be rejected and you need to handle this issue.

我不会更深入地介绍这个过程–可能只是对服务器的标准Ajax调用,或者您可以将此对象作为JSON或字符串发送,然后服务器需要将该对象保存在数据库中。 我不会显示此代码,因为它取决于您的App Server的实现方式。 如果用户拒绝许可或发生任何其他错误,则诺言将被拒绝,您需要处理此问题。

权限请求 (Permission Request)

If your web app doesn't have permissions to show notifications at the time of calling subscribe(), the browser will request the permissions for you. But there is another option – you can request permissions manually by calling Notification.requestPermission method directly. This method will return a promise that resolves with the permission picked by the user. Possible values for this are granted, denied, or default.

如果您的Web应用没有权限在调用subscribe()时显示通知,则浏览器将为您请求权限。 但是还有另一个选项–您可以通过直接调用Notification.requestPermission方法来手动请求权限。 此方法将返回一个承诺,该承诺将通过用户选择的权限来解决。 可能的值被授予,拒绝或默认。

Notification.requestPermission(function(result) {

  if (result!== 'granted') {

    //handle permissions deny

  }

});

订阅参数 (Subscription Parameters)

Let's look at the parameter object passed into the subscribe method:

让我们看一下传递给订阅方法的参数对象:

reg.pushManagerpushManager.subscribe({

  userVisibleOnly: true,

  applicationServerKey: new Uint8Array([...])

});
  • userVisibleOnly: If it's set to true, it means that every push message will result in showing a Notification to the user. Silent push messages sent in the background, when the user isn't notified, are not allowed in this case. Currently, Chrome only allows this option to be set to true because theoretically silent push could be used by a developer to do nasty things like setting up hidden geo tracking for example. Firefox supports a limited number of silent push messages. There might be changes in the specification regarding this rule.

    userVisibleOnly:如果将其设置为true,则意味着每条推送消息都会向用户显示通知。 在这种情况下,不允许在未通知用户的情况下在后台发送静默的推送消息。 目前,Chrome仅允许将此选项设置为true,因为从理论上讲,开发人员可以使用静默推送来进行令人讨厌的事情,例如设置隐藏的地理跟踪。 Firefox支持数量有限的静默推送消息。 关于此规则的规范可能有所更改。
  • applicationServerKey: It's the public part of a public/private key pair identifying your application server. The browser will send this application server key to the push server, and it will be used by the push server to identify that the application subscribing a user is the same application that is messaging that user. I will explain the identification process in detail in the next round.

    applicationServerKey:它是标识应用程序服务器的公用/专用密钥对的公用部分。 浏览器会将此应用程序服务器密钥发送到推送服务器,推送服务器将使用它来识别订阅用户的应用程序与向该用户发送消息的应用程序相同。 我将在下一轮中详细说明身份识别过程。

订阅对象 (Subscription Object)

Let's look at the PushSubscription object that is returned by resolving the promise. This PushSubscription object is associated with the Service Worker that we registered in the previous round. This Push subscription describes the delivery bridge for push messages.

让我们看一下通过解决承诺返回的PushSubscription对象。 此PushSubscription对象与我们在上一轮注册的Service Worker相关联。 此推送订阅描述了推送消息的传递桥。

interface PushSubscription {

  readonly attribute endpoint;

  // "https://{push\_server\_url}/{user\_identifier}",

  function getKey();

  //auth - authentication secret

  //p256dh - key for encrypting messages

};

It contains two important parts:

它包含两个重要部分:

  • endpoint is a push server URL followed by a unique user identifier. This URL is used by the application server to send messages to the Push Server.

    端点是一个推送服务器URL,后跟一个唯一的用户标识符。 应用程序服务器使用此URL将消息发送到Push Server。
  • getKey method returns two keys: auth is an authentication secret generated by browser and p256dh is a public P-256 ECDH key that can be used to encrypt push messages.

    getKey方法返回两个密钥:auth是由浏览器生成的身份验证密钥,而p256dh是可用于加密推送消息的公共P-256 ECDH密钥。

Both keys will be used by the application server to send message data to the service worker. The endpoint defines where to send push messages, and the keys define how to encrypt them. You need to send both values to your application server, and it's completely up to you how you send them.

应用程序服务器将使用这两个密钥将消息数据发送给服务工作者。 端点定义将推送消息发送到的位置,密钥定义如何对其进行加密。 您需要将这两个值都发送到您的应用程序服务器,这完全取决于您如何发送它们。

第三轮:推送消息 (Round 3: Push Message)

The third round is sending Push messages. This round occurs when something urgent and relevant happens that the user needs to know. For example, if the user's flight is delayed or he received a new message in a chat.

第三轮是发送推送消息。 当用户需要知道一些紧急且相关的事情时,就会发生此回合。 例如,如果用户的航班延误或他在聊天中收到新消息。

Which parts of the game will be played in this round? The application server sends a push message to the push server. The Push server forwards this message to the browser when the browser is online. The browser wakes up the Service Worker associated with the push subscription used to send this message. And the Service Worker handles this message and shows a Notification to the user.

游戏的哪一部分将在本轮比赛中进行? 应用服务器将推送消息发送到推送服务器。 当浏览器处于联机状态时,Push服务器会将此消息转发到浏览器。 浏览器将唤醒与用于发送此消息的推送订阅关联的Service Worker。 然后,服务人员将处理此消息并向用户显示通知。

alt

The first step in this round is done by the Application Server. The application server requests the delivery of a push message by sending an HTTP POST request to the push server using the push server URL and user identifier from the endpoint received from the web application in the previous round. The content of the encrypted push message is included in the body of the request. This request must use the HTTPS protocol. This protocol provides confidentiality and integrity protection from external parties for subscriptions and push messages.

此轮的第一步是由Application Server完成的。 应用服务器通过使用上一轮从Web应用程序接收到的来自端点的推送服务器URL和用户标识符向推送服务器发送HTTP POST请求,来请求推送消息的传递。 加密的推送消息的内容包含在请求的正文中。 该请求必须使用HTTPS协议。 该协议为订阅和推送消息提供了来自外部各方的机密性和完整性保护。

When the Push Server receives this request, it replies with a response indicating that the push message was accepted and queues the message. This message will remain queued until the browser comes online and the push server delivers the message.

当Push Server收到此请求时,它将回复指示已接受Push消息的响应,并将该消息排队。 该消息将一直排队,直到浏览器联机并且推送服务器传递该消息为止。

POST请求 (POST Request)

POST /{user\_identifier} HTTP/1.1

Host: {push\_server\_url}

TTL: 15

Content-Type: text/plain;charset=utf8

Content-Length: 36

{encrypted\_message}

The Application server may add some additional headers to this request to tell the Push Server how to handle the message:

应用服务器可能会向此请求添加一些其他标头,以告知推送服务器如何处理该消息:

  • Prefer: The application server can include the Prefer header field with the "respond-async" preference to request confirmation from the push server when a push message is delivered and acknowledged by the browser.

    首选:应用程序服务器可以将“首选”标头字段包含在“响应异步”首选项中,以便在浏览器传递并确认推送消息时向推送服务器请求确认。

Prefer: respond-async

首选:response-async

  • Time-to-Live: The push server can improve the reliability of push message delivery by storing push messages for a period. Some push messages are not useful once a certain period is over. So such messages should not be delivered at all. That is why the application server MUST include the TTL (Time-To-Live) header field in the request for push message delivery. The TTL header field contains a value in seconds that suggests how long a push message should be queued by the push server. Once the TTL period is over, the push server MUST NOT attempt to deliver the push message to the browser.

    生存时间:推送服务器可以通过存储推送消息一段时间来提高推送消息传递的可靠性。 一段时间结束后,某些推送消息将不再有用。 因此,此类消息完全不应传递。 这就是为什么应用服务器必须在推送消息传递请求中包括TTL(生存时间)标头字段。 TTL标头字段包含一个以秒为单位的值,该值表明推送服务器应将推送消息排队多长时间。 TTL周期结束后,推送服务器务必不要尝试将推送消息传递到浏览器。

TTL: 15

TTL:15

  • Urgency: For a battery-powered device, it is often critical to avoid consuming resources to receive trivial messages, so it is helpful if an application server can define the urgency of a message and if the browser can request delivering only messages of a specific urgency. The application server MAY include message urgency in the request for push message delivery. The possible values are "very-low" / "low" / "normal" / "high".

    紧急度:对于电池供电的设备,避免消耗大量资源来接收琐碎的消息通常非常关键,因此,如果应用程序服务器可以定义消息的紧急度,并且浏览器可以仅请求发送特定紧急度的消息,则这将非常有帮助。 应用服务器可以在发送推送消息的请求中包括消息紧急性。 可能的值为“非常低” /“低” /“正常” /“高”。

Urgency: high

紧急程度:高

  • Topic: A push message that has been queued by the push server can be replaced with new content. If the browser is offline during the time when the push messages are sent, updating a push message avoids sending outdated messages to the browser. Only push messages that have been assigned a topic can be replaced. A push message with a topic replaces any outstanding push message with an identical topic.

    主题:可以将推送服务器已排队的推送消息替换为新内容。 如果在发送推送消息期间浏览器处于脱机状态,则更新推送消息可避免将过时的消息发送到浏览器。 只能替换已分配了主题的推送消息。 具有主题的推送消息将替换具有相同主题的所有未完成的推送消息。

Topic: upd

主题:upd

讯息加密 (Message Encryption)

A Push message may not include any data at all. In this case, the POST request will have an empty body, and the service worker may need to fetch some necessary data before showing a Notification to the user. Or the application server can send some data called a payload along with the push message, so the service worker can avoid making the extra request. However, all payload data must be encrypted. It is an important point. HTTPS provides secure communication between the browser and the application server, because you trust your application server.

推送消息可能根本不包含任何数据。 在这种情况下,POST请求的主体为空,并且服务工作者可能需要获取一些必要的数据,然后才能向用户显示通知。 或者,应用程序服务器可以与推送消息一起发送一些称为有效负载的数据,因此服务工作者可以避免发出额外的请求。 但是,所有有效负载数据都必须加密。 这是重要的一点。 HTTPS在浏览器和应用程序服务器之间提供安全的通信,因为您信任应用程序服务器。

However, the browser chooses which push server will be used to deliver the data, so you, as the application developer, cannot control it. HTTPS can only guarantee that no one can read or modify the message in transit to the push server. But once the push server receives it, it can theoretically re-transmit the data to third parties or modify it. To protect against this problem, you must encrypt the data to ensure that a push server can't read or modify the payload data.

但是,浏览器选择将使用哪个推送服务器来传递数据,因此作为应用程序开发人员,您将无法控制它。 HTTPS只能保证没有人可以读取或修改传递到推送服务器的消息。 但是,一旦推送服务器收到数据,它就可以从理论上将数据重新传输给第三方或对其进行修改。 为了防止出现此问题,您必须加密数据以确保推送服务器无法读取或修改有效负载数据。

You must encrypt a push message using elliptic-curve Diffie-Hellman (ECDH) on the P-256 curve. The browser generates an ECDH key pair and authentication secret that it associates with each subscription it creates. The ECDH public key and the authentication secret are sent to the Application Server with other details of the push subscription and it's used to encrypt the message data.

您必须使用P-256曲线上的椭圆曲线Diffie-Hellman(ECDH)加密推送消息。 浏览器会生成ECDH密钥对和与其创建的每个订阅相关联的身份验证密钥。 ECDH公钥和身份验证密钥将与推送订阅的其他详细信息一起发送到Application Server,并用于加密消息数据。

I highly recommend that you use a library for encrypting payload data and do not implement it manually. Although, you can find a detailed description of the encryption process in the Web Push Protocol, the standard may be changed, and then you would need to adjust and verify your implementation.

我强烈建议您使用一个库来加密有效载荷数据,不要手动实现它。 虽然,您可以在Web Push Protocol中找到有关加密过程的详细说明,但是可能会更改标准,然后需要调整和验证实现。

Here is the encryption library for Node.js developed by Google. There are also libraries for other languages.

这是Google 为Node.js开发的加密库 。 也有其他语言的库。

自愿识别应用程序服务器 (Voluntary Identification of the Application Server)

This is where our applicationServerKey that we sent to the subscribe method in the previous round plays its part. The Application Server needs to prove that it is allowed to send Notifications to the user and the Push Server needs to validate this step.

这是我们在上一轮中发送给subscription方法的applicationServerKey发挥作用的地方。 Application Server需要证明它被允许向用户发送通知,而Push Server需要验证这一步骤。

To do this, the Application Server adds an Authorization header, which contains information signed with the private key, coupled with its public key – applicationServerKey – shared with the Push Server when the PushSubscription was created. When the push server receives this request, it validates this signature, checks that the request was signed using the private key coupled with the applicationServerKey associated with the PushSubscription receiving the request . If the signature is valid, the push server knows that it is a valid push message from the authorized Application Server. It provides security protection that prevents anyone else from sending messages to an application's users.

为此,Application Server添加一个Authorization标头,其中包含用私钥签名的信息以及在创建PushSubscription时与Push Server共享的公用密钥applicationServerKey。 当推送服务器接收到此请求时,它将验证此签名,并使用私钥以及与接收请求的PushSubscription关联的applicationServerKey来检查该请求是否已签名 如果签名有效,则推送服务器从授权的应用程序服务器获知这是有效的推送消息。 它提供了安全保护,可以防止其他任何人向应用程序的用户发送消息。

POST /{user\_identifier} HTTP/1.1

Host: {push\_server\_url}

TTL: 15

Content-Length: 136

Authorization: Bearer

eyJ0eXAi...

Crypto-Key: p256ecdsa=BA1Hxzy...

{encrypted\_message}

The Authorization Header contains a JSON Web Token (JWT). This token is a way of sending a message to a third party, so the receiver can validate who sent it.

授权标头包含一个JSON Web令牌(JWT)。 此令牌是一种将消息发送给第三方的方法,因此接收者可以验证谁发送了消息。

It includes the following claims:

它包括以下声明:

  • "aud" (Audience) claim in the token MUST include the unicode serialization of the origin of the push server URL. This binds the token to a specific push server.

    令牌中的“ aud”(受众)声明必须包括推送服务器URL的来源的unicode序列化。 这会将令牌绑定到特定的推送服务器。
  • "exp" (Expiry) claim MUST be included with the time that the token expires. This limits the time that a token is valid. An "exp" claim MUST NOT be more than 24 hours from the time of the request.

    令牌到期的时间必须包括“ exp”(到期)声明。 这限制了令牌有效的时间。 从请求之日起,“ exp”声明不得超过24小时。
  • "sub" (Subject) claim in the JWT. The "sub" claim SHOULD include a contact URI for the application server as either a "mailto:" (email) or an "https:" URI.

    JWT中的“ sub”(主题)声明。 “ sub”声明应包括应用服务器的联系URI,作为“ mailto:”(电子邮件)或“ https:” URI。

There is an additional "Crypto-Key" header that includes the base64url-encoded ApplicationServerKey.

还有一个额外的“ Crypto-Key”标头,其中包含以base64url编码的ApplicationServerKey。

处理推送消息 (Handling the Push Message)

The Application Server sent a push message to the user, the Push Server validated it and forwarded it to the browser. The Browser woke up the Service Worker and sent a push event to it. And the Service Worker handled this event and processed the push message.

应用服务器将推送消息发送给用户,推送服务器对其进行验证并将其转发给浏览器。 浏览器唤醒了Service Worker,并向其发送了推送事件。 然后,Service Worker处理此事件并处理了推送消息。

The last step of this round is made by the Service Worker. This code should be added to your Service Worker:

此轮的最后一步是由服务人员进行的。 此代码应添加到您的服务人员:

self.addEventListener('push', function(event) {

  var data = event.data.json();

  event.waitUntil(self.registration.showNotification(data.title, {

    body: data.body,

    icon: data.icon,

    tag: data.tag

  }));

});

The Service Worker's push event listener function receives an event object as a parameter. This event object includes push message data as a property. And the handler shows a Notification based on this data by calling a showNotification method. You need to pass a notification title and a Notification configuration object to the method. These config objects may contain different parameters defining the Notification: body for Notification text, icon, image, vibrate, and some others.

Service Worker的push事件侦听器功能接收事件对象作为参数。 该事件对象包括推送消息数据作为属性。 然后,处理程序通过调用showNotification方法基于此数据显示通知。 您需要将通知标题和Notification配置对象传递给该方法。 这些配置对象可能包含定义Notification的不同参数:Notification文本,图标,图像,振动等主体。

I would like to cover two important points:

我想介绍两个要点:

  • Firefox allows a limited number (quota) of push messages to be sent to an application without showing a Notification, and the limit is refreshed each time the site is visited. But Chrome requires that every push message shows a notification, and if you don't show a Notification, Chrome will show a default notification.

    Firefox允许在不显示通知的情况下将有限数量(配额)的推送消息发送到应用程序,并且每次访问该站点时都会刷新限制。 但是Chrome要求每条推送消息都必须显示一个通知,并且如果您不显示通知,Chrome将显示默认通知。
  • waitUntil method tells the browser to keep the Service Worker running until the promise that is passed to this method has been resolved. If you do not add this method, the Browser will shut down the Service Worker immediately, and the Notification will not be shown.

    waitUntil方法告诉浏览器使Service Worker保持运行状态,直到已解决传递给此方法的承诺。 如果不添加此方法,浏览器将立即关闭Service Worker,并且不会显示通知。

处理通知点击 (Handling the Notification Click)

The Service Worker needs to handle a Notification click. One of the most common responses is to close a notification and open a window / tab to a specific URL. We can do this with the clients.openWindow() API.

服务人员需要处理通知单击。 最常见的响应之一是关闭通知并打开特定URL的窗口/选项卡。 我们可以使用client.openWindow() API来做到这一点。

self.addEventListener('notificationclick', function(event) {

  event.notification.close();

  event.waitUntil(clients.openWindow('http://mywebsite.com'));

});

动作通知 (Notifications with Actions)

The Notification can also contain actions – buttons with some text. You can define them using an actions parameter of the notification config object. And then in the notificationclick handler, you can check which button was clicked.

通知还可以包含操作-带有一些文本的按钮。 您可以使用通知配置对象的action参数定义它们。 然后在notificationclick处理程序中,您可以检查单击了哪个按钮。

self.registration.showNotification(data.title, {

  body: data.body,

  actions: [

    { action: 'ok', title: 'Yes' },

    { action: 'decline', title: 'No' }

  ]

});

self.addEventListener('notificationclick', function(event) {

  if (event.action == 'ok') {

    // do something

  }

});

通知关闭 (Notification Close)

And the last thing that you have to handle is a notificationcloseevent. It happens when a user doesn't click any action button or notification itself, but does click the close button. It is a good place to perform some logging for example.

最后,您需要处理的是notificationcloseevent。 当用户没有单击任何操作按钮或通知本身,而是单击关闭按钮时,就会发生这种情况。 例如,这是执行一些日志记录的好地方。

self.addEventListener('notificationclose', function(event) {

  //do something

});

There is one exception to the rule to always show a Notification. It is not mandatory to show a Notification when the user is actively using your application. But what if you still want to let the user know that an event has occurred? One approach is to send a message from the service worker to the page, this way the web page can show the user a notification or update, informing him of the event.

始终显示通知的规则有一个例外。 当用户正在积极使用您的应用程序时,显示通知不是强制性的。 但是,如果您仍然想让用户知道事件已发生怎么办? 一种方法是将消息从服​​务工作者发送到页面,这样,网页可以向用户显示通知或更新,从而将事件通知给用户。

To handle this case, we can check if any window client is focused and send the message to every client using the postMessage method. This method is a common way to organize a communication channel between a Service Worker and the page. And if no client window is focused, we can show a normal Notification.

为了处理这种情况,我们可以检查是否有任何窗口客户端处于焦点状态,并使用postMessage方法将消息发送给每个客户端。 此方法是组织Service Worker和页面之间的通信通道的常用方法。 并且如果没有客户窗口聚焦,我们可以显示一个正常的通知。

if (focused) {

  clients.forEach(function(client){

    client.postMessage({

      message: data.message

    });

  });

} else {

  return self.registration.showNotification(data.title, {

    body: data.message

  });

}

The third round is the most important round. It requires the most effort to implement. You need to manage the whole push message from the Application Server to the ServiceWorker and handle them in the the ServiceWorker's implementation.

第三轮是最重要的一轮。 它需要最大的努力来实施。 您需要管理从应用程序服务器到ServiceWorker的整个推送消息,并在ServiceWorker的实现中进行处理。

第四轮:退订 (Round 4: Unsubscription)

The fourth round is unsubscription from Web Push Notifications. It happens when a user doesn't want to receive Web Push Notifications from your application anymore. This round involves the same players as the Subscription round – Web Application, Browser, Application Server, and Push Server.

第四轮取消订阅Web推送通知。 当用户不再希望从您的应用程序接收Web推送通知时,就会发生这种情况。 此轮与订阅轮涉及相同的参与者-Web应用程序,浏览器,应用程序服务器和推送服务器。

The whole process is similar to the subscription process. Your web application asks the browser to unsubscribe the user from receiving Web Push Notifications. The browser sends a request to the Push Server to remove the push subscription. The Push Server replies to the browser with the confirmation and the browser forwards this confirmation to your web application. As the last step, your web application sends the confirmation to the application server. And the application server removes the subscription record from the database or other storage.

整个过程类似于订阅过程。 您的Web应用程序要求浏览器取消订阅用户以接收Web推送通知。 浏览器向推送服务器发送删除推送订阅的请求。 推送服务器将确认信息回复到浏览器,浏览器将此确认信息转发到您的Web应用程序。 最后一步,您的Web应用程序将确认发送到应用程序服务器。 然后,应用程序服务器从数据库或其他存储中删除订阅记录。

alt

Your web application is the main player, and the code I will show you should be added to your Web App:

您的Web应用程序是主要角色,我将向您显示的代码应添加到您的Web应用程序中:

registration.pushManager.getSubscription().then(function(subscription) {

  if (subscription) {

    return subscription.unsubscribe().then(function(successful) {

      removePushSubscription(subscription);

    }).catch(function(e) {

      //error handling

    });

  }

})

.catch(function(error) {

  //error handling

})

We request a Subscription object from a pushManager, when the promise is resolved, we call an unsubscribe method of the subscription object. And if the subscription was successfully removed from the Push Server, we call a method that sends a request to the Application Server to delete this subscription.

我们从pushManager请求一个Subscription对象,当承诺被解决时,我们调用该订阅对象的unsubscribe方法。 并且,如果已成功将订阅从Push Server中删除,我们将调用一种方法,该方法向Application Server发送请求以删除此订阅。

附加回合:订阅到期 (Additional Round: Subscription Expiration)

There is also one additional round – Subscription expiration. It happens when the subscription is about to expire (the server gets overloaded, or if a user is offline for a long time). This is highly server-dependent, so the exact behavior is difficult to predict.

另外还有一轮-订阅到期。 当订阅即将到期(服务器过载,或者用户长时间离线)时,会发生这种情况。 这与服务器高度相关,因此很难预测确切的行为。

alt

In any case, you can handle this situation by watching for the pushsubscriptionchange event in your Service Worker and providing an event handler; this event is fired only in this specific case.

无论如何,您可以通过在Service Worker中监视pushsubscriptionchange事件并提供事件处理程序来处理这种情况。 仅在此特定情况下会触发此事件。

self.addEventListener('pushsubscriptionchange',

  function(registration, newSubscription, oldSubscription) {

    removePushSubscription(oldSubscription);

    savePushSubscription(newSubscription);

});

In the event handler, you need to remove the old subscription passed as a first parameter from the Application Server and save the new one passed as a second parameter.

在事件处理程序中,您需要从Application Server中删除作为第一个参数传递的旧订阅,并保存作为第二个参数传递的新订阅。

规格状态 (State of Specifications)

This is the current state of the specifications describing the rules of all these rounds. Only the Notification API and Web Push specifications have states of living and proposed standards. The Push API, Push Message Encryption, and VAPID specifications are still drafts.

这是描述所有这些回合规则的规范的当前状态。 只有Notification API和Web Push规范具有生存状态和提议的标准。 Push API,Push Message Encryption和VAPID规范仍然是草案。

SpecificationState
Push APIWorking draft
Notification APILiving standard
HTTP Web PushProposed standard
Push Message Encryption protocolInternet-draft
VAPID protocolInternet-draft
规范
推送API 工作草案
通知API 生活水平
HTTP Web推送 拟议标准
推送消息加密协议 互联网草稿
VAPID协议 互联网草稿

浏览器支持 (Browser Support)

This is a list of browsers supporting this new functionality.

这是支持此新功能的浏览器列表。

BrowserDesktopMobile
ChromeYesYes
FirefoxYesYes
EdgeBetaBeta
SafariYesNo
OperaYesYes
IENoNo
浏览器 桌面 移动
Chrome
火狐浏览器
边缘 贝塔 贝塔
苹果浏览器 没有
歌剧
IE浏览器 没有 没有

The browser support changes quickly. Only Chrome and Firefox are fully supporting this functionality. Opera started supporting it recently. Safari supports it on Mac OS but in a different way. Apple's implementation differs from the official specification. They have the same players and the same basic concepts, but it's a slightly different API and technical implementation. For example, Notifications are stored in a MacOS Notification center.

浏览器支持变化很快。 仅Chrome和Firefox完全支持此功能。 Opera最近开始支持它。 Safari在Mac OS上支持它,但是以不同的方式。 苹果的实现方式与官方规范不同。 它们具有相同的参与者和相同的基本概念,但是API和技术实现略有不同。 例如,通知存储在MacOS通知中心中。

In Edge, Web Push Notifications are available in the Windows Insider Preview release on desktop and tablets. And Microsoft announced that it will be available to all Microsoft Edge customers in EdgeHTML 14. IE doesn't support web push notifications, but I guess no one would expect that.

在Edge中,Web推送通知在台式机和平板电脑上的Windows Insider Preview版本中可用。 微软宣布将在EdgeHTML 14中向所有Microsoft Edge客户开放。IE不支持Web推送通知,但我想没人会期望这样做。

The biggest missing piece currently is iOS. iOS doesn't support push notifications, but it was mentioned in the 5 year plan at the WebKit contributors meeting in 2015. So, hopefully it will be supported one day.

当前最大的遗失部分是iOS。 iOS不支持推送通知,但在2015年WebKit贡献者会议的5年计划中提到了iOS。因此,希望有一天会得到支持。

结论 (Conclusion)

Web Push Notification technology is ready to be used widely. It helps you to communicate with your users in a more efficient way, engages users by providing urgent and relevant notifications, and it makes web applications better in general.

Web推送通知技术已准备就绪,可以广泛使用。 它可以帮助您以更有效的方式与用户进行通信,通过提供紧急且相关的通知来吸引用户,并且可以使Web应用程序总体上变得更好。

Try it out in your applications. Sencha Cmd 6.5 supports the following progressive web app features: Add to Home Screen Banner and Caching with Service Workers. Read the Sencha Cmd docs to learn more or download a free trial of Sencha Ext JS where you'll get access to over 115 components and tools, including Sencha Cmd.

在您的应用程序中尝试一下。 Sencha Cmd 6.5支持以下渐进式Web应用程序功能:添加到主屏幕横幅和使用Service Workers进行缓存。 阅读Sencha Cmd文档以了解更多信息,或下载 Sencha Ext JS 的免费试用版 ,在这里您可以使用115种以上的组件和工具,包括Sencha Cmd。

翻译自: https://www.sitepoint.com/how-to-use-push-notifications-for-web-applications/

安卓web应用推送通知

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值