首页 > 解决方案 > 如何在不触发权限提示的情况下检查 FCM 是否允许通知

问题描述

我想知道用户是否在当前浏览器上允许通知,以便我可以在 UI 上显示该状态,但我不想触发请求权限,除非用户执行启用通知的操作。这是一种鸡蛋问题,因为我没有可靠的方法来识别当前用户浏览器。我可以将 FCM 令牌存储在 firebase 数据库中并在 FE 上获取它。但是每个浏览器的每个令牌都是唯一的,我无法将它与任何东西进行比较,我必须检查现有令牌之一是否适用于当前浏览器的唯一方法是使用getTokenfirebase FCM 中的方法并检查返回的令牌是否开启令牌列表,但这可能会触发请求权限提示,除非用户要求,否则我不希望这样做。

一种可能的解决方案可能涉及在本地存储中存储一个标志,但如果用户清除它,当用户仍订阅 FCM 主题时,UI 将显示通知为禁用。我知道Notification API 有一个属性,该属性指示用户是否已授予通知权限,但这可能已经发生,并且由于某些随机网络错误未检索到令牌,因此我不能仅依赖于此。此外,它仅指示用户是否已授予权限,但在我的应用程序逻辑通知可能被禁用(因为用户选择)并且不会撤销权限。

如果用户想要禁用通知,事情也不好:为了从数据库中删除令牌,我需要当前的浏览器令牌,而知道当前浏览器令牌的唯一可靠方法是使用 getToken 询问它,这可能会触发如果用户禁用了通知,则请求权限,我将永远不会获得实际的令牌,我需要将其从数据库中删除

有没有关于如何处理这个问题的指导方针?FCM 文档非常稀少

标签: firebasefirebase-cloud-messagingprogressive-web-apps

解决方案


这是一个我不确定它是否超级健壮的解决方案,但它很简单并且可能满足大多数情况。

首先,检查当前浏览器是否允许通知。如果没有,只需在 UI 上显示该值,因为即使在后端订阅了通知,用户也不会收到通知。

如果已经允许通知,您可以安全地运行 getToken(不会触发权限请求)并将值与用户/配置文件数据库中的值进行比较。

因为我在这里使用 react 是一个钩子上的实现:

  const areNotificationsAllowed =
    Notification && Notification.permission === "granted";

  useEffect(() => {
    // because we don't want to trigger a permission request
    if (!areNotificationsAllowed) return;
    // Notifications are allowed, we can safely run getToken to see if they are activated on this browser
    messaging.getToken({ vapidKey }).then((token?: string) => {
      if (!token) return setNotificationsEnabled(false);
      if (notificationsCfg[token]) setNotificationsEnabled(true);
    });
  }, [areNotificationsAllowed])

推荐阅读