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

如何为基于Firestore数据库的Flutter消息应用集成Firebase Cloud Messaging推送通知?

这个需求其实很常见,用Firebase的Cloud Functions就能完美解决——它能监听Firestore的文档变化,然后触发FCM推送。我给你一步步拆解实现步骤:

1. 前期准备

首先确保你的Firebase项目已经启用了以下服务:

  • Firestore数据库(你已经在用了)
  • Firebase Cloud Messaging(FCM)
  • Cloud Functions

另外,本地要安装好Firebase CLI,并且完成项目初始化(如果还没做,运行firebase init functions选择JavaScript/TypeScript,关联你的项目)。

2. 核心:编写Cloud Function监听Firestore新增消息

我们需要写一个Cloud Function,监听消息集合的新增文档事件,当有新消息写入时,自动获取接收者的FCM令牌,然后推送通知。

假设你的消息存在messages集合,每个消息文档包含:

  • recipientId: 接收者的用户ID
  • senderId: 发送者的用户ID
  • content: 消息内容

同时你的users集合中,每个用户文档需要存储fcmToken字段(后续客户端会把设备的FCM令牌存在这里)。

示例代码(JavaScript)

打开functions/index.js,替换成以下代码:

const functions = require("firebase-functions");
const admin = require("firebase-admin");

// 初始化Firebase Admin SDK
admin.initializeApp();

// 监听messages集合的新增文档
exports.sendNewMessageNotification = functions.firestore
  .document("messages/{messageId}")
  .onCreate(async (snap, context) => {
    // 1. 获取新增的消息数据
    const newMessage = snap.data();
    const { recipientId, senderId, content } = newMessage;

    // 2. 获取接收者的FCM令牌
    const recipientDoc = await admin.firestore().collection("users").doc(recipientId).get();
    if (!recipientDoc.exists) {
      functions.logger.error(`接收者用户 ${recipientId} 不存在`);
      return null;
    }
    const fcmToken = recipientDoc.data().fcmToken;
    if (!fcmToken) {
      functions.logger.error(`接收者 ${recipientId} 未绑定FCM令牌`);
      return null;
    }

    // 3. 获取发送者的昵称(提升通知友好度)
    const senderDoc = await admin.firestore().collection("users").doc(senderId).get();
    const senderName = senderDoc.exists ? (senderDoc.data().displayName || senderId) : senderId;

    // 4. 构建FCM推送内容
    const payload = {
      notification: {
        title: `新消息来自 ${senderName}`,
        body: content,
        clickAction: "FLUTTER_NOTIFICATION_CLICK" // 针对Flutter应用,其他平台可调整为对应跳转标识
      },
      token: fcmToken
    };

    // 5. 发送通知
    try {
      const response = await admin.messaging().send(payload);
      functions.logger.log(`通知发送成功:${response}`);
      return response;
    } catch (error) {
      functions.logger.error(`通知发送失败:${error}`);
      return null;
    }
  });

3. 部署Cloud Function

在终端运行命令:

firebase deploy --only functions

部署完成后,Firebase会给你这个函数的URL,不过我们不需要直接调用它——Firestore的新增事件会自动触发它。

4. 客户端配置:获取并存储FCM令牌

客户端需要获取当前设备的FCM令牌,并存入Firestore的用户文档,这样Cloud Function才能找到要推送的设备。

示例(Flutter)

如果你用的是Flutter,先添加firebase_messaging依赖,然后在用户登录/注册后执行:

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

// 获取FCM令牌并保存到Firestore
Future<void> saveFcmToken(String currentUserId) async {
  FirebaseMessaging messaging = FirebaseMessaging.instance;
  // 请求推送权限(iOS必须,Android可选)
  NotificationSettings settings = await messaging.requestPermission(
    alert: true,
    badge: true,
    sound: true,
  );
  if (settings.authorizationStatus == AuthorizationStatus.authorized) {
    String? token = await messaging.getToken();
    if (token != null) {
      await FirebaseFirestore.instance
          .collection('users')
          .doc(currentUserId)
          .update({'fcmToken': token});
    }
  }

  // 监听令牌刷新,实时更新到Firestore
  FirebaseMessaging.instance.onTokenRefresh.listen((newToken) {
    FirebaseFirestore.instance
        .collection('users')
        .doc(currentUserId)
        .update({'fcmToken': newToken});
  });
}

其他平台(Android/iOS原生、Web)的实现逻辑类似,核心是获取令牌并同步到Firestore。

5. 测试与排障

  • 发送一条新消息到messages集合,检查Cloud Functions的日志(Firebase控制台→Functions→日志),看函数是否触发、有没有错误。
  • 如果通知没收到,检查:
    • 接收者的fcmToken是否正确存入Firestore
    • 客户端是否获取了推送权限(iOS尤其要注意)
    • FCM令牌是否有效(如果令牌过期/无效,FCM会返回错误,可在日志中看到)

额外注意事项

  • 安全规则:确保Cloud Functions的服务账号有权限读取users和messages集合(默认情况下Cloud Functions有完全访问权限,如果你自定义了Firestore安全规则,需要给服务账号开权限)。
  • 通知自定义:可以根据需求调整payload,比如添加data字段传递额外信息(比如消息ID,方便客户端点击通知跳转对应聊天界面)。
  • 批量推送:如果一个消息要推送给多个用户,可使用sendMulticast方法代替send。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 11:32:43