开放 Web 上的推送通知

Matt Gaunt

如果您询问其他开发者,Google Play 上 那么推送通知始终位于列表靠前的位置。

通过推送通知,用户可以选择接收他们 并让您能够通过量身定制的引人入胜的内容有效地重新吸引这些用户。

从 Chrome 42 版开始,Push APINotification API 开发者。

Chrome 中的 Push API 依赖于几项不同的技术,包括 Web 应用清单Service Worker。 在这篇博文中,我们将介绍所有这些技术 以便启动并运行推送消息为了更好地了解 清单的其他功能以及 Service Worker 的离线功能, 请访问以上链接。

我们还将介绍在以后的 Chrome 版本中向 API 中添加哪些功能, 最后会提供一个常见问题解答

为 Chrome 实现推送消息

本部分介绍了支持推送功能需要完成的各个步骤 消息功能

注册 Service Worker

需要一个 Service Worker 来实现推送消息 。原因在于当收到推送消息时 浏览器可以启动一个 Service Worker,该 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 之前,我们会检查 Service Worker 是否受支持 该文件包含处理推送消息的逻辑。这里我们 只是告诉浏览器此 JavaScript 文件是 Service Worker

设置初始状态

Chrome 中已启用和已停用推送消息的用户体验示例。

注册 Service Worker 后,我们需要设置界面的状态。

用户希望通过一个简单的界面为您的网站启用或停用推送消息, 并希望它能及时掌握所发生的任何变化。在其他 如果他们为网站启用了推送消息功能, 一周后,界面中会突出显示推送消息已启用。

您可以在此文档中找到一些用户体验指南, 在本文中,我们将重点介绍技术方面。

此时,您可能以为只有两种状态需要处理, 。但周围还有其他一些州 您需要考虑哪些通知

一张示意图,突出显示了 Chrome 中推送的不同注意事项和状态

在启用按钮之前,我们需要检查许多 API,并且 如果一切都受支持,我们可以启用界面并将初始状态 指示推送消息是否已订阅。

这些检查中的大多数都会导致界面被停用,因此您应该 将初始状态设为“disabled”。这样也避免了 网页的 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 解决后,再检查是否有 订阅并启用推送按钮(因为它仅在服务之后) 工作器处于活动状态,您可以订阅推送消息。

下一步是处理以下情况:用户想要启用推送消息, 我们需要先设置一个 Google Developer Console 项目 并向我们的清单文件添加一些参数 使用 Firebase Cloud Messaging (FCM), 以前称为 Google Cloud Messaging (GCM)。

在 Firebase 开发者控制台上创建项目

Chrome 使用 FCM 处理推送消息的发送和传递;然而, 使用 FCM API,您需要在 Firebase Developer Console 上设置一个项目。

以下步骤仅适用于 Chrome、Android 版 Opera 和三星 使用 FCM 的浏览器。我们将在本文的后面部分讨论该方法在其他浏览器中是如何工作的。

创建新的 Firebase 开发者项目

首先,您需要在 https://console.firebase.google.com/ 上创建一个新项目 点击“Create New Project”即可

新建 Firebase 项目的屏幕截图

添加项目名称,创建项目,系统会将您转到该项目 信息中心:

Firebase 项目首页

在此信息中心内,点击顶部项目名称旁边的齿轮图标 然后点击“项目设置”

Firebase 项目设置菜单

在设置页面中,点击“Cloud Messaging”标签页。

Firebase 项目 Cloud Messaging 菜单

本页面包含用于推送消息功能的 API 密钥(稍后我们会用到), 以及下一个所需的发送者 ID。 部分。

添加 Web 应用清单

对于推送,我们需要添加一个带有 gcm_sender_id 字段的清单文件, 才能成功推送订阅只有 Chrome、Opera(Android 版)和三星浏览器,以便可以使用 FCM / GCM。

这些浏览器在订阅用户时会用到 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 项目。

