You need to enable JavaScript to run this app. Flutter集成FCM运行一段时间后停止接收通知,重启才恢复怎么解决?
优惠活动
大模型
产品
解决方案
定价
更多

Flutter集成FCM运行一段时间后停止接收通知,重启才恢复怎么解决?

问题根因

你遇到的运行一段时间后无法收到推送的问题,核心由以下几个原因导致:

  1. 后台消息处理函数直接操作UI组件,后台Isolate独立运行时UI相关实例为空,抛出未捕获异常后中断后续推送接收链路
  2. 未监听FCM Token刷新事件,Token定期失效后服务端用旧Token推送无法送达
  3. 后台Isolate没有单独初始化依赖服务,被系统回收后再次触发推送时直接调用相关方法抛出异常
  4. 云函数推送优先级不足,容易被安卓系统后台拦截

修复方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 11:54:03