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

Flutter firebase_messaging:^11.4.2 FCM代码推送无法接收问题

Flutter firebase_messaging: ^11.4.2 版本FCM功能异常修复

控制台手动发通知能正常接收、接口调用返回200但设备收不到消息,是以下几个代码逻辑错误叠加导致的:

  • 监听注册时机完全错误:你在发送请求拿到200响应之后才注册FirebaseMessaging.onMessage监听,FCM推送是异步过程,等你注册监听时消息早就送达设备被系统丢弃,根本触发不了回调。
  • 初始化顺序错误:Firebase.initializeApp()被放在发送消息的成功回调里执行,Firebase核心实例未完成初始化时,所有FCM相关调用都不会生效。
  • Topic订阅缺失+载荷格式不规范:代码中未调用订阅接口将当前设备加入fcm_test主题;Topic消息未使用标准的to字段格式;缺失高优先级、通知渠道ID等关键参数,安卓系统会直接拦截不规范的通知。
  • 发送地址非官方:你使用的https://api.rnfirebase.io/messaging/send是第三方测试代理地址,存在转发丢消息的风险。

修复步骤

  1. 把Firebase初始化、FCM监听注册、主题订阅逻辑全部移到App启动入口,在runApp之前执行,绝对不要放到业务逻辑里延迟执行。
  2. 修正发送接口地址和消息载荷格式,补全必填参数。
  3. 提前配置好安卓通知权限和通知渠道,保证参数匹配。

修正后代码示例

启动入口初始化逻辑

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // 最先初始化Firebase核心
  await Firebase.initializeApp();
  // 初始化本地通知插件、创建通知渠道
  await flutterLocalNotificationsPlugin.initialize(/* 你的初始化配置 */);
  const AndroidNotificationChannel channel = AndroidNotificationChannel(
    'fcm_default_channel', // 固定ID,后续载荷里要和这个一致
    '默认通知',
    description: 'FCM推送默认通知渠道',
    importance: Importance.high,
  );
  await flutterLocalNotificationsPlugin
      .resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
      ?.createNotificationChannel(channel);
  // 注册FCM全场景监听
  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    RemoteNotification? notification = message.notification;
    AndroidNotification? android = message.notification?.android;
    if (notification != null && android != null && !kIsWeb) {
      flutterLocalNotificationsPlugin.show(
        notification.hashCode,
        notification.title,
        notification.body,
        NotificationDetails(
          android: AndroidNotificationDetails(
            channel.id,
            channel.name,
            channelDescription: channel.description,
            icon: 'launch_background',
          ),
        ),
      );
    }
  });
  // 注册后台通知点击监听,避免漏处理
  FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    // 这里写通知点击后的页面跳转逻辑
  });
  // 订阅目标主题
  await FirebaseMessaging.instance.subscribeToTopic("fcm_test");
  runApp(const MyApp());
}

消息发送逻辑

Future<void> sendPushMessage() async {
  try {
    final response = await http.post(
      Uri.parse('https://fcm.googleapis.com/fcm/send'),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
        'Authorization': 'key=你的FCM服务端密钥'
      },
      body: constructFCMPayload(),
    );
    if(response.statusCode == 200){
      print('发送请求已提交');
      // 禁止在这里写初始化、注册监听的逻辑
    }else{
      print('发送失败,状态码:${response.statusCode},返回内容:${response.body}');
    }
  } catch (e) {
    print('发送异常:$e');
  }
}

String constructFCMPayload() {
  _messageCount++;
  return jsonEncode({
    // Topic消息固定用to字段,格式必须是/topics/主题名
    'to': "/topics/fcm_test",
    // 发单设备消息替换为'to': _token即可
    'priority': 'high', // 安卓高优先级,避免被系统休眠拦截
    'data': {
      'via': 'FlutterFire Cloud Messaging!!!',
      'count': _messageCount.toString(),
    },
    'notification': {
      'title': 'Hello FlutterFire!',
      'body': 'This notification (#$_messageCount) was created via FCM!',
      'android_channel_id': 'fcm_default_channel', // 和前面创建的渠道ID完全一致
    },
  });
}

额外注意事项

  • 安卓13及以上版本必须在AndroidManifest.xml中声明POST_NOTIFICATIONS权限,并且动态申请用户授权,否则通知无法弹出。
  • FCM接口返回200仅代表请求格式合法被服务端接收,不代表消息一定送达设备,需结合控制台送达统计排查。
  • 控制台发消息能正常接收是因为控制台自动补全了优先级、通知渠道等参数,自定义接口调用时必须手动配置这些参数。
  • 测试后台推送时尽量打release包,debug模式下系统省电策略会干扰推送送达逻辑。

内容的提问来源于stack exchange,提问作者Mohit Saini

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 12:31:02