iOS端Flutter应用完全关闭时Airship通知点击无响应问题
问题:Flutter应用通过Urban Airship接收通知,冷启动时点击通知不执行跳转逻辑
- 应用处于前台/后台时,点击通知可正常触发
Airship.push.onNotificationResponse.listen内的页面跳转逻辑 - 应用完全关闭(上滑退出)后,点击通知仅能打开应用,不会执行上述监听内的代码
- 测试环境:Release模式,基于Urban Airship Flutter官方仓库修改,仅新增了通知点击时的页面跳转逻辑
解决方案
问题核心是冷启动时监听注册时机过晚:当应用从完全关闭状态通过通知启动时,onNotificationResponse事件会在MyApp的initState执行前触发,此时监听尚未注册,导致逻辑无法被捕获执行。
调整方案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); } }
- 在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等代码 }
- 保留原有监听
在initPlatformState中保留原有的监听,处理前台/后台状态下的通知点击:
Future<void> initPlatformState() async { // ... 其他监听代码 Airship.push.onNotificationResponse.listen(_handleNotification); // ... 其他监听代码 }
调整方案2:使用Deep Link实现跳转
另一种更可靠的方式是通过配置通知的Deep Link参数,利用Airship.onDeepLink监听处理跳转,该监听同样需要提前注册:
- 发送通知时添加
deep_link字段(如message_center) - 在
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()); }
- 在
MyApp初始化后根据缓存的目标Tab执行跳转。
内容的提问来源于stack exchange,提问作者user27729375
相关产品推荐
相关产品推荐

