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

iOS端Flutter应用完全关闭时Airship通知点击无响应问题

问题:Flutter应用通过Urban Airship接收通知,冷启动时点击通知不执行跳转逻辑
  • 应用处于前台/后台时,点击通知可正常触发Airship.push.onNotificationResponse.listen内的页面跳转逻辑
  • 应用完全关闭(上滑退出)后,点击通知仅能打开应用,不会执行上述监听内的代码
  • 测试环境:Release模式,基于Urban Airship Flutter官方仓库修改,仅新增了通知点击时的页面跳转逻辑

解决方案

问题核心是冷启动时监听注册时机过晚:当应用从完全关闭状态通过通知启动时,onNotificationResponse事件会在MyApp的initState执行前触发,此时监听尚未注册,导致逻辑无法被捕获执行。

调整方案1:提前注册监听+全局状态缓存事件

  1. 在main函数中提前注册监听
    在Airship.takeOff完成后立即注册通知响应监听,确保冷启动时事件能被捕获,同时将事件缓存到全局状态:
// 全局状态类,用于缓存冷启动时的通知事件
class GlobalNotificationCache {
  static NotificationResponseEvent? pendingEvent;
}

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  // ... 设备方向、Airship配置等初始化代码

  Airship.takeOff(config);

  // 提前注册通知响应监听,缓存冷启动事件
  Airship.push.onNotificationResponse.listen((event) {
    if (WidgetsBinding.instance.lifecycleState != AppLifecycleState.resumed) {
      GlobalNotificationCache.pendingEvent = event;
    } else {
      // 前台/后台状态直接处理
      _handleNotification(event);
    }
  });

  // ... 其他Airship配置代码
  runApp(const MyApp());
}

// 全局通用的通知处理逻辑
void _handleNotification(NotificationResponseEvent event) {
  debugPrint('Notification Response $event');
  // 这里需要通过全局路由Key或状态管理来触发页面跳转,示例中使用全局导航Key
  if (MyApp.navigatorKey.currentState != null) {
    // 示例:跳转至指定Tab页,可根据通知内容动态调整
    final tabController = MyApp.tabController;
    tabController?.animateTo(1);
  }
}
  1. 在Widget初始化后处理缓存事件
    在MyApp的状态类中,初始化完成后检查并处理缓存的冷启动事件:
class MyApp extends StatefulWidget {
  const MyApp({super.key});
  static GlobalKey<NavigatorState> navigatorKey = GlobalKey();
  static TabController? tabController;

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  @override
  void initState() {
    super.initState();
    MyApp.tabController = TabController(length: 4, vsync: this);
    
    // 处理冷启动时缓存的通知事件
    if (GlobalNotificationCache.pendingEvent != null) {
      _handleNotification(GlobalNotificationCache.pendingEvent!);
      GlobalNotificationCache.pendingEvent = null;
    }

    initPlatformState();
    // ... 其他初始化代码
  }

  // 复用全局处理逻辑
  void _handleNotification(NotificationResponseEvent event) {
    debugPrint('Handled cold start Notification Response $event');
    MyApp.tabController?.animateTo(1);
  }

  // ... 原有build、initPlatformState等代码
}
  1. 保留原有监听
    在initPlatformState中保留原有的监听,处理前台/后台状态下的通知点击:
Future<void> initPlatformState() async {
  // ... 其他监听代码
  Airship.push.onNotificationResponse.listen(_handleNotification);
  // ... 其他监听代码
}

调整方案2:使用Deep Link实现跳转

另一种更可靠的方式是通过配置通知的Deep Link参数,利用Airship.onDeepLink监听处理跳转,该监听同样需要提前注册:

  1. 发送通知时添加deep_link字段(如message_center)
  2. 在main函数中提前注册Deep Link监听:
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  // ... 初始化代码

  Airship.takeOff(config);

  Airship.onDeepLink.listen((event) {
    switch (event.deepLink) {
      case "message_center":
        GlobalNotificationCache.targetTab = 1;
        break;
      case "home":
        GlobalNotificationCache.targetTab = 0;
        break;
    }
  });

  // ... 其他代码
  runApp(const MyApp());
}
  1. 在MyApp初始化后根据缓存的目标Tab执行跳转。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 01:27:13