You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Flutter中FirebaseMessaging.getInitialMessage()在应用杀死后点击通知始终返回NULL的问题

Flutter中FirebaseMessaging.getInitialMessage()在应用杀死后点击通知始终返回NULL的问题

我明白你现在遇到的这个问题有多头疼——应用完全杀死后点击推送通知,FirebaseMessaging.getInitialMessage()一直返回NULL,没法正常触发跳转逻辑对吧?结合你贴的代码,我帮你梳理下问题出在哪,以及怎么一步步修复:


问题根源分析

从你的代码来看,核心问题出在Firebase消息链路和本地通知链路的割裂

  1. FirebaseMessaging.getInitialMessage() 只会在由Firebase系统直接触发的应用冷启动时返回消息(比如后台收到Firebase消息后,直接点击系统级的Firebase通知启动应用)。
  2. 但你在处理后台消息时,是通过 flutter_local_notifications 手动展示通知的,这种本地通知触发的冷启动,Firebase不会自动关联原始消息,所以getInitialMessage()拿不到任何数据。
  3. 你虽然把payload存在了AppStateStore里,但冷启动时的登录前置逻辑,导致_handlePushPayload在登录完成前没法处理payload,后续也没有兜底触发的逻辑。

解决方案(结合你的代码修改)

我们需要把Firebase消息和本地通知的payload处理逻辑统一,同时补充冷启动+登录后的兜底跳转逻辑:

步骤1:统一Payload的存储与读取逻辑

确保所有通知(不管是Firebase还是本地通知)的payload都存在AppStateStore,并且点击事件都走统一的处理入口:

// 修复_configurePayloadMessage,确保冷启动时payload被正确存储
@pragma('vm:entry-point')
Future<void> _configurePayloadMessage(NotificationResponse response) async {
  if (response.payload == null || response.payload!.isEmpty) return;
  final payload = _convertStringToJson(response.payload);
  final pushPayload = PushPayloadModel(
    type: payload['type'] as String?,
    username: payload['username'] as String?,
    data: payload,
  );
  AppStateStore().setPushPayload(pushPayload);

  // 冷启动时还没登录,不立即跳转,等登录后再处理
  if (SdkController.isSessionOpened) {
    handlePayloadNavigation(payload);
    AppStateStore().clearPushPayload();
  }
}

步骤2:修复冷启动时的Payload处理逻辑

修改_handleInitialMessage,同时覆盖Firebase启动和本地通知启动两种场景:

Future<void> _handleInitialMessage() async {
  // 1. 处理Firebase直接触发的冷启动
  final RemoteMessage? firebaseMessage = await FirebaseMessaging.instance.getInitialMessage();
  if (firebaseMessage != null) {
    final pushPayload = PushPayloadModel.fromNotification(firebaseMessage);
    AppStateStore().setPushPayload(pushPayload);
    if (SdkController.isSessionOpened) {
      handlePayloadNavigation(firebaseMessage.data);
      AppStateStore().clearPushPayload();
    }
  } 
  // 2. 处理本地通知触发的冷启动(此时firebaseMessage为null,读取AppStateStore的缓存)
  else {
    final localPayload = AppStateStore().pushPayloadModel;
    if (localPayload != null && SdkController.isSessionOpened) {
      handlePayloadNavigation(localPayload.data!);
      AppStateStore().clearPushPayload();
    }
  }
}

步骤3:补充登录成功后的兜底跳转

因为冷启动时用户还没登录,_handlePushPayload会跳过处理,所以需要在登录成功的回调里主动检查未处理的payload:

// 假设这是你的登录成功处理方法
Future<void> onLoginSuccess(UserInfoModel user) async {
  // 登录成功后的常规逻辑...
  state.userInfoModel = user;
  
  // 兜底检查未处理的推送payload
  final pendingPayload = AppStateStore().pushPayloadModel;
  if (pendingPayload != null && pendingPayload.type != null) {
    // 校验用户匹配性
    if (pendingPayload.username == user.login) {
      handlePayloadNavigation(pendingPayload.data!);
      AppStateStore().clearPushPayload();
    }
  }
}

步骤4:优化HomeController的_handlePushPayload逻辑

确保在页面初始化完成后,能处理已登录状态下的pending payload:

void _handlePushPayload() {
  final payload = state.pushPayloadModel;
  if (payload == null || payload.type == null) return;
  
  // 校验用户匹配
  if (payload.username != state.userInfoModel.login) return;
  
  // 触发跳转
  handlePayloadNavigation(payload.data!);
  state.clearPushPayload();
}

关键注意点

  1. 所有通知的点击事件,不管是前台、后台还是冷启动,都要把payload存在AppStateStore,不要依赖Firebase的getInitialMessageonMessageOpenedApp兜底。
  2. 跳转逻辑必须在用户登录完成后触发,所以一定要在登录成功的回调里补充兜底检查,避免冷启动时还没登录就触发跳转导致异常。
  3. 记得在处理完payload后调用clearPushPayload(),避免重复触发跳转。

火山引擎 最新活动