Flutter中Firebase Messaging通知无故延迟批量送达问题求助
通知延迟批量推送的问题排查与修复
核心问题分析
你的Cloud Functions代码存在几个关键问题,直接导致通知延迟或批量推送:
forEach未等待异步操作完成
forEach循环不会等待内部的异步函数执行完毕,Cloud Functions可能在所有推送请求发送前就提前终止,导致消息被缓存后批量触发。仅使用data消息,未利用FCM的notification字段
当前消息只有data字段,Android/iOS在后台状态下不会自动展示这类通知,需要客户端手动处理,这会增加延迟;而notification字段的消息会由系统直接展示,及时性更高。错误处理与日志缺失
未对sendMulticast的返回结果做处理,无法得知哪些推送失败,也没有重试机制,失败的消息可能被延迟重试。
修复后的代码示例
exports.messageTrigger = functions.firestore.document('/Messages/{messageID}').onCreate(async (snapshot, context) => { function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } const currentRoomUsers = snapshot.data().members; const senderID = snapshot.data().senderID; const roomName = capitalizeFirstLetter(snapshot.data().room); const messageType = snapshot.data().type; // 用for...of替代forEach,确保异步操作顺序执行 for (const userID of currentRoomUsers) { if (userID === senderID) continue; // 跳过发送者 try { const doc = await db.collection('Users').doc(userID).get(); if (!doc.exists) { console.log(`用户 ${userID} 不存在`); continue; } const deviceTokens = doc.data()['Device_token']; if (!deviceTokens || deviceTokens.length === 0) { console.log(`用户 ${userID} 无设备令牌`); continue; } // 构建包含notification和data的消息 const message = { tokens: deviceTokens, // 系统直接展示的通知内容 notification: { title: `来自${roomName}的新消息`, body: messageType === 'm.text' ? '发送了一条新消息' : messageType === 'm.start' ? '邀请你通话' : messageType === 'm.image' ? '发送了一张图片' : '发送了一条新消息' }, // 附加数据,供客户端处理 data: { room: snapshot.data().room, messageID: context.params.messageID }, android: { priority: 'high', notification: { priority: 'high', sound: 'default' // 确保通知有声音,提升及时性 } }, apns: { payload: { aps: { contentAvailable: true, priority: 1 // iOS高优先级,确保后台推送及时 } } }, priority: 'high' }; const response = await admin.messaging().sendMulticast(message); // 记录推送结果 console.log(`用户 ${userID} 推送完成:成功${response.successCount}条,失败${response.failureCount}条`); // 处理失败的推送,可添加重试逻辑 if (response.failureCount > 0) { response.responses.forEach((resp, idx) => { if (!resp.success) { console.error(`令牌 ${deviceTokens[idx]} 推送失败:${resp.error}`); } }); } } catch (error) { console.error(`处理用户 ${userID} 时出错:${error}`); } } });
额外优化建议
- 客户端配置检查:确保flutter_local_notifications和firebase_messaging的配置正确,Android端在
AndroidManifest.xml中设置高优先级通道,iOS端开启推送权限并配置APNs证书。 - 批量推送优化:如果一个用户有多个设备令牌,用
sendMulticast是正确的;如果是多个用户,可考虑分组处理,但避免一次发送过多请求导致限流。 - Cloud Functions资源配置:如果推送量较大,可适当提高Cloud Functions的内存和超时时间,避免因资源不足导致中断。
内容的提问来源于stack exchange,提问作者ialyzaafan
相关产品推荐
相关产品推荐

