Flutter集成FCM时onBackgroundMessage触发崩溃,通知无法显示求助
问题解决方案
一、修复应用终止状态下FCM崩溃问题
你的onBackgroundMessage使用匿名函数的方式不符合FCM后台消息处理要求,必须使用顶级异步函数,且函数内部需要重新初始化Firebase(后台隔离环境无默认初始化)。修改如下:
// 必须是顶级函数,不能放在类或方法内部 Future<void> firebaseMessagingBackgroundHandler(Map<String, dynamic> message) async { await Firebase.initializeApp(); print("Handling a background message: ${message['data']}"); // 后台消息触发本地通知 await showNotification(message); } // 初始化FCM监听逻辑 void setupFCM() { FirebaseMessaging.onMessage.listen((RemoteMessage message) { print("Foreground message data: ${message.data}"); showNotification(message); }); FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { print("Resumed message data: ${message.data}"); // 应用从后台恢复后的自定义逻辑 }); // 绑定后台消息处理函数,必须指向顶级函数 FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler); }
关键注意点:
onBackgroundMessage只能绑定顶级函数,匿名函数会导致应用终止时崩溃- 后台函数内必须手动初始化Firebase,否则无法正常调用Firebase相关API
二、集成flutter_local_notifications解析FCM数据并显示通知
1. 初始化本地通知插件
在应用启动时(如initState)完成初始化:
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); Future<void> initLocalNotifications() async { // Android初始化配置 const AndroidInitializationSettings androidInitSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); // iOS初始化配置 const IOSInitializationSettings iosInitSettings = IOSInitializationSettings(); const InitializationSettings initSettings = InitializationSettings( android: androidInitSettings, iOS: iosInitSettings); await flutterLocalNotificationsPlugin.initialize(initSettings, // 可选:处理通知点击事件 onSelectNotification: (String? payload) async { if (payload != null) { Map<String, dynamic> data = jsonDecode(payload); print('通知点击数据:$data'); // 这里可添加页面跳转等逻辑 } }); }
2. 解析FCM消息并显示通知
完善showNotification函数,兼容FCM的两种消息格式(RemoteMessage和旧版Map):
import 'dart:convert'; Future<void> showNotification(dynamic message) async { String title; String body; Map<String, dynamic> data; // 适配新版FCM RemoteMessage格式 if (message is RemoteMessage) { title = message.notification?.title ?? '系统通知'; body = message.notification?.body ?? '收到一条新消息'; data = message.data; } // 兼容旧版Map格式 else if (message is Map<String, dynamic>) { title = message['notification']?['title'] ?? message['data']?['title'] ?? '系统通知'; body = message['notification']?['body'] ?? message['data']?['body'] ?? '收到一条新消息'; data = message['data'] ?? {}; } // 默认兜底 else { title = '未知通知'; body = '收到一条未知消息'; data = {}; } var androidDetails = AndroidNotificationDetails( 'fcm_notification_channel', // 渠道ID必须唯一 'FCM通知渠道', '用于显示FCM推送的通知', importance: Importance.max, priority: Priority.high, showWhen: true, ); var iosDetails = IOSNotificationDetails(); var platformDetails = NotificationDetails(android: androidDetails, iOS: iosDetails); // 显示通知,用时间戳作为id避免重复覆盖 await flutterLocalNotificationsPlugin.show( DateTime.now().millisecond, title, body, platformDetails, payload: jsonEncode(data), // 将消息数据转为JSON字符串,点击时可获取 ); }
三、额外注意事项
- 确保AndroidManifest.xml和Info.plist已配置好FCM所需的权限、服务和推送证书
- 应用终止状态下,FCM的
notification类型消息由系统直接显示,data类型消息需要通过onBackgroundMessage触发本地通知 - 测试后台推送建议使用真实设备,部分模拟器对后台消息支持不完善
内容的提问来源于stack exchange,提问作者mideveloper
相关产品推荐
相关产品推荐

