Flutter集成FCM运行一段时间后停止接收通知,重启才恢复怎么解决?
问题根因
你遇到的运行一段时间后无法收到推送的问题,核心由以下几个原因导致:
- 后台消息处理函数直接操作UI组件,后台Isolate独立运行时UI相关实例为空,抛出未捕获异常后中断后续推送接收链路
- 未监听FCM Token刷新事件,Token定期失效后服务端用旧Token推送无法送达
- 后台Isolate没有单独初始化依赖服务,被系统回收后再次触发推送时直接调用相关方法抛出异常
- 云函数推送优先级不足,容易被安卓系统后台拦截
修复方案
1. 重构后台消息处理逻辑
后台消息运行在独立Isolate中,禁止直接操作UI,且需要单独初始化依赖服务:
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { // 后台Isolate必须单独初始化依赖 WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); // 单独初始化本地通知服务 FlutterLocalNotificationsPlugin localNotifications = FlutterLocalNotificationsPlugin(); const AndroidInitializationSettings initSettingsAndroid = AndroidInitializationSettings('@drawable/splash'); const InitializationSettings initSettings = InitializationSettings(android: initSettingsAndroid); await localNotifications.initialize(initSettings); // 单独创建通知通道 const AndroidNotificationChannel channel = AndroidNotificationChannel( 'high_importance_channel', 'High Importance Notifications', 'This channel is used for important notifications.', importance: Importance.high, ); await localNotifications .resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(channel); RemoteNotification notification = message.notification; if (notification != null) { await localNotifications.show( notification.hashCode, notification.title, notification.body, NotificationDetails( android: AndroidNotificationDetails( channel.id, channel.name, channel.description, icon: '@drawable/splash', playSound: true ), ) ); } // 所有UI跳转逻辑移除,放到通知点击回调中处理 }
2. 添加FCM Token同步逻辑
FCM Token会定期更新,必须监听刷新事件同步到服务端,在_MyAppState的initState中添加如下代码:
// 应用启动时获取当前Token上传 String? initialToken = await FirebaseMessaging.instance.getToken(); if (initialToken != null) { FirebaseFirestore.instance .collection('users') .doc('123456') // 替换为当前登录用户的真实ID .collection('tokens') .doc(initialToken) .set({}); } // 监听Token刷新事件,自动上传新Token FirebaseMessaging.instance.onTokenRefresh.listen((newToken) { FirebaseFirestore.instance .collection('users') .doc('123456') .collection('tokens') .doc(newToken) .set({}); });
3. 补充通知点击跳转逻辑
把页面跳转逻辑放到通知点击回调中处理,修改本地通知初始化代码:
var initializationSettingsAndroid = AndroidInitializationSettings('@drawable/splash'); var initializationSettings = InitializationSettings(android:initializationSettingsAndroid); flutterLocalNotificationsPlugin.initialize(initializationSettings, // 前台通知点击回调 onDidReceiveNotificationResponse: (response) { navigatorKey.currentState?.push(MaterialPageRoute(builder: (_) => OrdersScreen())); } ); // 后台状态下点击通知打开应用的回调 FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { navigatorKey.currentState?.push(MaterialPageRoute(builder: (_) => OrdersScreen())); });
4. 适配安卓系统限制
在android/app/src/main/AndroidManifest.xml中添加推送相关权限,降低后台被拦截概率:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
可在应用设置中引导用户开启自启动权限、关闭电池优化,进一步提升后台送达率。
5. 优化云函数推送配置
调高推送优先级,避免被系统拦截:
await admin.messaging().sendToDevice(tokens,{ notification: { title: 'You have new order!', body: `Order # ${original.uniqueOrderNumber}`, click_action: 'FLUTTER_NOTIFICATION_CLICK' } }, { priority: 'high', contentAvailable: true, });
内容的提问来源于stack exchange,提问作者mcfred
相关产品推荐
相关产品推荐

