Flutter中无法读取通知消息数据问题求助
问题:FCM通知能弹出但无法读取数据,控制台报错
我用Postman调用Firebase Cloud Messaging发送通知,Android端能正常弹出通知,但Debug控制台里读取不到通知数据,同时出现以下错误日志:
D/FLTFireMsgReceiver(23051): broadcast received for message W/FLTFireMsgService(23051): A background message could not be handled in Dart as no onBackgroundMessage handler has been registered. W/FirebaseMessaging(23051): Missing Default Notification Channel metadata in AndroidManifest. Default value will be used.
以下是我的推送通知类代码:
import 'dart:io'; import 'package:cholachol_drive/globalvariables.dart'; import 'package:firebase_database/firebase_database.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; class PushNotificationService { // final FirebaseMessaging fcm = FirebaseMessaging.instance; Future initialize(context) async { FirebaseMessaging.onMessage.listen((event) { (Map<String, dynamic> message) async { // retrieveRideRequestInfo(getRideRequestId(message), context); print("onMessage: $message"); if (Platform.isAndroid) { String rideID = message["data"]['ride_id']; if (rideID != null) { print("Fucked"); } else { print('ride_id: $rideID'); } } }; }); FirebaseMessaging.onMessageOpenedApp.listen((event) { (Map<String, dynamic> message) async { // retrieveRideRequestInfo(getRideRequestId(message), context); print("onLaunch: $message"); if (Platform.isAndroid) { String rideID = message["data"]['ride_id']; if (rideID != null) { print("Fucked"); } else { print('ride_id: $rideID'); } } }; }); } Future<String> getToken() async { String token = await FirebaseMessaging.instance.getToken(); print("token: $token"); DatabaseReference tokerRef = FirebaseDatabase.instance .ref() .child("drivers/${currentFirebaseUser.uid}/token"); FirebaseMessaging.instance.subscribeToTopic('alldrivers'); FirebaseMessaging.instance.subscribeToTopic('allusers'); } }
问题原因及解决办法
1. 核心问题:回调写法错误
你在onMessage和onMessageOpenedApp的监听回调中,嵌套定义了一个未执行的匿名函数,导致实际的消息处理逻辑根本没触发。同时,FirebaseMessaging的回调参数是RemoteMessage类型,而非直接的Map,需要通过event.data获取自定义数据。
修复后的初始化代码:
Future initialize(context) async { // 处理前台收到通知 FirebaseMessaging.onMessage.listen((RemoteMessage event) { print("onMessage: ${event.data}"); if (Platform.isAndroid) { String? rideID = event.data['ride_id']; if (rideID != null) { print("ride_id: $rideID"); } else { print("ride_id is null"); } } }); // 处理点击通知打开App FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage event) { print("onMessageOpenedApp: ${event.data}"); if (Platform.isAndroid) { String? rideID = event.data['ride_id']; if (rideID != null) { print("ride_id: $rideID"); } else { print("ride_id is null"); } } }); }
2. 背景消息处理缺失
控制台提示的no onBackgroundMessage handler has been registered,意味着App在后台时无法处理通知数据。需要添加顶层静态函数作为后台处理器:
添加后台消息处理:
在PushNotificationService类外定义顶层函数:
@pragma('vm:entry-point') Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async { print("Background message data: ${message.data}"); String? rideID = message.data['ride_id']; if (rideID != null) { print("Background ride_id: $rideID"); } }
然后在initialize方法开头注册:
Future initialize(context) async { FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler); // 后续的onMessage和onMessageOpenedApp代码... }
3. 修复Android通知通道问题
控制台提示的通知通道缺失,需要在AndroidManifest.xml的<application>标签内添加配置:
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="@string/default_notification_channel_id" />
在res/values/strings.xml中定义通道ID:
<string name="default_notification_channel_id" translatable="false">default_channel</string>
可选但规范的操作:在App启动时创建该通道(需依赖flutter_local_notifications):
if (Platform.isAndroid) { const AndroidNotificationChannel channel = AndroidNotificationChannel( 'default_channel', 'Default Notifications', description: 'Channel for default notifications', importance: Importance.high, ); final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.createNotificationChannel(channel); }
4. 检查Postman请求格式
确保Postman发送的FCM请求包含data字段,示例请求体:
{ "to": "你的设备token或主题", "notification": { "title": "测试通知", "body": "这是一条测试通知" }, "data": { "ride_id": "123456" } }
仅发送notification字段时,FCM会直接展示系统通知,Dart代码无法读取自定义数据,必须同时包含data字段。
内容的提问来源于stack exchange,提问作者Aamir M Zobayer
相关产品推荐
相关产品推荐

