You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 02:50:28