如果您询问开发者网络中缺少什么移动设备功能,推送通知始终位居答案前列。
借助推送通知,用户可以选择及时接收他们喜爱的网站的更新内容,还可以利用具有吸引力的定制内容有效地重新吸引用户。
从 Chrome 版本 42 开始,开发者可以使用 Push API 和 Notification API。
Chrome 中的 Push API 依赖于一些不同的技术,包括网络应用清单和服务工作线程。在本博文中,我们将介绍这些技术,但只介绍启用和运行推送消息所需的最低限度内容。如需更好地了解清单的其他一些功能以及服务工件的离线功能,请访问上面的链接。
我们还将介绍未来版本的 Chrome 中将添加到该 API 的功能,最后是常见问题解答。
为 Chrome 实现推送消息传递
本部分介绍了为了在 Web 应用中支持推送消息传递需要完成的各个步骤。
注册 Service Worker
您需要有服务工作线程才能为网站实现推送消息。原因在于,收到推送消息时,浏览器可以启动服务工作线程,该服务工作线程在后台运行,无需打开网页,并分派事件,以便您决定如何处理该推送消息。
以下是如何在 Web 应用中注册 Service Worker 的示例。注册成功完成后,我们会调用 initialiseState(),我们稍后将介绍此内容。
var isPushEnabled = false;
…
window.addEventListener('load', function() {
var pushButton = document.querySelector('.js-push-button');
pushButton.addEventListener('click', function() {
if (isPushEnabled) {
unsubscribe();
} else {
subscribe();
}
});
// Check that service workers are supported, if so, progressively
// enhance and add push messaging support, otherwise continue without it.
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(initialiseState);
} else {
console.warn('Service workers aren\'t supported in this browser.');
}
});
按钮点击处理脚本会为用户订阅或取消订阅推送消息。isPushEnabled 是一个全局变量,只会跟踪当前是否订阅了推送消息。我们将在整个代码段中引用这些值。
然后,我们会先检查是否支持服务工作线程,然后再注册包含处理推送消息逻辑的 service-worker.js
文件。在这里,我们只是告诉浏览器此 JavaScript 文件是我们网站的服务工作线程。
设置初始状态
注册 service worker 后,我们需要设置界面的状态。
用户希望通过简单的界面为您的网站启用或停用推送消息,并且希望该界面能够及时了解发生的任何变化。换句话说,如果用户为您的网站启用推送消息,然后离开并在一周后返回,您的界面应突出显示已启用推送消息。
您可以在此文档中找到一些用户体验准则,本文将重点介绍技术方面。
这时,您可能认为只有两种状态需要处理,即启用或停用。不过,您还需要考虑与通知相关的一些其他状态。
在启用按钮之前,我们需要检查许多 API,如果一切都受支持,我们可以启用界面并设置初始状态来指示是否已订阅推送消息。
由于其中大多数检查都会导致我们的界面被停用,因此您应将初始状态设为停用。这还有助于避免在网页的 JavaScript 出现问题(例如无法下载 JS 文件或用户停用了 JavaScript)时造成任何混淆。
<button class="js-push-button" disabled>
Enable Push Messages
</button>
使用此初始状态,我们可以在 initialiseState()
方法中(即在注册 Service Worker 之后)执行上述检查。
// Once the service worker is registered set the initial state
function initialiseState() {
// Are Notifications supported in the service worker?
if (!('showNotification' in ServiceWorkerRegistration.prototype)) {
console.warn('Notifications aren\'t supported.');
return;
}
// Check the current Notification permission.
// If its denied, it's a permanent block until the
// user changes the permission
if (Notification.permission === 'denied') {
console.warn('The user has blocked notifications.');
return;
}
// Check if push messaging is supported
if (!('PushManager' in window)) {
console.warn('Push messaging isn\'t supported.');
return;
}
// We need the service worker registration to check for a subscription
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
// Do we already have a push message subscription?
serviceWorkerRegistration.pushManager.getSubscription()
.then(function(subscription) {
// Enable any UI which subscribes / unsubscribes from
// push messages.
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = false;
if (!subscription) {
// We aren't subscribed to push, so set UI
// to allow the user to enable push
return;
}
// Keep your server in sync with the latest subscriptionId
sendSubscriptionToServer(subscription);
// Set your UI to show they have subscribed for
// push messages
pushButton.textContent = 'Disable Push Messages';
isPushEnabled = true;
})
.catch(function(err) {
console.warn('Error during getSubscription()', err);
});
});
}
以下是这些步骤的简要概述:
- 我们检查 ServiceWorkerRegistration 原型中是否有
showNotification
。如果没有它,我们将无法在收到推送消息时显示来自 Service Worker 的通知。 - 我们会检查当前的
Notification.permission
,以确保它不是"denied"
。如果权限被拒绝,则表示在用户在浏览器中手动更改权限之前,您无法显示通知。 - 如需检查是否支持推送消息传递,我们需要检查窗口对象中是否有
PushManager
。 - 最后,我们使用
pushManager.getSubscription()
检查是否已有订阅。如果是,我们会将订阅详情发送到我们的服务器,以确保我们拥有正确的信息,并将界面设置为指示是否已启用推送消息功能。我们将在本文的后面部分介绍订阅对象中存在的详细信息。
我们等到 navigator.serviceWorker.ready
解析完成后再检查订阅并启用推送按钮,因为只有在 Service Worker 处于活动状态后,您才可以实际订阅推送消息。
下一步是处理用户想要启用推送消息的情况,但在此之前,我们需要设置一个 Google Developer Console 项目并向清单添加一些参数,以便使用 Firebase Cloud Messaging (FCM)(以前称为 Google Cloud Messaging (GCM))。
在 Firebase 开发者控制台中创建项目
Chrome 使用 FCM 来处理推送消息的发送和传递;不过,如需使用 FCM API,您需要在 Firebase 开发者控制台中设置项目。
以下步骤仅适用于使用 FCM 的 Chrome、Opera for Android 和三星浏览器。我们将在本文后面部分讨论此功能在其他浏览器中的运作方式。
创建新的 Firebase 开发者项目
首先,您需要在 https://console.firebase.google.com/ 上点击“创建新项目”,创建一个新项目。
添加项目名称并创建项目,然后您将进入项目信息中心:
在此信息中心内,点击左上角项目名称旁边的齿轮图标,然后点击“项目设置”。
在“设置”页面中,点击“Cloud Messaging”标签页。
此页面包含用于推送消息的 API 密钥(我们稍后会用到),以及我们需要在下一部分中添加到 Web 应用清单中的发件人 ID。
添加网络应用清单
对于推送,我们需要添加包含 gcm_sender_id 字段的清单文件,以便成功进行推送订阅。只有 Chrome、适用于 Android 的 Opera 和三星浏览器才需要此参数,以便它们可以使用 FCM / GCM。
当这些浏览器使用 FCM 为用户设备订阅时,会使用 gcm_sender_id。这意味着,FCM 可以识别用户的设备,并确保您的发送者 ID 与相应的 API 密钥相匹配,并且用户已允许您的服务器向其发送推送通知。
以下是一个超级简单的清单文件:
{
"name": "Push Demo",
"short_name": "Push Demo",
"icons": [{
"src": "images/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
}],
"start_url": "/index.html?homescreen=1",
"display": "standalone",
"gcm_sender_id": "<Your Sender ID Here>"
}
您需要将 gcm_sender_id 值设置为 Firebase 项目中的发件人 ID。
将清单文件保存到项目中(manifest.json 是一个不错的名称)后,请在网页的标头中使用以下标记从 HTML 中引用该文件。
<link rel="manifest" href="/manifest.json">
如果您未添加包含这些参数的 Web 清单,则在尝试让用户订阅推送消息时,会收到包含错误 "Registration failed - no sender id provided"
或 "Registration failed -
permission denied"
的异常。
订阅推送消息
现在,您已设置好清单,可以返回网站 JavaScript 了。
如需订阅,您必须对 PushManager 对象调用 subscribe() 方法,您可以通过 ServiceWorkerRegistration 访问该对象。
系统会要求用户授权您的来源发送推送通知。如果没有此权限,您将无法成功订阅。
如果 subscribe() 方法返回的 promise 解析,您将获得一个 PushSubscription 对象,其中包含一个 endpoint。
您应为每位用户保存端点,因为您日后需要使用这些端点发送推送通知。
以下代码会为用户订阅推送消息:
function subscribe() {
// Disable the button so it can't be changed while
// we process the permission request
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = true;
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
serviceWorkerRegistration.pushManager.subscribe()
.then(function(subscription) {
// The subscription was successful
isPushEnabled = true;
pushButton.textContent = 'Disable Push Messages';
pushButton.disabled = false;
// TODO: Send the subscription.endpoint to your server
// and save it to send a push message at a later date
return sendSubscriptionToServer(subscription);
})
.catch(function(e) {
if (Notification.permission === 'denied') {
// The user denied the notification permission which
// means we failed to subscribe and the user will need
// to manually change the notification permission to
// subscribe to push messages
console.warn('Permission for Notifications was denied');
pushButton.disabled = true;
} else {
// A problem occurred with the subscription; common reasons
// include network errors, and lacking gcm_sender_id and/or
// gcm_user_visible_only in the manifest.
console.error('Unable to subscribe to push.', e);
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
}
});
});
}
此时,您的 Web 应用已准备好接收推送消息,但在我们向服务工作器文件添加推送事件监听器之前,不会发生任何事情。
Service Worker 推送事件监听器
收到推送消息后(我们将在下一部分介绍如何实际发送推送消息),您的服务工作线程中会分派一个推送事件,届时您需要显示通知。
self.addEventListener('push', function(event) {
console.log('Received a push message', event);
var title = 'Yay a message.';
var body = 'We have received a push message.';
var icon = '/images/icon-192x192.png';
var tag = 'simple-push-demo-notification-tag';
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
);
});
此代码会注册一个推送事件监听器,并显示包含预定义标题、正文文本、图标和通知标记的通知。此示例中要重点介绍的一个细节是 event.waitUntil()
方法。此方法接受一个 promise,并延长事件处理程序的生命周期(也可以认为是保持服务工作线程处于活动状态),直到 promise settled;在本例中,传递给 event.waitUntil
的 promise 是从 showNotification()
返回的 promise。
通知标记可用作唯一通知的标识符。如果我们向同一端点发送了两条推送消息,且两者之间存在短暂的延迟,并显示带有相同标签的通知,则浏览器会显示第一条通知,并在收到推送消息时将其替换为第二条通知。
如果您想一次显示多个通知,请使用不同的标签,或不使用任何标签。我们将在本文的后面部分介绍一个更完整的显示通知示例。现在,我们先保持简单,看看发送推送消息是否会显示此通知。
发送推送消息
我们已订阅推送消息,我们的 Service Worker 已准备好显示通知,是时候通过 FCM 发送推送消息了。
这仅适用于使用 FCM 的浏览器。
当您将 PushSubscription.endpoint
变量发送到服务器时,FCM 的端点是特殊的。网址末尾有一个参数,即 registration_id
。
端点示例如下:
https://fcm.googleapis.com/fcm/send/APA91bHPffi8zclbIBDcToXN_LEpT6iA87pgR-J-MuuVVycM0SmptG-rXdCPKTM5pvKiHk2Ts-ukL1KV8exGOnurOAKdbvH9jcvg8h2gSi-zZJyToiiydjAJW6Fa9mE3_7vsNIgzF28KGspVmLUpMgYLBd1rxaVh-L4NDzD7HyTkhFOfwWiyVdKh__rEt15W9n2o6cZ8nxrP
FCM 网址为:
https://fcm.googleapis.com/fcm/send
registration_id
为:
APA91bHPffi8zclbIBDcToXN_LEpT6iA87pgR-J-MuuVVycM0SmptG-rXdCPKTM5pvKiHk2Ts-ukL1KV8exGOnurOAKdbvH9jcvg8h2gSi-zZJyToiiydjAJW6Fa9mE3_7vsNIgzF28KGspVmLUpMgYLBd1rxaVh-L4NDzD7HyTkhFOfwWiyVdKh__rEt15W9n2o6cZ8nxrP
这仅适用于使用 FCM 的浏览器。在普通浏览器中,您只需获取一个端点,并以标准方式调用该端点,并且无论网址如何,它都会正常工作。
这意味着,您需要在服务器上检查端点是否适用于 FCM,如果适用,则提取 registration_id。如需在 Python 中执行此操作,您可以执行以下操作:
if endpoint.startswith('https://fcm.googleapis.com/fcm/send'):
endpointParts = endpoint.split('/')
registrationId = endpointParts[len(endpointParts) - 1]
endpoint = 'https://fcm.googleapis.com/fcm/send'
获取注册 ID 后,即可调用 FCM API。您可以点击此处查看 FCM API 参考文档。
调用 FCM 时需要注意以下关键方面:
- 调用 API 时,必须设置值为
key=<YOUR_API_KEY>
的 Authorization 标头,其中<YOUR_API_KEY>
是 Firebase 项目中的 API 密钥。- FCM 使用该 API 密钥来查找相应的发送者 ID,确保用户已授予您的项目权限,并最终确保服务器的 IP 地址已列入该项目的许可名单。
- 适当的
Content-Type
标头(application/json
或application/x-www-form-urlencoded;charset=UTF-8
),具体取决于您是将数据作为 JSON 还是表单数据发送。 - 一组
registration_ids
- 这些是您从用户的端点中提取的注册 ID。
请务必查看相关文档,了解如何从服务器发送推送消息,但如需快速查看 Service Worker,您可以使用 cURL 向浏览器发送推送消息。
将此 c网址 命令中的 <YOUR_API_KEY>
和 <YOUR_REGISTRATION_ID>
替换为您自己的,然后从终端运行该命令。
您应该会看到一条漂亮的通知:
curl --header "Authorization: key=<YOUR_API_KEY>" --header
"Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d
"{\"registration_ids\":[\"<YOUR_REGISTRATION_ID>\"]}"
在开发后端逻辑时,请注意,Authorization 标头和 POST 正文的格式因 FCM 端点而异,因此请检测端点何时为 FCM 端点,并有条件地添加标头并设置 POST 正文格式。对于其他浏览器(希望未来 Chrome 也支持),您需要实现 Web Push 协议。
Chrome 中当前实现的 Push API 的一个缺点是,您无法通过推送消息发送任何数据。没错,什么都没搜到。原因在于,在未来的实现中,载荷数据必须先在服务器上加密,然后才能发送到推送消息端点。这样一来,无论是哪种推送服务提供商,端点都无法轻松查看推送消息的内容。这还可防范其他漏洞,例如 HTTPS 证书验证不当以及服务器和推送服务提供商之间发生的中间人攻击。不过,此加密方式尚不受支持,因此在此期间,您需要执行提取操作,以获取填充通知所需的信息。
更完整的推送事件示例
我们目前看到的通知非常基本,就示例而言,它在涵盖实际应用场景方面做得非常不充分。
实际上,大多数用户都希望先从服务器获取一些信息,然后再显示通知。这些数据可以用来在通知标题和消息中填充特定内容,也可以进一步缓存一些网页或数据,以便在用户点击通知时,在打开浏览器时立即显示所有内容,即使网络在当时不可用也是如此。
在以下代码中,我们从 API 提取一些数据,将响应转换为对象,并使用该对象填充通知。
self.addEventListener('push', function(event) {
// Since there is no payload data with the first version
// of push messages, we'll grab some data from
// an API and use it to populate a notification
event.waitUntil(
fetch(SOME_API_ENDPOINT).then(function(response) {
if (response.status !== 200) {
// Either show a message to the user explaining the error
// or enter a generic message and handle the
// onnotificationclick event to direct the user to a web page
console.log('Looks like there was a problem. Status Code: ' + response.status);
throw new Error();
}
// Examine the text in the response
return response.json().then(function(data) {
if (data.error || !data.notification) {
console.error('The API returned an error.', data.error);
throw new Error();
}
var title = data.notification.title;
var message = data.notification.message;
var icon = data.notification.icon;
var notificationTag = data.notification.tag;
return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
});
}).catch(function(err) {
console.error('Unable to retrieve data', err);
var title = 'An error occurred';
var message = 'We were unable to get the information for this push message';
var icon = URL_TO_DEFAULT_ICON;
var notificationTag = 'notification-error';
return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
})
);
});
值得再次强调的是,event.waitUntil()
会接受一个 promise,从而导致 showNotification()
返回 promise,这意味着在异步 fetch()
调用完成并显示通知之前,我们的事件监听器不会退出。
您会发现,即使出现错误,我们也会显示通知。这是因为,如果我们不这样做,Chrome 就会显示自己的一般通知。
在用户点击通知时打开网址
当用户点击通知时,您的服务工作器中会分派 notificationclick
事件。在处理程序中,您可以执行适当的操作,例如将焦点移至标签页或打开包含特定网址的窗口:
self.addEventListener('notificationclick', function(event) {
console.log('On notification click: ', event.notification.tag);
// Android doesn't close the notification when you click on it
// See: http://crbug.com/463146
event.notification.close();
// This looks to see if the current is already open and
// focuses if it is
event.waitUntil(
clients.matchAll({
type: "window"
})
.then(function(clientList) {
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
if (client.url == '/' && 'focus' in client)
return client.focus();
}
if (clients.openWindow) {
return clients.openWindow('/');
}
})
);
});
此示例会将浏览器打开到网站源的根目录,具体方法是聚焦于现有的同源标签页(如果有),否则打开一个新标签页。
我们专门发布了一篇博文,介绍您可以使用 Notification API 执行的一些操作。
取消订阅用户的设备
您已为用户的设备订阅了推送消息,并且用户正在接收推送消息,但如何取消订阅?
如需取消订阅用户设备,您需要执行的主要操作是:对 PushSubscription 对象调用 unsubscribe()
方法,并从服务器中移除端点(以免发送您知道不会收到的推送消息)。以下代码正是执行此操作:
function unsubscribe() {
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = true;
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
// To unsubscribe from push messaging, you need get the
// subscription object, which you can call unsubscribe() on.
serviceWorkerRegistration.pushManager.getSubscription().then(
function(pushSubscription) {
// Check we have a subscription to unsubscribe
if (!pushSubscription) {
// No subscription object, so set the state
// to allow the user to subscribe to push
isPushEnabled = false;
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
return;
}
var subscriptionId = pushSubscription.subscriptionId;
// TODO: Make a request to your server to remove
// the subscriptionId from your data store so you
// don't attempt to send them push messages anymore
// We have a subscription, so call unsubscribe on it
pushSubscription.unsubscribe().then(function(successful) {
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
isPushEnabled = false;
}).catch(function(e) {
// We failed to unsubscribe, this can lead to
// an unusual state, so may be best to remove
// the users data from your data store and
// inform the user that you have done so
console.log('Unsubscription error: ', e);
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
});
}).catch(function(e) {
console.error('Error thrown while unsubscribing from push messaging.', e);
});
});
}
及时更新订阅
FCM 和您的服务器之间的订阅可能会不同步。请确保您的服务器解析 FCM API 的 send POST 的响应正文,查找 error:NotRegistered
和 canonical_id
结果,如 FCM 文档中所述。
Service Worker 和服务器之间的订阅也可能会不同步。例如,成功订阅/取消订阅后,不稳定的网络连接可能会阻止您更新服务器;或者用户可能会撤消通知权限,从而触发自动取消订阅。通过定期(例如在网页加载时)检查 serviceWorkerRegistration.pushManager.getSubscription()
的结果并将其与服务器同步,处理此类情况。如果您已不再订阅,并且 Notification.permission == 'granted',您可能还希望自动重新订阅。
在 sendSubscriptionToServer()
中,您需要考虑在更新 endpoint
时如何处理失败的网络请求。一种解决方案是在 Cookie 中跟踪 endpoint
的状态,以确定服务器是否需要最新详细信息。
完成上述所有步骤后,您便可以在 Chrome 46 中全面实现 Web 版推送消息传递。但仍有一些规范化功能可以简化操作(例如用于触发推送消息的标准 API),但此版本可让您立即开始将推送消息构建到您的 Web 应用中。
如何调试您的 Web 应用
在实现推送消息时,错误会出现在以下两个位置之一:您的网页或您的服务工作器。
您可以使用 DevTools 调试网页中的 bug。您可以通过以下两种方式调试 Service Worker 问题:
- 依次转到 chrome://inspect > Service Worker。除了当前正在运行的服务工作器之外,此视图不会提供太多信息。
- 前往 chrome://serviceworker-internals,您可以在此处查看 Service Worker 的状态,以及查看是否存在错误。在开发者工具提供类似的功能集之前,此页面只是临时页面。
对于刚开始接触服务工作线程的用户,我能提供的最佳提示之一就是使用名为“Open DevTools window and pause JavaScript execution on service worker startup for debugging”(在服务工作线程启动时打开 DevTools 窗口并暂停 JavaScript 执行以进行调试)的复选框。此复选框会在服务工作线程开头添加一个断点并暂停执行,以便您恢复或逐步执行服务工作线程脚本,并查看是否遇到任何问题。
如果 FCM 和您的服务工件的推送事件之间似乎存在问题,那么您无法查看 Chrome 是否收到了任何内容,因此无法采取太多措施来调试问题。关键要确保的是,当服务器进行 API 调用时,FCM 的响应是否成功。该代码将如下所示:
{"multicast_id":1234567890,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1234567890"}]}
请注意 "success": 1
响应。如果您看到失败,则表示 FCM 注册 ID 有问题,并且系统未将推送消息发送到 Chrome。
调试 Chrome(Android 版)上的 Service Worker
目前,在 Android 版 Chrome 上调试服务工件并不容易。您需要前往 chrome://inspect,找到您的设备,然后查找名称为“Worker pid:....”(包含服务工作器的网址)的列表项。
推送通知的用户体验
Chrome 团队一直在整理一份有关推送通知用户体验最佳实践的文档,以及一份介绍使用推送通知时的一些极端情况的文档。
Chrome 和开放网络上的推送消息的未来
本部分将详细介绍此实现的一些 Chrome 专用部分(您应予以留意),以及与其他浏览器实现的不同之处。
网络推送协议和端点
Push API 标准的优点在于,您应该能够通过实现网络推送协议获取端点,将其传递给服务器并发送推送消息。
Web Push 协议是一种推送服务提供商可以实现的新标准,让开发者不必担心推送服务提供商是谁。其基本思路是,避免开发者需要注册 API 密钥并发送格式特殊的数据(如使用 FCM 时所需)。
Chrome 是第一个实现 Push API 的浏览器,而 FCM 不支持 Web Push 协议,因此 Chrome 需要 gcm_sender_id
,并且您需要为 FCM 使用 RESTful API。
Chrome 的最终目标是朝着在 Chrome 和 FCM 中使用网络推送协议这一方向发展。
在此之前,您需要检测端点“https://fcm.googleapis.com/fcm/send”,并将其与其他端点分开处理,即以特定方式设置载荷数据的格式并添加授权密钥。
如何实现 Web Push 协议?
Firefox Nightly 目前正在开发推送功能,很可能是首个实现 Web Push 协议的浏览器。
常见问题解答
规格在哪里?
https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ https://w3c.github.io/push-api/ https://notifications.spec.whatwg.org/
如果我的网站存在多个来源,或者我同时拥有网站版和原生版网站,我可以防止收到重复通知吗?
这个问题暂时没有解决办法,不过你可以跟踪 Chromium 的进展。
理想情况下,您应为用户设备提供某种 ID,然后在服务器端匹配原生应用和 Web 应用订阅 ID,并决定向哪个 ID 发送推送消息。您可以通过屏幕尺寸、设备型号以及在 Web 应用和原生应用之间共享生成的密钥来实现此目的,但每种方法各有利弊。
为什么需要 gcm_sender_id?
必须执行此操作,Chrome、Android 版 Opera 和三星浏览器才能使用 Firebase Cloud Messaging (FCM) API。目标是在标准最终确定且 FCM 可以支持 Web 推送协议时使用该协议。
为什么不使用 Web 套接字或服务器发送的事件 (EventSource)?
使用推送消息的优势在于,即使页面关闭,您的 Service Worker 也会被唤醒并能够显示通知。关闭网页或浏览器时,Web Sockets 和 EventSource 的连接会关闭。
如果我不需要后台事件传送,该怎么办?
如果您不需要后台传送,Web Sockets 是一个很好的选择。
在什么情况下可以使用不显示通知的推送(即静默后台推送)?
虽然目前还没有推出此功能的时间表,但我们打算实现后台同步,并且相关讨论尚未确定或规范,但关于如何启用静默推送和后台同步。
为什么需要使用 HTTPS?如何在开发期间解决此问题?
Service Worker 需要安全的来源,以确保 Service Worker 脚本来自预期的来源,而不是来自中间人攻击。目前,这意味着在正式版网站上使用 HTTPS,但在开发期间可以使用 localhost。
浏览器支持情况如何?
Chrome 在其稳定版中支持此功能,Mozilla 正在 Firefox Nightly 中开发推送功能。 如需了解详情,请参阅实现 Push API bug;您可以在此处跟踪其通知实现情况。
我可以在一段时间后移除通知吗?
目前无法执行此操作,但我们计划添加支持,以便获取当前可见通知的列表。如果您有在通知显示创建后为其设置到期时间的用例,我们非常乐意了解,因此请添加评论,我们会将其转交给 Chrome 团队。
如果您只需要在特定时间段后停止向用户发送推送通知,并且不关心通知保持可见的时间长短,则可以使用 FCM 的存活时间 (ttl) 参数,点击此处了解详情。
Chrome 中的推送消息有哪些限制?
本文中列出了一些限制:
- Chrome 将 CCM 用作推送服务,这会产生一些专有要求。我们正在共同努力,看看未来是否可以提升其中的一些机制。
- 您必须在收到推送消息时显示通知。
- 桌面版 Chrome 有一个限制,即如果 Chrome 未运行,则不会收到推送消息。这与 ChromeOS 和 Android 不同,在 ChromeOS 和 Android 中,系统会始终接收推送消息。
我们不应该使用 Permissions API 吗?
Permission API 已在 Chrome 中实现,但不一定会在所有浏览器中提供。您可以点击此处了解详情。
当我点击通知时,为什么 Chrome 无法打开上一个标签页?
此问题仅会影响目前未由 Service Worker 控制的网页。您可以点击此处了解详情。
如果通知在用户设备收到推送时已过期,该怎么办?
您必须在收到推送消息时始终显示通知。如果您想要发送通知,但该通知只在特定时间段内有效,则可以在 CCM 上使用“time_to_live”参数,以便 FCM 在通知过期后不会发送推送消息。
如果我发送了 10 条推送消息,但只希望设备接收一条,会发生什么情况?
FCM 有一个“collapse_key”参数,您可以使用该参数告知 FCM 将具有相同“collapse_key”的所有待处理消息替换为新消息。