【问题标题】:How to handle multiple Firebase FCM tokens per user?如何为每个用户处理多个 Firebase FCM 令牌?
【发布时间】:2017-11-13 18:48:54
【问题描述】:

从官方文档中我了解到它的工作方式是这样的:

  1. 用户安装应用,生成 FCM 令牌
  2. 向应用服务器发送令牌
  3. 服务器使用令牌向此设备发送推送通知。

如果该用户同时在另一台设备上安装应用,我应该在应用服务器上为每个用户存储多个令牌吗?如果是 - 这意味着应该检查哪些已过期?

【问题讨论】:

  • 每次触发推送请求时,都可以返回一个 json 结构。示例:{"multicast_id":5221242244170421431,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1524496848239873%cc9b4facf9fd7ecd"}]} -- 如果失败等于1,则删除对应的token。
  • 好吧,您可以存储诸如唯一设备 ID 和令牌之类的东西。使两个唯一约束。设置机制来删除早于 x 时间的记录。

标签: firebase firebase-cloud-messaging


【解决方案1】:

我遇到了同样的问题,我试图解决这个问题的方法是维护这样的数据结构。并将这些数据保存到我的通知服务器的数据库中。

type UserToken struct {
    UserId      string
    Tokens      []DeviceToken
}

type DeviceToken struct {
    DeviceName  string
    Token       string
}

每当您从 firebase 获得新的设备令牌时,只需将该设备的现有设备令牌替换为新设备令牌即可。

对于网络部分,我认为存储最后一个就足够了。

【讨论】:

    【解决方案2】:

    我也有类似情况,在尝试发送到过期令牌时发现如下错误响应代码:

    {
    "error": {
        "code": 404,
        "message": "Requested entity was not found.",
        "status": "NOT_FOUND",
        "details": [
            {
                "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError",
                "errorCode": "UNREGISTERED"
            }
        ]
    }}
    

    假设用户使用多个设备,我的应用服务器接受每个用户的多个令牌。发送新消息时,我会尝试将其发送到与用户相关的所有令牌。返回此错误的那些将被删除,因此以后的消息将仅发送到活动令牌。

    【讨论】:

      【解决方案3】:

      Graykos,你可以这样:

      每次用户从 google 登录 get a new token 时,以及注销时 delete that token。 因此,如果用户从多个设备/浏览器登录或多个用户从一个设备/浏览器依次登录,您可以很好地处理所有这些。

      以这种方式“多个用户从一个设备/浏览器一个接一个地登录”,它们都具有相同的令牌(因此每次登录都删除并更新)

      正如Andres SK 在您问题的第一条评论中提到的,您可以在发生故障时删除令牌(可能是用户无法注销的丢失设备)。

      【讨论】:

      • 如果用户在没有执行注销操作的情况下删除应用程序将不起作用。
      • 您没有阅读答案中的最后两行。如果用户在未注销帐户的情况下卸载应用程序。当您想发送通知时会失败,您必须从服务器中删除该令牌。
      • 用户注销后删除令牌。等等,所以你永远不会仅仅因为用户退出就向用户发送通知。
      • DroidDev 没错,就像任何应用程序(例如 Gmail)一样,当您从您的帐户注销时,您将永远不会收到邮件通知,并且当您再次登录时会收到一个新代码。在 FCM (firebase.google.com/docs/cloud-messaging/…) 中读取“错误:未注册”
      • 它可以是一个解决方案,也许它是唯一的一个,但老实说我不是 100% 喜欢它,有很多事情可能会出错。 1) 发送消息后才知道消息是否能送达; 2)如果您突然发送对帐消息,然后谷歌,或者您的后端失败,那么该过程将无法按预期进行
      【解决方案4】:

      我也遇到了确切的挑战,不得不下定决心找到一个解决方案: 根据设备 ID 为用户存储每个令牌。 有趣的是,这个函数实际上存在于 firebase 消息传递方法中。但更令人惊讶的是,没有文档可以处理这种情况。 https://firebase.google.com/docs/reference/android/com/google/firebase/iid/FirebaseInstanceId.html#getId()

      总的来说,在向服务器发送新令牌的同时,还要发送 getId() 方法返回的设备 ID,并使用它来强制每个设备的令牌唯一性。

      为了在利用 FCM 的设备分组功能的同时应用此解决方案,您可以在 FCM 组上发出服务器请求,以便在用新令牌替换之前删除该设备 ID 上的旧令牌。

      【讨论】:

      • 但是 getId() 的文档说:Returns a stable identifier that uniquely identifies the app instance.。它不能识别设备 ID。
      • firebase.google.com/docs/reference/android/com/google/firebase/… 是的,但这不会改变,除非:实例 ID 稳定,除非:*App 删除实例 ID。 *应用程序在新设备上恢复。 *用户卸载/重新安装应用程序。 *用户清除应用数据。
      • 我知道,我读到了,但你称它为设备 ID,不是这样,它只是一个实例 ID。如果用户删除并重新安装应用程序,您将在同一设备中拥有另一个实例 ID。因此,您将无法区分同一设备的旧令牌和新令牌。
      【解决方案5】:

      如果该用户同时在另一台设备上安装应用,我应该在应用服务器上为每个用户存储多个令牌吗?

      是的。一个用户可能有多个设备,Device Groups 是常用的情况。

      如果是 - 这意味着应该检查哪些过期了?

      如果令牌过期,则会触发回调(Android 为onTokenRefresh()),您必须从该回调将新令牌发送到您的应用服务器并删除与用户/设备对应的旧令牌。

      【讨论】:

      • 但是如果用户从 10 台设备登录并丢失了其中的 9 台会怎样。所以他们不会触发回调。我是否必须永远向这些丢失的设备发送通知?
      • 开发人员有责任跟踪设备组的映射。查看我的回答 herehere
      • "删除用户/设备对应的旧的"...好的,但是如何确定唯一设备呢?如果是同一用户使用 2 个不同的浏览器或不同的机器怎么办。是否有获取唯一设备 ID 的 firebase 方法,或为此提供公共网络 API?
      • @johnb003 当您向群组发送通知时,您会获得成功、部分成功或失败。如果您获得部分成功或失败,它还包括所有无法接收通知的令牌,因此您获取这些令牌并将它们从组中删除?同上。在网上或文档中找不到任何有用的东西...firebase.google.com/docs/cloud-messaging/android/…
      • 谢谢@AL。非常有用的信息。我突然想到一个想法:为什么不使用带有用户 ID 前缀的消息主题?这样,您不会向令牌发送通知,而是向由 user_id + 主题名称组成的主题发送通知。用户登录后,您注册设备令牌(如果已更新)并将令牌链接到相应的主题名称(例如 123_new-order-registration)。也许有更好的方法来做到这一点,但你明白了
      猜你喜欢
      • 1970-01-01
      • 2017-10-23
      • 1970-01-01
      • 1970-01-01
      • 2016-10-13
      • 1970-01-01
      • 2018-11-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多