在 Flutter 中接入 Firebase Cloud Messaging(FCM)分步指南
本文说明如何在一个 Flutter 应用里集成 Firebase Cloud Messaging(FCM),实现远程推送:获取设备令牌、处理前台/后台/完全退出后的消息,并说明 Android 与 iOS 在权限与配置上各自的注意点。
你将完成什么
- 在 Firebase 控制台创建/绑定项目并添加 Android、iOS 应用
- 在 Flutter 中集成
firebase_core与firebase_messaging - 申请通知权限、监听令牌刷新、分类处理三种状态下的推送
前置条件
- Flutter SDK 与环境可正常
flutter run - Firebase 控制台 账号
- Android:Android Studio、已创建可调试签名(debug 即可联调)
- iOS:macOS、Xcode、Apple 开发者账号(真机推送与 APNs 需付费账号;模拟器能力有限)
官方插件文档:firebase_messaging、FlutterFire 配置。
第一步:Firebase 控制台与项目
- 打开 Firebase Console,新建项目或选择已有项目。
- 若尚未启用,在项目中添加 Cloud Messaging(一般随项目默认可用)。
- 分别 添加 Android 应用 与 添加 iOS 应用,按向导填写包名 / Bundle ID(须与 Flutter 工程
applicationId/PRODUCT_BUNDLE_IDENTIFIER一致)。 - 下载配置文件:
- Android:
google-services.json→ 放到android/app/ - iOS:
GoogleService-Info.plist→ 用 Xcode 拖入Runner并勾选 Copy items if needed
- Android:
第二步:安装 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 工程修改
- 用 Xcode 打开
ios/Runner.xcworkspace。 - Signing & Capabilities 中:
- 打开 Push Notifications
- 打开 Background Modes,勾选 Remote notifications
- 将 GoogleService-Info.plist 加入 Runner 目标。
- 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) {
// 从终止状态由通知启动
}
第七步:从服务端或控制台发测试消息
- Firebase控制台 → Engage → Messaging(或 Cloud Messaging)→ 新建活动 /发送测试消息。
- 使用上一步拿到的 FCM 注册令牌 作为测试目标。
- 区分 Notification payload 与 Data payload:仅 data 时,前台/后台行为与系统展示可能不同,需按业务设计。
常见问题简表
| 现象 | 可能原因 |
|---|---|
| Android 收不到 | google-services.json 包名不一致、未应用 google-services 插件、未联网 |
| iOS 收不到 | 未配置 Push / Background、未上传 APNs 密钥、Bundle ID 不一致、未用真机 |
| 前台没有通知栏 | 预期行为;需本地通知或自定义 UI |
| 令牌为空 | 初始化顺序错误、权限拒绝、Google Play服务异常(模拟器无 GMS) |
小结
- Firebase 添加应用并放置
google-services.json/GoogleService-Info.plist,iOS 配置 APNs。 flutterfire configure生成firebase_options.dart,添加firebase_core与firebase_messaging。main中initializeApp+onBackgroundMessage。- 请求权限、
getToken、监听onMessage/onMessageOpenedApp/getInitialMessage。 - 将 FCM Token存服务端,由后端调用 FCM HTTP v1 API 或经 Firebase Admin SDK 下发推送。
按上述步骤即可在 Flutter 中完成 FCM 的基础接入;若你需要富文本动作、分组、图片通知等,可再引入 flutter_local_notifications 并与 FCM 的 message.notification / data 字段协同解析。