我正在尝试通过Node.js服务器在我的Android应用中实施Firebase云消息传递,并且我已经陷入了一个用例。
我看到了使用注册令牌创建设备组的Firebase教程,以便在登录相同用户的情况下向所有设备发送消息/通知,我不明白当其中一个注册令牌被onTokenRefresh刷新时会发生什么() 方法。
我如何区分要更改哪个令牌,因为所有令牌都属于同一个用户?
更新
好的,现在我又陷入了另一个阻塞用例。我正在创建一个由我的服务器中的用户ID标识的用户组。如果用户立即卸载并重新安装应用程序而另一个用户登录设备,如果我在之前的用户组上调用gcm消息,则此设备仍会收到该消息。
gcm是否有任何方法可以识别发送通知的设备是否已登录?如果是,是否使用与该组相同的用户登录?
答案 0 :(得分:5)
所以我一直在考虑如何使用这种情况。首先,让我们在调用onRefreshToken()时放入实例:
不会经常调用,需要进行密钥轮换并处理由于以下原因导致的实例ID更改:
- 应用删除实例ID
- 应用程序已在新设备上恢复
- 用户卸载/重新安装应用
- 用户清除应用数据
猜猜,你可以说'onTokenRefresh()`将在上述情况发生之后被调用,如果设备在线(当然它必须在线才能获得新的令牌)。所以我想这就是我如何继续这个场景:
首先,在注册时,我会保存注册令牌并将其与另一个标识符配对,让我们说一个deviceId(因为我们处于具有多个设备的用户的场景中) App Server。
因此假设我添加了3个注册令牌,这些令牌也与他们的deviceIds配对。我将它们全部添加到设备组中。
现在说其中一个设备会触发onTokenRefresh()
,我会立即向我的App Server发送删除请求,以获取当前与该deviceId配对的注册令牌(您还应该在任何设备组中将其删除( s)它已连接到),用新的替换它,然后将其重新添加到相应的设备组。
这是我能想到的最简单的方法。这里的关键是您将注册令牌与另一个标识符配对,并使用它来查找您需要替换的注册令牌。
答案 1 :(得分:3)
还有另一种使用Cloud Firebase功能解决此问题的方法。
由于所有人都属于我,我将如何区分要更改的令牌 到同一用户?
您不必使用Firebase功能。在onTokenRefresh()中,您可以将新令牌发送到服务器。
例如:
用户有3个设备,每个设备都有一个已发送到服务器的令牌。
*** deviceTokenA / B / C代表令牌的UID ...我们不知道它们是什么,或者它们属于哪个设备。
UserId:
Device Tokens:
deviceTokenA: true,
deviceTokenB: true,
deviceTokenC: true,
现在,用户位于触发deviceTokenA的设备上。刷新令牌,并调用onTokenRefresh(),将令牌发送到该集合。
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.
deviceTokenA不再适用,因为它已刷新,并且不再连接到实际设备。
在查看设备令牌时,我们仍然不知道哪些令牌好,哪些坏,以及哪些令牌属于哪个设备。没关系!
因此,然后创建一个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);
答案 2 :(得分: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个设备的不同组?