处理FCM设备组的刷新令牌

时间:2016-10-19 19:41:43

标签: android node.js firebase firebase-cloud-messaging

我正在尝试通过Node.js服务器在我的Android应用中实施Firebase云消息传递,并且我已经陷入了一个用例。

我看到了使用注册令牌创建设备组的Firebase教程,以便在登录相同用户的情况下向所有设备发送消息/通知,我不明白当其中一个注册令牌被onTokenRefresh刷新时会发生什么() 方法。

我如何区分要更改哪个令牌,因为所有令牌都属于同一个用户?

更新

好的,现在我又陷入了另一个阻塞用例。我正在创建一个由我的服务器中的用户ID标识的用户组。如果用户立即卸载并重新安装应用程序而另一个用户登录设备,如果我在之前的用户组上调用gcm消息,则此设备仍会收到该消息。

gcm是否有任何方法可以识别发送通知的设备是否已登录?如果是,是否使用与该组相同的用户登录?

3 个答案:

答案 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个设备的不同组?