Flutter集成FCM后,如何实现后台收消息且自定义通知而非自动显示?
Flutter FCM后台自定义通知实现方案
要实现后台接收FCM消息且完全自定义通知样式,核心是避开系统自动处理的通知消息,改用数据消息 + 本地通知插件来实现,以下是分步骤的具体操作:
第一步:后端发送「数据消息」而非「通知消息」
FCM消息分两种类型,只有数据消息不会被系统自动弹出通知,完全由App控制:
- 通知消息:后台/锁屏时系统直接弹通知,无法拦截自定义
- 数据消息:系统仅传递数据,App接收后自行处理
后端发送消息时,必须使用纯数据格式(不要带notification字段),示例JSON:
{ "to": "目标设备的FCM Token", "data": { "title": "你的自定义标题", "content": "你的自定义内容", "extra_data": "需要传递的额外参数" } }
第二步:Flutter端配置与逻辑实现
需要用到firebase_messaging(处理FCM消息接收)和flutter_local_notifications(自定义通知样式)两个包:
1. 初始化本地通知插件
先配置本地通知的基础设置,确保能自定义样式:
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; final FlutterLocalNotificationsPlugin _localNotifPlugin = FlutterLocalNotificationsPlugin(); Future<void> initLocalNotifications() async { // Android初始化:指定通知图标(用你自己的图标资源) const androidInit = AndroidInitializationSettings('@mipmap/ic_launcher'); // iOS初始化 const iosInit = DarwinInitializationSettings(); const initSettings = InitializationSettings(android: androidInit, iOS: iosInit); await _localNotifPlugin.initialize(initSettings); // Android 8.0+必须创建通知渠道 await _createAndroidNotificationChannel(); } // 创建自定义通知渠道(Android专属) Future<void> _createAndroidNotificationChannel() async { const channel = AndroidNotificationChannel( 'fcm_custom_channel', // 唯一渠道ID 'FCM自定义通知', // 渠道名称 description: '用于显示自定义样式的FCM通知', importance: Importance.high, // 通知重要性 ); await _localNotifPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(channel); }
2. 设置FCM后台消息处理器
后台消息的处理函数必须是顶级函数或静态函数(因为Flutter后台隔离环境无法访问类实例),在这里实现自定义通知的显示逻辑:
import 'package:firebase_messaging/firebase_messaging.dart'; // 后台消息处理回调(顶级函数) Future<void> fcmBackgroundMessageHandler(RemoteMessage message) async { // 仅处理数据消息 if (message.data.isEmpty) return; // 从数据中提取自定义内容 final title = message.data['title'] ?? '默认标题'; final content = message.data['content'] ?? '默认内容'; final extra = message.data['extra_data']; // 构建自定义通知样式 const androidDetails = AndroidNotificationDetails( 'fcm_custom_channel', // 和之前创建的渠道ID一致 'FCM自定义通知', importance: Importance.high, priority: Priority.high, // 可以添加更多自定义属性:大图标、小图标、进度条、样式模板等 ); const iosDetails = DarwinNotificationDetails(); const notifDetails = NotificationDetails(android: androidDetails, iOS: iosDetails); // 显示自定义通知 await _localNotifPlugin.show( DateTime.now().millisecondsSinceEpoch, // 唯一通知ID(避免重复) title, content, notifDetails, payload: extra, // 点击通知时传递的参数 ); } // 初始化FCM Future<void> initFCM() async { final messaging = FirebaseMessaging.instance; // 请求iOS通知权限(Android默认开启,iOS必须主动请求) await messaging.requestPermission( alert: true, badge: true, sound: true, ); // 设置后台消息处理器 FirebaseMessaging.onBackgroundMessage(fcmBackgroundMessageHandler); // 可选:前台消息监听(App在前台时也用自定义通知) FirebaseMessaging.onMessage.listen((message) { if (message.data.isNotEmpty) { // 复用后台的通知显示逻辑即可 } }); }
第三步:平台专属配置
Android端配置
- 无需修改
AndroidManifest.xml中的FCM服务配置,数据消息不会触发系统默认通知 - 确保通知图标资源存在(
@mipmap/ic_launcher对应你自己的应用图标)
iOS端配置
- 在
Info.plist中添加以下配置,禁止FCM代理自动处理通知:
<key>FirebaseAppDelegateProxyEnabled</key> <false/>
- 在Xcode中开启后台模式:选择你的项目 -> Signing & Capabilities -> 添加Background Modes -> 勾选「Remote notifications」
- 注意:iOS后台消息的送达受系统严格限制,App被完全杀死后可能无法及时接收,这是iOS系统机制,无法绕过
关键注意事项
- 绝对不能发送带
notification字段的混合消息,否则系统仍会自动弹出默认通知 - 后台消息处理器必须是顶级/静态函数,不能是类的成员方法
- 测试时,确保设备处于后台/锁屏状态,验证自定义通知是否正常显示
内容的提问来源于stack exchange,提问作者yalda mohasseli
相关产品推荐
相关产品推荐

