Flutter推送通知:如何禁用FCM自动通知或捕获后台数据消息?
解决方案
需求1:阻止FCM自动创建通知,统一用flutter_local_notifications展示
Android 端配置
- 自定义
FirebaseMessagingService拦截通知,避免系统自动展示:
在android/app/src/main/kotlin/[你的包名]/下创建CustomMessagingService.kt:import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingService class CustomMessagingService : FirebaseMessagingService() { override fun onMessageReceived(remoteMessage: RemoteMessage) { // 将消息转发给Flutter端处理 FlutterFirebaseMessagingService.handleMessage(this, remoteMessage) // 不调用父类方法,阻止系统自动生成通知 } } - 修改
AndroidManifest.xml,替换默认服务:
在application标签内添加:
移除原有默认的<service android:name=".CustomMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>FirebaseMessagingService注册项。
iOS 端配置
修改AppDelegate.swift,设置通知代理拦截系统展示:
import UIKit import Flutter import Firebase import UserNotifications @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate, UNUserNotificationCenterDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { FirebaseApp.configure() UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: { _, _ in } ) application.registerForRemoteNotifications() GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } // 拦截通知展示 func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([]) // 告诉系统不自动展示 if let message = notification.request.content.userInfo as? [String: Any] { FirebaseMessaging.instance.app.send(message) // 转发给Flutter } } // 处理通知点击 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { if let message = response.notification.request.content.userInfo as? [String: Any] { FirebaseMessaging.instance.app.send(message) } completionHandler() } }
Flutter 端统一处理
监听所有消息回调,用flutter_local_notifications展示:
import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin(); final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance; void setupNotifications() async { // 初始化本地通知插件 const AndroidInitializationSettings androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); const DarwinInitializationSettings iosSettings = DarwinInitializationSettings(); const InitializationSettings settings = InitializationSettings(android: androidSettings, iOS: iosSettings); await _notificationsPlugin.initialize(settings); // 前台消息监听 FirebaseMessaging.onMessage.listen(showCustomNotification); // 后台/终止状态消息监听 FirebaseMessaging.onBackgroundMessage(_handleBackgroundMessage); } void showCustomNotification(RemoteMessage message) async { String title = message.notification?.title ?? '新通知'; String body = message.notification?.body ?? '您有一条新消息'; String? customData = message.data['custom_key']; const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'custom_notification_channel', '自定义通知', importance: Importance.high, priority: Priority.high, ); const DarwinNotificationDetails iosDetails = DarwinNotificationDetails(); const NotificationDetails details = NotificationDetails(android: androidDetails, iOS: iosDetails); await _notificationsPlugin.show( DateTime.now().millisecondsSinceEpoch, title, body, details, payload: customData, ); } // 后台消息处理(必须为顶级函数) Future<void> _handleBackgroundMessage(RemoteMessage message) async { // 重新初始化本地通知插件 const AndroidInitializationSettings androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); const DarwinInitializationSettings iosSettings = DarwinInitializationSettings(); const InitializationSettings settings = InitializationSettings(android: androidSettings, iOS: iosSettings); final FlutterLocalNotificationsPlugin notificationsPlugin = FlutterLocalNotificationsPlugin(); await notificationsPlugin.initialize(settings); String title = message.notification?.title ?? '新通知'; String body = message.notification?.body ?? '您有一条新消息'; const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'custom_notification_channel', '自定义通知', importance: Importance.high, priority: Priority.high, ); const DarwinNotificationDetails iosDetails = DarwinNotificationDetails(); const NotificationDetails details = NotificationDetails(android: androidDetails, iOS: iosDetails); await notificationsPlugin.show( DateTime.now().millisecondsSinceEpoch, title, body, details, ); }
需求2:后台/终止状态捕获仅数据消息并展示
前提配置
- Android:完成需求1中的自定义
FirebaseMessagingService配置。 - iOS:在Xcode项目设置的
Signing & Capabilities中,勾选Background Modes下的Remote notifications。
Flutter 端处理
复用需求1中的Flutter代码,核心是onBackgroundMessage回调——它会在应用终止或后台时触发数据消息的处理。
服务器数据消息格式
确保发送纯数据消息,示例结构:
{ "message": { "token": "token_1", "data": { "title": "自定义标题", "body": "自定义内容", "custom_key": "自定义扩展数据" } } }
Flutter端可从message.data中提取字段,用flutter_local_notifications展示。
内容的提问来源于stack exchange,提问作者Lalit Thakare
相关产品推荐
相关产品推荐

