如何从Firebase Database获取所有iOS设备FCM令牌?
如何正确从Firebase Database获取iOS设备令牌数组用于FCM推送
你的问题出在对Firebase DataSnapshot对象的处理上——你直接调用Object.keys(tokensSnapShot),但这个方法拿到的是DataSnapshot自身的内置属性(比如node_、ref_这些),而不是你存储的设备令牌数据。下面是修正后的代码,我会一步步解释关键修改点:
exports.iOSPush = functions.database.ref('/BootCamp/Bulletins/date').onWrite(async (snapShot, context) => { // 1. 直接获取iOS令牌节点的完整快照,不需要加{key}通配符 const tokensSnapshot = await admin.database().ref('/BootCamp/Notifications/iOS').once('value'); // 2. 遍历快照,提取每个子节点中的deviceToken字段 const tokens = []; tokensSnapshot.forEach(childSnapshot => { const deviceToken = childSnapshot.val().deviceToken; if (deviceToken) { // 过滤空令牌,避免无效推送 tokens.push(deviceToken); } }); if (tokens.length === 0) { console.log('没有可用的iOS设备令牌,跳过推送'); return null; } // 3. 构建FCM推送 payload const payload = { notification: { title: 'congrats it works', body: 'Cloud function noti for ios', sound: 'default', badge: '1' } }; // 4. 发送推送并处理结果 return admin.messaging().sendToDevice(tokens, payload) .then(response => { console.log('推送发送成功,结果:', response); // 可选:清理失效的令牌(比如过期或注销的设备) const cleanupPromises = []; response.results.forEach((result, index) => { const error = result.error; if (error) { console.error('推送失败的令牌:', tokens[index], '错误:', error); // 针对无效令牌,从数据库中删除 if (error.code === 'messaging/invalid-registration-token' || error.code === 'messaging/registration-token-not-registered') { const tokenKey = Object.keys(tokensSnapshot.val())[index]; cleanupPromises.push(tokensSnapshot.ref.child(tokenKey).remove()); } } }); return Promise.all(cleanupPromises); }) .catch(error => { console.error('推送发送失败:', error); }); });
关键修改说明:
- 修正快照获取路径:去掉了路径中的
{key},因为你需要获取/BootCamp/Notifications/iOS下的所有子节点,而不是单个节点。 - 正确遍历快照数据:使用DataSnapshot的
forEach方法遍历每个自动ID子节点,通过childSnapshot.val().deviceToken提取每个节点的令牌值,收集到数组中。 - 增加空数组校验:先检查令牌数组是否为空,避免调用
sendToDevice时传入空数组导致不必要的错误。 - 可选的失效令牌清理:添加了对无效令牌的处理逻辑,自动删除数据库中过期或失效的令牌,优化后续推送效率。
这样修改后,你就能得到预期的设备令牌数组,正常发送FCM推送了。
内容的提问来源于stack exchange,提问作者KarmaDeli
相关产品推荐
相关产品推荐

