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

Android端FCM通知接收失败(控制台显示送达成功)及云函数咨询

解决FCM通知显示送达但收不到+数据库触发通知的问题

我来帮你搞定这个问题!首先咱们先把你的云函数补全并优化,然后再排查收不到通知的常见坑点。

完整的云函数代码

你原来的代码不完整,我给你写了一个可以直接运行的版本,专门针对/published节点新增数据时触发通知:

'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');

// 初始化Admin SDK,最新写法不需要额外参数
admin.initializeApp();

exports.sendNotification = functions.database.ref('/published/{msg_id}')
    .onCreate(async (snapshot, context) => { 
        // 用onCreate代替onWrite,只在新增文章时触发,避免修改/删除时误发
        try {
            // 1. 获取刚发布的文章数据
            const newPost = snapshot.val();
            // 兜底处理,防止标题/内容为空
            const postTitle = newPost.title || '新文章发布啦!';
            const postContent = newPost.content || '点击查看最新内容';

            // 2. 从数据库获取所有用户的FCM令牌
            // 假设你在/users节点存储了每个用户的fcmToken字段
            const usersSnapshot = await admin.database().ref('/users').once('value');
            const users = usersSnapshot.val();
            const validTokens = [];

            if (users) {
                // 遍历所有用户,收集有效的令牌
                Object.values(users).forEach(user => {
                    if (user.fcmToken) {
                        validTokens.push(user.fcmToken);
                    }
                });
            }

            if (validTokens.length === 0) {
                console.log('没有可用的FCM令牌,跳过通知发送');
                return null;
            }

            // 3. 构建通知内容
            const payload = {
                notification: {
                    title: postTitle,
                    body: postContent,
                    // 注意:如果是Flutter项目,这个字段必须设为FLUTTER_NOTIFICATION_CLICK
                    // 原生Android/iOS根据自己的需求调整
                    click_action: 'FLUTTER_NOTIFICATION_CLICK' 
                },
                data: {
                    // 可选:传递额外数据,比如文章ID,方便客户端跳转
                    postId: context.params.msg_id,
                    title: postTitle
                }
            };

            // 4. 批量发送通知(Firebase推荐的高效方式)
            const sendResult = await admin.messaging().sendMulticast({
                tokens: validTokens,
                notification: payload.notification,
                data: payload.data
            });

            // 5. 打印发送结果,方便排查问题
            console.log(`成功发送 ${sendResult.successCount} 条通知,失败 ${sendResult.failureCount} 条`);

            // 可选:清理无效令牌(用户卸载APP后令牌会失效)
            const failedTokens = [];
            sendResult.responses.forEach((resp, index) => {
                if (!resp.success) {
                    failedTokens.push(validTokens[index]);
                }
            });

            if (failedTokens.length > 0) {
                console.log('无效的FCM令牌:', failedTokens);
                // 这里可以加逻辑删除数据库里的无效令牌,比如:
                // Object.keys(users).forEach((userId, index) => {
                //     if (failedTokens.includes(users[userId].fcmToken)) {
                //         admin.database().ref(`/users/${userId}/fcmToken`).remove();
                //     }
                // });
            }

            return null;
        } catch (error) {
            console.error('发送通知出错:', error);
            return null;
        }
    });

代码关键点说明

  • 用onCreate替代onWrite:onWrite会在节点新增、修改、删除时都触发,而你只需要发布新文章时发通知,onCreate更精准,避免不必要的触发。
  • 令牌收集逻辑:必须确保你的/users节点里存储了每个用户的FCM令牌(用户登录后要把设备的令牌上传到数据库),这是发送批量通知的前提。
  • 通知格式适配:click_action字段对Flutter项目至关重要,原生Android/iOS要根据自己的通知点击逻辑调整。
  • 批量发送优化:用sendMulticast代替循环发送单个通知,效率更高,还能直接获取成功/失败统计。

排查“控制台显示送达但收不到通知”的常见原因

  1. 无效令牌:用户卸载APP、清除数据或设备重置后,令牌会失效。上面的代码已经帮你记录了失败的令牌,你可以定期清理数据库里的无效令牌。
  2. 前台通知不显示:如果APP在前台,默认可能不会弹出通知。比如:
    • Android需要创建Notification Channel,并且配置前台通知的显示逻辑。
    • Flutter需要用flutter_local_notifications插件处理前台通知的展示。
  3. 推送权限未开启:iOS必须用户允许推送通知,Android 13+需要申请POST_NOTIFICATIONS权限,要确保客户端已经请求并获取了权限。
  4. 客户端FCM配置错误:检查Android的google-services.json或iOS的GoogleService-Info.plist是否配置正确,客户端初始化FCM时是否有报错。
  5. 通知内容问题:如果title或body为空,或者click_action设置错误,可能导致通知无法正常显示。
  6. 云函数权限问题:默认情况下Functions的服务账号有发送FCM的权限,但如果手动修改过IAM权限,要确保账号有firebase.messaging.send权限。

测试建议

  • 先测试单个令牌:在代码里临时写一个固定的有效令牌,发送测试通知,确认能收到后再批量发送。
  • 查看云函数日志:在Firebase控制台的Functions页面查看日志,看是否有错误信息(比如令牌为空、发送失败的具体原因)。
  • 客户端日志:在设备上查看FCM相关的日志,确认是否有接收通知的记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:27:31