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是第三方测试代理地址,存在转发丢消息的风险。
修复步骤
- 把Firebase初始化、FCM监听注册、主题订阅逻辑全部移到App启动入口,在
runApp之前执行,绝对不要放到业务逻辑里延迟执行。 - 修正发送接口地址和消息载荷格式,补全必填参数。
- 提前配置好安卓通知权限和通知渠道,保证参数匹配。
修正后代码示例
启动入口初始化逻辑
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
相关产品推荐
相关产品推荐

