Firebase实时数据库新增帖子时如何向用户推送通知?
基于Firebase实时数据库实现新事件上报推送通知的实现方案
你可以直接搭配Firebase生态内的Firebase Cloud Messaging(FCM)+ Firebase Cloud Functions实现需求,逻辑完全适配实时数据库的触发规则,不需要额外引入第三方服务:
核心实现步骤
- 第一步:客户端接入FCM SDK,用户首次启动应用时生成专属FCM令牌,结合用户授权的地理位置信息,将令牌、用户所在区域标签存入实时数据库的
/user-fcm-tokens节点,存储格式参考:/user-fcm-tokens/{地区标识}/{用户uid} = "用户FCM令牌" - 第二步:配置Firebase Cloud Functions触发规则,监听你存储上报事件的节点(比如
/reported-events)的onCreate事件,只要有新的事件数据写入就自动触发云函数执行 - 第三步:云函数运行时先读取新上报事件的地理位置、覆盖范围,去
/user-fcm-tokens节点拉取对应区域的所有有效用户FCM令牌,构造通知标题、内容、跳转参数后调用FCM批量推送接口完成下发 - 第四步:客户端侧配置通知接收回调,不管应用在前台还是后台都能正常展示通知,点击通知时携带事件ID跳转至对应事件详情页即可
注意事项
- 如果需要做精确的圆形范围匹配,可以在云函数中集成地理位置计算逻辑,用事件的经纬度和用户最后上报的经纬度计算距离,过滤符合范围的用户再推送;如果对精度要求不高,直接按城市、区县标签匹配即可,性能更高
- FCM推送返回的错误中如果包含无效令牌标识,要自动把对应令牌从实时数据库中删除,避免无效推送消耗配额
- 可以在用户侧新增通知开关配置,用户关闭通知时直接移除对应区域下的FCM令牌,或者增加
notification_enabled标记,推送前过滤掉关闭通知的用户
云函数触发逻辑示例代码
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); // 监听新事件上报节点的创建事件 exports.sendNewEventNotification = functions.database.ref('/reported-events/{eventId}') .onCreate(async (snapshot, context) => { const newEvent = snapshot.val(); const eventArea = newEvent.areaTag; // 新事件的所属区域标签,上报时写入 // 拉取对应区域的所有用户FCM令牌 const tokensSnapshot = await admin.database().ref(`/user-fcm-tokens/${eventArea}`).once('value'); const tokens = Object.values(tokensSnapshot.val() || {}); if (tokens.length === 0) return null; // 构造通知内容 const payload = { notification: { title: "附近有新的上报事件", body: `地点:${newEvent.location} | 类型:${newEvent.type}`, click_action: "EVENT_DETAIL_ACTION" // 可自定义为客户端跳转的动作标识,按技术栈调整 }, data: { eventId: context.params.eventId, eventLocation: newEvent.location } }; // 批量推送通知 const response = await admin.messaging().sendEachForMulticast({tokens, ...payload}); // 清理无效令牌 const invalidUids = []; const uidList = Object.keys(tokensSnapshot.val() || {}); response.responses.forEach((resp, idx) => { if (!resp.success && (resp.error.code === 'messaging/invalid-registration-token' || resp.error.code === 'messaging/registration-token-not-registered')) { invalidUids.push(uidList[idx]); } }); if (invalidUids.length > 0) { const updates = {}; invalidUids.forEach(uid => updates[uid] = null); await admin.database().ref(`/user-fcm-tokens/${eventArea}`).update(updates); } return null; });
内容的提问来源于stack exchange,提问作者user15608723
相关产品推荐
相关产品推荐