在项目中保存清单文件后(manifest.json 是很好的选择), 名称),请从 HTML 中引用它,并在 页面。

<link rel="manifest" href="/manifest.json">

如果您不使用这些参数添加网络清单,就会出现例外情况 当您尝试订阅用户推送消息时,系统会显示错误 "Registration failed - no sender id provided""Registration failed - permission denied"

订阅推送消息

现在您已经设置了清单,可以返回到网站的 JavaScript 了。

要进行订阅,您必须调用 subscribe() 方法 PushManager 对象, 您可以通过 ServiceWorkerRegistration

这将要求用户向您的来源授予发送推送的权限 通知。如果没有此权限,您将无法成功 订阅。

如果 promise 返回 subscribe() 方法进行解析,您将获得一个 PushSubscription 对象,该对象包含一个端点

对于每个可连接的端点, 用户,因为稍后您需要他们发送推送消息。

以下代码可为用户订阅推送消息功能:

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 文件添加推送事件监听器时,才会触发。

Service Worker 推送事件监听器

当收到推送消息时(我们将介绍 推送事件 将在 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 并扩展 事件处理脚本的生命周期(或者可以视为 worker 处于活动状态),直到 promise 开始 已解决; 在本例中,传递给 event.waitUntil 的 promise 是返回的 promise 来自:showNotification()

通知标记的作用是用作 唯一通知的标识符。如果我们向同一个 在端点之间设置短暂的延迟,以及显示通知 具有相同标记,浏览器将显示第一条通知,并将其替换为 收到推送消息时的第二个通知。

如果您想一次显示多条通知,则使用其他标签,或者 完全没有标记。 在本专精课程稍后的部分中 信息。现在,为简单起见,看看发送推送消息是否会显示 此通知。

发送推送消息

我们已订阅推送消息,我们的 Service Worker 已准备好显示 所以现在可以通过 FCM 发送推送消息了。

这仅适用于使用 FCM 的浏览器。

PushSubscription.endpoint 变量发送到服务器后, 端点很特殊。网址末尾有一个参数 是 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 时,请注意以下几个重要方面:

  • 值为 key=&lt;YOUR_API_KEY&gt;Authorization 标头 必须在调用该 API 时设置,其中 &lt;YOUR_API_KEY&gt; 是 来自 Firebase 项目的 API 密钥。
    • FCM 使用该 API 密钥查找相应的发送者 ID, 该用户已经为您的项目授予了权限, 确保服务器的 IP 地址已列入该项目的许可名单。
  • 适当的 Content-Type 标头 application/jsonapplication/x-www-form-urlencoded;charset=UTF-8,具体取决于您是否 将数据作为 JSON 或表单数据发送。
  • registration_ids 的数组 - 这些是您想要的注册 ID 从用户的端点中提取数据。

请务必查看文档 如何从服务器发送推送消息, 但如需快速查看 Service Worker,您可以使用 cURL 向浏览器发送推送消息。

交换 &lt;YOUR_API_KEY&gt;&lt;YOUR_REGISTRATION_ID&gt; 运行此 c网址 命令,然后从终端运行该命令。

您应该会看到一条出色的通知:

    curl --header "Authorization: key=<YOUR_API_KEY>" --header
    "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d
    "{\"registration_ids\":[\"<YOUR_REGISTRA>TION_ID\"]}"
来自 Android 版 Chrome 的推送消息示例。

在开发后端逻辑时,请记住授权标头和 POST 正文的格式特定于 FCM 端点,因此检测 端点用于 FCM,并有条件地添加标头并设置 POST 正文的格式。 对于其他浏览器(以后也有可能为 Chrome 浏览器), Web 推送协议

当前在 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 事件 在 Service Worker 中运行。在处理程序中,您可以执行适当的操作, 例如聚焦标签页或打开特定网址的窗口:

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 执行的一些操作

取消订阅用户的设备

您已订阅用户的设备,他们也收到了推送消息,但是如何 退订这些邮件?

取消订阅用户设备的主要操作是调用 unsubscribe() 方法(针对 PushSubscription 对象并从服务器中移除端点(这样您就无需 您知道自己不会收到这些推送消息)。使用以下代码 就是:

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 发送 POST 时的响应正文,以查找 error:NotRegisteredcanonical_id 结果(如 FCM 文档中所述)。

订阅在 Service Worker 和您的 服务器。例如,在成功订阅/取消订阅后, 网络连接可能会导致您无法更新服务器;或者用户可能 撤消通知权限,此操作会触发自动退订。标识名 针对这种情况,检查 定期serviceWorkerRegistration.pushManager.getSubscription()(例如 并将其与服务器同步。您可能还希望 如果您不再拥有订阅,那么系统会自动重新订阅 Notification.permission == 'granted'。

sendSubscriptionToServer(),您需要考虑 在更新 endpoint 时失败的网络请求。一种解决办法是 跟踪 Cookie 中 endpoint 的状态 以确定您的服务器是否需要最新详细信息。

完成上述所有步骤后,在 Chrome 46 中的 Web 应用。此外,还有一些经过规范的功能, (如用于触发推送消息的标准 API),但此版本可让您 立即开始将推送消息构建到您的 Web 应用中。

如何调试您的 Web 应用

实现推送消息时,错误会集中在以下两个位置之一:您的网页 或 Service Worker。

可以使用以下代码调试页面中的 bug: DevTools。调试 Service Worker 您有两种选择:

  1. 转到 chrome://inspect >Service Worker。此视图不提供 除了当前运行的 Service Worker 以外的很多信息。
  2. 转到 chrome://serviceworker-internals,然后在其中查看 Service Worker 的状态,以及查看错误(如有)。此网页是 直到开发者工具提供类似的功能集为止。

对于刚刚接触 Service Worker 的人,我可以给出的最好的建议之一就是 使用名为“打开开发者工具窗口并暂停 JavaScript 执行”的复选框 调试。”此复选框将在 启动 Service Worker 并暂停执行,这样您便可以 继续或单步调试 Service Worker 脚本,看看是否遇到任何 问题。

显示“暂停执行”复选框在 serviceworker-internals 上的位置的屏幕截图。

如果 FCM 和 Service Worker 的推送事件之间似乎有问题, 那么调试问题就没有太多的办法了 以查看 Chrome 是否收到了任何内容。需要确保的关键在于 从 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

目前,在 Chrome(Android 版)上调试 Service Worker 还不明显。 您需要前往 chrome://inspect,找到您的设备并查找 名为“Worker pid:....”的列表项其中包含您的服务网址 worker。

显示 Service Worker 在 Chrome 检查中的位置的屏幕截图

推送通知的用户体验

Chrome 团队正在汇总最佳做法文档, 以及一个文档,其中介绍了一些 使用推送通知时的极端情况

Chrome 和开放网络推送消息功能的未来

本部分将详细介绍 Chrome 浏览器的一些 应该了解的特定部分,以及如何 与其他浏览器实现方式不同。

网络推送协议和端点

Push API 标准的优点在于您应该能够 endpoint,将它们传递给您的服务器,然后发送推送 通过实现网络推送协议来发送和接收消息

网络推送协议是一种新标准,推送提供程序可以实现 让开发者无需担心推送提供程序是谁。通过 这种做法可免去注册 API 密钥的麻烦, 格式的数据,就像使用 FCM 时那样。

Chrome 是第一个实现 Push API 的浏览器,但 FCM 并未实现 支持网络推送协议,因此 Chrome 要求 gcm_sender_id,并且您需要针对 FCM 使用 RESTful API。

Chrome 的最终目标是朝着将 Web 推送协议与 Chrome 和 FCM 结合使用。

在此之前,您需要检测端点 &quot;https://fcm.googleapis.com/fcm/send&quot; 并将其与其他端点分开处理,例如,将载荷数据的格式设置为 然后添加授权密钥

如何实现网络推送协议?

Firefox Nightly 目前正在进行推送,可能会是第一款 实现网络推送协议

常见问题解答

规格在哪里?

https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ https://w3c.github.io/push-api/ https://notifications.spec.whatwg.org/

如果我的网络身份有多个源,或者我既有网络又有原生,我可以防止出现重复的通知吗?

此问题还没有解决方案,但您可以按照 Chromium 的进度跟踪。

理想的场景是为用户设备创建某种 ID,然后 在服务器端匹配原生应用和 Web 应用的订阅 ID,并且 决定向哪个消息发送推送消息您可以通过屏幕尺寸 设备模型,在 Web 应用和原生应用之间共享生成的密钥,但 每种方法各有利弊。

为什么我需要 gcm_sender_id?

只有这样,Chrome、Android 版 Opera 和三星浏览器才能 使用 Firebase Cloud Messaging (FCM) API。目标是使用 Web 推送协议(如果标准已最终确定且 FCM 可支持它)。

为什么不使用 Web Sockets 或服务器发送事件 (EventSource)?

使用推送消息的优势在于,即使页面关闭, Service Worker 将被唤醒,并显示通知。WebSocket 和 EventSource 的连接会在网页或浏览器关闭时关闭。

如果我不需要传送后台事件,该怎么办?

如果您不需要后台传送,Web Sockets 是一个很好的选择。

何时可以在不显示通知的情况下使用推送(即无声背景推送)?

对于何时能够实现这一目标,没有具体的时间表,但 实现后台同步 虽然相关技术未定或规范,但关于启用 支持后台同步的静默推送

为什么这需要 HTTPS?如何在开发期间解决此问题?

Service Worker 需要安全的源,以确保 Service Worker 脚本 来自预期出处,而非中间人 攻击。目前,这意味着在实际网站上使用 HTTPS 工作。

浏览器支持情况如何?

Chrome 已在稳定版中提供支持,而 Mozilla 也已在 Firefox Nightly 中推送消息。 如需了解详情,请参阅实现 Push API bug 您可以在此处跟踪其通知实现情况

我可以在一段时间后移除通知吗?

目前不能这样做,但我们计划增加支持, 当前可见通知的列表。如果您需要设置一个 显示相应通知后会过期 请添加评论,我们会将其转达给 Chrome 团队。

如果您只需阻止向用户发送推送通知 并不在意通知的持续时间 则您可以使用 FCM 的存留时间 (ttl) 参数, 点击此处了解详情

在 Chrome 中推送消息有哪些限制?

该博文会介绍一些限制:

  • Chrome 使用 CCM 作为推送服务, 要求。我们正在共同努力,看看能否在 Google Cloud 中 未来。
  • 您必须在收到推送消息时显示通知。
  • Chrome 桌面版会提醒用户,如果 Chrome 未运行,则系统会推送消息 不会接收。这与推送消息的 ChromeOS 和 Android 设备不同 始终会接收到。

我们不应该使用 Permissions API 吗?

通过 Permission API 在 Chrome 中实现, 但并不一定适用于所有浏览器。您可以点击此处了解详情

当我点击通知时,为什么 Chrome 无法打开上一个标签页?

此问题只会影响当前不受服务控制的网页 worker。您可以点击此处了解详情

如果在用户设备收到推送时通知已过期,该怎么办?

无论何时,您都必须在收到推送消息时显示通知。 当您想要发送通知,但通知只有用时 则可以使用“time_to_live”CCM 上的参数 以便 FCM 在超过过期时间后不会发送推送消息。

如需了解详情,请点击此处

如果我发送了 10 条推送消息,但只希望设备接收一条,会发生什么情况?

FCM 具有“折叠键”此参数可用于指示 FCM 替换任何待处理 消息中的新消息。

如需了解详情,请点击此处