← 返回文章列表
开发笔记

在 Flutter 中接入 Firebase Cloud Messaging(FCM)分步指南

本文说明如何在一个 Flutter 应用里集成 Firebase Cloud Messaging(FCM),实现远程推送:获取设备令牌、处理前台/后台/完全退出后的消息,并说明 Android 与 iOS 在权限与配置上各自的注意点。

你将完成什么

  • 在 Firebase 控制台创建/绑定项目并添加 Android、iOS 应用
  • 在 Flutter 中集成 firebase_corefirebase_messaging
  • 申请通知权限、监听令牌刷新、分类处理三种状态下的推送

前置条件

  • Flutter SDK 与环境可正常 flutter run
  • Firebase 控制台 账号
  • Android:Android Studio、已创建可调试签名(debug 即可联调)
  • iOS:macOS、Xcode、Apple 开发者账号(真机推送与 APNs 需付费账号;模拟器能力有限)

官方插件文档:firebase_messagingFlutterFire 配置

第一步:Firebase 控制台与项目

  1. 打开 Firebase Console,新建项目或选择已有项目。
  2. 若尚未启用,在项目中添加 Cloud Messaging(一般随项目默认可用)。
  3. 分别 添加 Android 应用添加 iOS 应用,按向导填写包名 / Bundle ID(须与 Flutter 工程 applicationId / PRODUCT_BUNDLE_IDENTIFIER 一致)。
  4. 下载配置文件:
    • Android:google-services.json → 放到 android/app/
    • iOS:GoogleService-Info.plist → 用 Xcode 拖入 Runner 并勾选 Copy items if needed

第二步:安装 FlutterFire CLI 并生成配置(推荐)

在工程根目录执行(需已安装 Node.js):

dart pub global activate flutterfire_cli
flutterfire configure

按提示选择 Firebase 项目与平台,会在项目中生成 lib/firebase_options.dart
若你暂不使用 CLI,也可仅在原生侧放置上述配置文件,并在代码里用 DefaultFirebaseOptions 的手写方式初始化(不推荐长期维护)。

第三步:添加依赖

pubspec.yaml 中:

dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^3.8.0
  firebase_messaging: ^15.1.0

版本号请以 pub.dev 为准。然后执行:

flutter pub get

第四步:Android 工程修改

4.1 根级 android/build.gradle(或 settings.gradle 体系下的插件管理)

确保使用 Google Services插件(具体写法随 Gradle 版本可能略有不同,以 FlutterFire Android 文档 为准)。

4.2 android/app/build.gradle

  • minSdkVersion 建议 不低于 21(以当前 Firebase 要求为准)。
  • dependencies 中通常需包含 com.google.gms:google-services,并在文件末尾 apply plugin: 'com.google.gms.google-services'(若你使用较新 Gradle,可能是 plugins { id 'com.google.gms.google-services' } 形式)。

4.3 AndroidManifest.xml

  • 网络权限一般已有 INTERNET
  • Android 13(API 33)+ 若需运行时申请通知权限,使用 POST_NOTIFICATIONS(见下文 Dart 侧 requestPermission 与原生权限声明)。

4.4 通知渠道(重要)

Android 8+ 通知依赖 Notification Channel。仅依赖 firebase_messaging 时,系统默认渠道可能可用;若要与本地通知插件配合或自定义铃声/重要性,可创建渠道(也可用 flutter_local_notifications 统一创建)。

第五步:iOS 工程修改

  1. 用 Xcode 打开 ios/Runner.xcworkspace
  2. Signing & Capabilities 中:
    • 打开 Push Notifications
    • 打开 Background Modes,勾选 Remote notifications
  3. GoogleService-Info.plist 加入 Runner 目标。
  4. APNs:在 Firebase 控制台 → 项目设置 → Cloud Messaging 中上传 APNs 认证密钥(.p8)或证书,否则真机收不到远程推送。

iOS 必须在真机上完整验证推送;模拟器行为与系统版本有关,不要依赖模拟器做最终结论。

第六步:初始化 Firebase 与后台处理器

6.1 main.dart 入口

firebase_messaging 要求在 同一 isolate 里注册后台回调,且需在 runApp 之前完成 Firebase.initializeApp

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';

import 'firebase_options.dart';

@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  // 此处勿做 UI;可做轻量日志、本地存储等
}

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  runApp(const MyApp());
}

@pragma('vm:entry-point') 用于保证后台 isolate 能正确找到该顶层函数。

6.2 权限与令牌

在合适的时机(例如登录后或首页 initState):

final messaging = FirebaseMessaging.instance;

Future<void> setupFcm() async {
  final settings = await messaging.requestPermission(
    alert: true,
    badge: true,
    sound: true,
  );

  if (settings.authorizationStatus == AuthorizationStatus.denied) {
    return;
  }

  final token = await messaging.getToken();
  // 将 token 上传到你的后端,用于按设备发推送

  FirebaseMessaging.instance.onTokenRefresh.listen((newToken) {
    // 同步更新服务端
  });
}

Android 13+ 若使用 requestPermission,请确保已在 AndroidManifest.xml 声明 POST_NOTIFICATIONS 并按系统流程处理。

6.3 三种状态下的消息处理

状态说明常用监听
前台App 正在使用FirebaseMessaging.onMessage.listen
后台挂起但仍驻留onMessageOpenedApp;点击通知打开 App
终止进程被杀掉冷启动时需 getInitialMessage()

示例:

FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  // 前台默认不弹系统通知栏,可在此用 flutter_local_notifications 弹出
});

FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
  // 从通知点击进入 App(后台 → 前台)
});

final initial = await FirebaseMessaging.instance.getInitialMessage();
if (initial != null) {
  // 从终止状态由通知启动
}

第七步:从服务端或控制台发测试消息

  1. Firebase控制台 → EngageMessaging(或 Cloud Messaging)→ 新建活动 /发送测试消息。
  2. 使用上一步拿到的 FCM 注册令牌 作为测试目标。
  3. 区分 Notification payloadData payload:仅 data 时,前台/后台行为与系统展示可能不同,需按业务设计。

常见问题简表

现象可能原因
Android 收不到google-services.json 包名不一致、未应用 google-services 插件、未联网
iOS 收不到未配置 Push / Background、未上传 APNs 密钥、Bundle ID 不一致、未用真机
前台没有通知栏预期行为;需本地通知或自定义 UI
令牌为空初始化顺序错误、权限拒绝、Google Play服务异常(模拟器无 GMS)

小结

  1. Firebase 添加应用并放置 google-services.json / GoogleService-Info.plist,iOS 配置 APNs。
  2. flutterfire configure 生成 firebase_options.dart,添加 firebase_corefirebase_messaging
  3. maininitializeApp + onBackgroundMessage
  4. 请求权限、getToken、监听 onMessage / onMessageOpenedApp / getInitialMessage
  5. FCM Token存服务端,由后端调用 FCM HTTP v1 API 或经 Firebase Admin SDK 下发推送。

按上述步骤即可在 Flutter 中完成 FCM 的基础接入;若你需要富文本动作、分组、图片通知等,可再引入 flutter_local_notifications 并与 FCM 的 message.notification / data 字段协同解析。