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

如何通过C#向Flutter应用发送云消息及推送通知

基于C#实现Firestore新增文档触发Flutter通知的落地方案

方案选型

你可以根据自己的运维条件二选一:

  • 方案1:C#常驻后台服务 + Firestore实时监听 + FCM推送:全链路用C#实现,逻辑完全自控,不需要依赖GCP云函数,是最贴合需求的方案
  • 方案2:Firestore云函数触发器 + C#业务接口:不需要自己维护常驻监听进程,适合运维资源有限的场景

方案1 详细操作步骤(全C#栈实现)

前置准备

  • 准备Firebase项目,在控制台「项目设置-服务账号」页面生成服务账号私钥JSON文件,妥善保存
  • 准备一台常驻运行的服务器,部署C#服务(可以是控制台程序、Windows服务、ASP.NET Core后台服务,不要把监听逻辑写在WinForm客户端里,客户端关闭会直接断连漏消息)
  • Flutter端提前集成FCM能力,将每个用户登录后的设备注册Token,存在Firestore的UserTokens集合中,集合字段至少包含UserId(对应用户唯一标识)、Token(FCM设备令牌)、LastActiveTime(设备最后活跃时间)
  • C#项目通过Nuget安装两个依赖包:Google.Cloud.Firestore、FirebaseAdmin

第一步:初始化Firestore与FCM客户端

using Google.Cloud.Firestore;
using FirebaseAdmin;
using FirebaseAdmin.Messaging;
using Google.Apis.Auth.OAuth2;

// 替换成你自己的Firebase项目ID
string projectId = "你的Firebase项目ID";
// 替换成你下载的服务账号密钥文件本地路径
string credentialPath = "你的服务账号密钥.json";

// 初始化Firestore客户端
FirestoreDb firestoreDb = FirestoreDb.Create(projectId, GoogleCredential.FromFile(credentialPath));

// 初始化FCM推送客户端
FirebaseApp.Create(new AppOptions()
{
    Credential = GoogleCredential.FromFile(credentialPath)
        .CreateScoped("https://www.googleapis.com/auth/firebase.messaging"),
    ProjectId = projectId
});
FirebaseMessaging messagingClient = FirebaseMessaging.DefaultInstance;

第二步:注册Requests集合新增文档监听

CollectionReference requestsCollection = firestoreDb.Collection("Requests");
// 初始查询游标:如果是服务首次启动,从当前时间开始监听;如果需要避免重启漏消息,可以把最后处理的文档时间存在本地配置/独立Firestore文档里,启动时读取这个时间作为查询起点
Timestamp listenStartTime = Timestamp.FromDateTime(DateTime.UtcNow);
Query listenQuery = requestsCollection.WhereGreaterThan("CreateTime", listenStartTime);

// 注册快照监听
listenQuery.Listen(async (snapshot) =>
{
    foreach (DocumentChange change in snapshot.Changes)
    {
        // 只处理新增文档事件,跳过修改、删除操作
        if (change.ChangeType != DocumentChange.Type.Added) continue;
        
        DocumentSnapshot newRequestDoc = change.Document;
        // 替换成你自己的Requests文档对应的实体类
        RequestModel newRequest = newRequestDoc.ConvertTo<RequestModel>();
        
        // 异步触发推送,不要阻塞监听线程
        _ = PushNotificationToUser(messagingClient, newRequest.TargetUserId, newRequestDoc.Id, newRequest.Content);
    }
}, ex =>
{
    // 这里加监听断连的日志、重连逻辑即可
    Console.WriteLine($"监听异常:{ex.Message}");
});

// 阻塞保持进程运行,不要让进程退出
await Task.Delay(Timeout.Infinite);

如果需要保证服务重启、断连期间的消息100%不丢,不要直接用服务启动时间作为监听起点,单独维护一个最后处理成功的文档创建时间戳,每次处理完新文档就更新这个时间戳,服务启动时从这个时间点开始监听即可

第三步:实现通知推送逻辑

async Task PushNotificationToUser(FirebaseMessaging messaging, string targetUserId, string requestId, string requestContent)
{
    // 查询目标用户绑定的所有有效设备Token
    QuerySnapshot tokenSnapshot = await firestoreDb.Collection("UserTokens")
        .WhereEqualTo("UserId", targetUserId)
        .WhereGreaterThan("LastActiveTime", Timestamp.FromDateTime(DateTime.UtcNow.AddDays(-30)))
        .GetSnapshotAsync();
    
    List<string> validTokens = tokenSnapshot.Documents.Select(d => d.GetValue<string>("Token")).ToList();
    if (!validTokens.Any()) return;

    // 构造通知内容
    MulticastMessage pushMessage = new MulticastMessage()
    {
        Tokens = validTokens,
        Notification = new Notification()
        {
            Title = "新申请提醒",
            Body = $"您收到一条新的申请:{requestContent}"
        },
        // 传递给Flutter端的业务参数
        Data = new Dictionary<string, string>()
        {
            {"requestId", requestId},
            {"action", "OPEN_REQUEST_DETAIL"}
        }
    };

    // 批量推送
    BatchResponse response = await messaging.SendMulticastAsync(pushMessage);
    
    // 清理失效的Token,避免后续重复推送无效地址
    if (response.FailureCount > 0)
    {
        List<string> invalidTokens = response.Responses
            .Zip(validTokens, (resp, token) => new { resp, token })
            .Where(item => !item.resp.IsSuccess)
            .Select(item => item.token)
            .ToList();
        // 补全从UserTokens集合删除invalidTokens的逻辑即可
    }
}

Flutter端配套处理

  • App启动时申请通知权限,初始化FCM后将当前设备的Token和登录用户ID绑定,上传到Firestore的UserTokens集合
  • 注册FCM前台、后台消息监听,点击通知时取出Data字段里的requestId,跳转到对应申请详情页
  • 应用在被杀后台状态时,FCM会自动弹出系统通知,不需要额外做保活处理

方案2 轻量实现(无常驻服务可选)

如果不想维护长期运行的C#服务进程,可以直接在Firebase控制台配置Firestore触发器,当Requests集合有新增文档时自动触发云函数,云函数中调用你部署的C# WebAPI接口做业务校验,校验通过后由C#接口调用FCM完成推送。
这种方案下C#侧只需要写普通的HTTP接口即可,不需要维护Firestore长连接监听,注意要给接口加签名校验,避免被恶意调用触发推送。

注意:绝对不要在WinForm客户端直接监听Requests集合做推送,第一是客户端无法保证24小时在线,必然出现消息漏发;第二是客户端直接读取全集合数据会有越权风险,普通用户可以通过抓包获取所有申请的敏感数据,所有监听、推送逻辑必须放在服务端运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:48:42