处理 FCM 设备组的刷新令牌

8
我正在尝试通过Node.js服务器在我的Android应用程序中实现Firebase云消息传递,并且我在一个用例中卡住了。
我看到Firebase教程使用注册令牌创建设备组,向所有已登录相同用户的设备发送消息/通知,但我不明白当其中一个注册令牌通过onTokenRefresh()方法刷新时会发生什么。
我如何区分要更改哪个令牌,因为所有令牌都属于同一用户?
更新:
好的,现在我又陷入了另一个阻塞用例。我正在创建由来自我的服务器的用户ID标识的用户组。如果用户立即卸载并重新安装应用程序,并且其他用户在设备上登录,则如果我在先前的用户组上调用gcm消息,则该设备仍将接收到该消息。
是否有任何方法让gcm识别它发送通知的设备是否已登录,如果已登录,则是否与组的相同用户登录?
3个回答

7
使用Cloud Firebase Functions有另一种解决问题的方法。
“我如何区分要更改哪个令牌,因为所有令牌都属于同一用户?”
使用Firebase Functions,您不需要。在onTokenRefresh()中,您可以将新令牌发送到服务器。
例如:
用户拥有3台设备,每台设备都有一个已发送到服务器的令牌。
*** deviceTokenA/B/C代表令牌的UID...我们不知道它们是什么,也不知道它们属于哪个设备。
UserId:
    Device Tokens:
        deviceTokenA: true,
        deviceTokenB: true,
        deviceTokenC: true,

现在,用户正在触发设备TokenA上。Token已经更新,onTokenRefresh()被调用,并将Token发送到该集合。

onTokenRefresh() {
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();
    sendTokenToServer(refreshedToken);
}

sendTokenToServer(String refreshedToken) {
    // send to Firebase or Firestore Database, put in the Device_Tokens collection.  }

现在,您的集合中将有4个令牌。
 UserId:
        Device Tokens:
            deviceTokenA: true,  // this one has been "unregistered"
            deviceTokenB: true,
            deviceTokenC: true,
            deviceTokenD: true, // this one has been registered.

由于已经刷新,设备标记A不再适用于实际设备。

在查看设备标记时,我们仍然不知道哪些标记可用,哪些是无效的,以及哪些标记属于哪个设备。这没关系!

因此,创建一个forEach循环,获取每个标记,然后向每个标记发送FCM,FCM可以让我们知道哪些标记已成功发送。其中一个将返回错误。如果返回错误,说明标记无效,我们可以捕获该错误并删除该标记,以便不会再次调用它。

// outside for Each loop
     var promiseHolder = [];


// create a forEach loop, iterating through the collection of deviceTokens
// within that loop, put:

let innerPromise = admin.messaging().send(message)
.then(response => {
    console.log('notification sent success: ' + response);
})
.catch((error) => {
    console.log('Error sending notification: ' + error);

    // if the error == bad token message, then Delete the Token.
    if (error == 'Error: Requested entity was not found.') {
        console.log('you matched the error, token doesn't work, handle here.');

        //delete the old token
        return admin.firestore()doc(`users/${userID}/device_tokens/${token_id}`).delete();
     }
}

// still within forEach loop
promiseHolder.push(innerPromise);

// end the forEach Loop, and outside forEachLoop put:
return Promise.all(promiseHolder);

你在 admin.firestore() 后面缺少了一个 .,并且在 .catch 语句的末尾还缺少了一个 )。没有这些代码,我的程序无法正常运行。 - siefix

5

我一直在思考如何应对这种情况。首先,让我们看看什么情况下会调用 onRefreshToken()

这不会经常被调用,它用于密钥轮换以及处理实例ID更改,原因是:

  • 应用删除了实例ID
  • 应用在新设备上恢复
  • 用户卸载/重新安装应用程序
  • 用户清除应用数据

可以说,“onTokenRefresh()`将在发生以上任何一种情况并且设备在线(当然必须在线才能获得新令牌)后被调用。所以我的建议是:

首先,在注册时,我会保存注册令牌并与另一个标识符进行配对,比如一个设备ID (因为我们的场景中一个用户可能有多个设备) 在我的应用服务器上。

假设我添加了3个注册令牌,这些令牌也与它们的设备ID配对。 我将它们全部添加到设备组中。

现在假设其中一个设备触发了onTokenRefresh(),我将立即向我的应用服务器发送一个删除请求,以删除当前与该设备ID配对的注册令牌(您还应将其从任何连接到它的设备组中删除),然后将新的注册令牌替换旧的,并重新添加到相应的设备组中。

这是我能想到的最简单的方法。关键在于将注册令牌与另一个标识符配对,并使用它来查找需要替换的注册令牌。


2
@AL,请问你在使用什么作为设备ID? - sauvik
@amarok 我也有这个问题。请参考以下链接:Web端 - https://dev59.com/YnVD5IYBdhLWcg3wXaYd#10747;Android端 - https://developer.android.com/reference/android/telephony/TelephonyManager.html#getDeviceId 或 https://developer.android.com/reference/android/net/wifi/WifiInfo.html#getMacAddress。 - CantThinkOfAnything
那个解决方案很有道理,但是你用什么作为deviceId? - Jeff Padgett
1
@JeffPadgett 目前,我仍在使用 ANDROID_ID,尽管它对于 Android O 及以上版本不再建议使用。我还没有找到一个真正好的替代方案。 - AL.
@amarok 很抱歉没能及时回复你。我刚刚注意到你的评论已经接近一年了,但是为了回答你的问题,请查看我上面的评论。干杯! - AL.
1
谢谢,我也在使用ANDROID_ID。虽然不建议使用,但在这种情况下似乎仍然有效。Android 8.0将对其进行修改,并使ANDROID_ID与应用程序签名密钥和设备组合相关联,从而使其更安全,但允许开发人员获得跨卸载和重新安装保持不变的设备ID。我认为只要我们不与第三方使用它、出售它或将其用于广告跟踪,就可以了。 - Jeff Padgett

0

目前我使用这种方法。在我的数据库中,我创建了一个带有设备ID的节点。

deviceId: {
   uid1: deviceId,
   uid2: deviceId,
   uid3: deviceId
}

另一个节点,其中包含订阅接收通知的用户

newsSubscriber: {
   uid1: [array of subscribers],
   uid2: [array of subscribers],
   uid3: [array of subscribers]
}

当我可以通过我的nodejs脚本发送通知时,我会获取保存在newsSubscriber节点中的所有用户,并为每个用户获取其deviceId并将其放入设备数组中以发送通知。 只有一个问题,我现在读到,在此模式下只有 20个设备的限制!。
但我认为这是一种好的简单方法,可以为任何用户获取相应的deviceId,因为当我在我的应用程序中使用注销或登录时,我可以更改任何用户的对应deviceId,以便在用户和设备之间保持一致性。
如果要绕过20台设备的限制,我将相同的通知发送给不同的20台设备组,会发生什么?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接