You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为同一Firebase用户存储多个FCM注册令牌?

解决方案:存储多设备FCM令牌列表并在Node.js中使用

当然可以实现!你只需要将Firestore中存储单个令牌的字段,改成数组类型来保存用户的所有设备令牌。这样同一用户在不同设备登录时,新令牌会被添加到数组中,而不是覆盖旧的。下面是具体的实现步骤:

1. 修改Android端的令牌存储代码

原来的代码使用update()直接覆盖token_id字段,现在我们改用Firestore的arrayUnion()方法来添加新令牌(这个方法会自动忽略数组中已存在的令牌,避免重复存储)。修改后的代码如下:

String token_id = FirebaseInstanceId.getInstance().getToken();
Log.i("token_id", token_id);

// 使用arrayUnion将新令牌添加到数组中,而不是覆盖
Map<String, Object> tokenMap = new HashMap<>();
tokenMap.put("token_ids", FieldValue.arrayUnion(token_id));

mFireStore.collection("Users").document(current_id)
    .update(tokenMap)
    .addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void aVoid) {
            Toast.makeText(LoginActivity.this, "Signed in Successfully", Toast.LENGTH_SHORT).show();
            startActivity(new Intent(LoginActivity.this, AdminActivity.class));
            finish();
        }
    });

注意:需要确保导入com.google.firebase.firestore.FieldValue类。如果是首次存储用户的令牌,数组会自动创建并添加第一个元素;如果已有数组,新令牌会被追加进去。

2. Firestore文档结构变化

修改后,你的Users集合中的文档结构会变成这样:

{
  "current_id": "用户唯一ID",
  "token_ids": [
    "设备1的FCM令牌",
    "设备2的FCM令牌",
    "设备3的FCM令牌"
  ],
  // 其他用户字段...
}

3. 在Node.js函数中使用令牌列表发送通知

当你需要给用户发送通知时,可以从Firestore读取该用户的token_ids数组,然后遍历数组给每个设备发送通知,或者使用FCM的批量发送功能。以下是Node.js的示例代码:

const admin = require('firebase-admin');
admin.initializeApp();

// 给指定用户发送通知的函数
async function sendNotificationToUser(userId, notificationPayload) {
  try {
    // 从Firestore获取用户的令牌列表
    const userDoc = await admin.firestore().collection('Users').doc(userId).get();
    if (!userDoc.exists) {
      console.log('用户不存在');
      return;
    }

    const tokenIds = userDoc.data().token_ids;
    if (!tokenIds || tokenIds.length === 0) {
      console.log('该用户没有可用的设备令牌');
      return;
    }

    // 给每个令牌发送通知
    const responses = await admin.messaging().sendEachForMulticast({
      tokens: tokenIds,
      notification: notificationPayload
    });

    console.log(`成功发送 ${responses.successCount} 条通知,失败 ${responses.failureCount} 条`);
    // 可以在这里处理失败的令牌(比如移除无效令牌)
    responses.responses.forEach((response, index) => {
      if (!response.success) {
        console.error(`令牌 ${tokenIds[index]} 发送失败: ${response.error}`);
        // 可选:移除无效令牌
        // admin.firestore().collection('Users').doc(userId).update({
        //   token_ids: admin.firestore.FieldValue.arrayRemove(tokenIds[index])
        // });
      }
    });
  } catch (error) {
    console.error('发送通知失败:', error);
  }
}

// 使用示例
sendNotificationToUser('用户的current_id', {
  title: '新通知',
  body: '你有一条新消息'
});

补充:如果用户在某台设备上注销,你可以调用FieldValue.arrayRemove(token_id)来从数组中移除对应的令牌,避免向无效设备发送通知。

内容的提问来源于stack exchange,提问作者rituparna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:20:50