如何管理 FCM 推送令牌
Posted
技术标签:
【中文标题】如何管理 FCM 推送令牌【英文标题】:How to manage FCM push tokens 【发布时间】:2021-05-17 01:29:23 【问题描述】:我想找到一种可持续的解决方案来存储用于推送通知的 FCM 令牌。我正在将 React Native 与 Firebase 一起使用。
要求是:
-
基于用户的应用程序
支持每位用户多台设备
任何时候都没有存储过时的令牌。
我目前的做法是:
维护一个带有列的表user_devices
:
保持对 fcm_token 和 device_uuid 的唯一性约束。
关键事件,包括但不限于:
应用程序启动 登录 onTokenRefresh将以下内容发送到后端:
device unique id FCM 注册令牌 用户 ID,如果有(通过身份验证令牌完成)然后后端使用上述值更新一行。如果设备 uuid 存在,这意味着我们会覆盖该设备 uuid 的令牌(可能还有 user_id)。
上述方法存在缺陷,因为:
device unique id 可以随时更改(设备重置、更新、应用重新安装等...) 注册令牌可以随时更改换句话说,表最终存储了许多过时的令牌,应用程序后端向这些过时的令牌发送通知。
此外,“设备”前端页面(向用户显示他们的注册设备并从上表中读取)显示了许多重复的设备,这些设备实际上代表相同的设备但具有不同的设备 uuid。
一个缓解步骤可以是定期向存储在带有dry_run=true
的表中的所有令牌发送通知。然后,删除带有发生错误的标记的行。这很糟糕,因为这意味着在一段时间内,表中的令牌是陈旧的。
我已经在线扫描了多个资源,包括 FCM 文档,但没有提及在实际应用程序中存储和维护这些令牌。有什么建议的方法吗?
【问题讨论】:
【参考方案1】:惯用方法是在发送消息的 Firebase 云消息传递 API 告诉您它无效时删除令牌。
有关如何执行此操作的示例,您可以查看 sending notifications 的 Cloud Functions 示例,它执行以下操作:
const response = await admin.messaging().sendToDevice(tokens, payload);
// For each message check if there was an error.
const tokensToRemove = [];
response.results.forEach((result, index) =>
const error = result.error;
if (error)
functions.logger.error(
'Failure sending notification to',
tokens[index],
error
);
// Cleanup the tokens who are not registered anymore.
if (error.code === 'messaging/invalid-registration-token' ||
error.code === 'messaging/registration-token-not-registered')
tokensToRemove.push(tokensSnapshot.ref.child(tokens[index]).remove());
);
return Promise.all(tokensToRemove);
因此,每次您通过 FCM 发送多条消息时,都会从数据库中剔除无效/过时的令牌。
【讨论】:
谢谢。这似乎是上述不完美解决方案的被动变体(定期检查存储令牌的有效性)。这意味着该表可以存储大量陈旧的令牌,我们会执行不需要的广播调用。 有一些应用程序,例如 PagerDuty,可以实现这一点——它们提供了一个面向用户的页面,其中列出了用户的设备,并且不会出现重复项。我想知道他们使用什么样的技术?此外,与返回错误消息匹配的字符串似乎非常不可持续。真是让我吃惊,这是惯用的方法。 代码在令牌使用一次后立即删除。在 FCM API 中,这是我所知道的最好的。我找到了更好的方法,请作为自我回答分享。 我想不出任何不涉及 FCM 方面更改的解决方案,因此问题:)。我相信一个潜在的解决方案是让onRefreshToken
传入之前的注册令牌(或之前的令牌链),但我的猜测是这会破坏这些令牌首先轮换的一些原因。通过削减上述三个要求之一,大多数实际应用程序很可能不会面临这个问题。其他生产级应用程序可能使用一组启发式方法。以上是关于如何管理 FCM 推送令牌的主要内容,如果未能解决你的问题,请参考以下文章
Firebase 推送通知 - 如何跟踪用户 FCM 令牌?