Flutter点击Firebase推送(前后台/终止态)无法跳转指定页面问题
你遇到的两类点击失效问题,本质是配置冲突+逻辑时序错配,和你使用的firebase_messaging: ^11.2.6版本的默认行为强相关:
- 手动在
AndroidManifest.xml中添加FLUTTER_NOTIFICATION_CLICK的intent-filter是旧版(<10.0.0)firebase_messaging的适配逻辑,11.x版本已经在库自身的清单文件中自动注册了正确的点击分发路由,手动加自定义filter会抢占事件通道,直接导致onMessageOpenedApp永远无法触发 - 前台状态下通过
flutter_local_notifications展示通知时,没有配置正确的点击透传参数,点击事件根本没有回传到Firebase Messaging的监听链路 - 终止态下
getInitialMessage调用时机、跳转执行时机不对:如果等SplashScreen自动跳转到首页之后才获取初始消息,或者导航栈还没完成初始化就执行跳转,自然会停留在首页
第一步:修正Android端清单配置
直接删掉你之前手动添加的FLUTTER_NOTIFICATION_CLICK相关intent-filter,保留MainActivity的默认配置即可:
<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"> <!-- 仅保留默认的启动页intent-filter,删掉所有自定义的FLUTTER_NOTIFICATION_CLICK相关filter --> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity>
同时把推送服务端载荷里的"click_action": "FLUTTER_NOTIFICATION_CLICK"字段删掉,11.x版本不需要在推送载荷中传这个参数,传了反而会触发自定义intent路由,绕过Firebase的事件监听逻辑。
第二步:修正通知点击事件透传逻辑
本地通知初始化配置
初始化FlutterLocalNotificationsPlugin时不要在点击回调里写跳转逻辑,避免和Firebase的事件分发冲突:
const AndroidInitializationSettings androidInitSetting = AndroidInitializationSettings('@mipmap/ic_launcher'); const InitializationSettings initSetting = InitializationSettings(android: androidInitSetting); await flutterLocalNotificationsPlugin.initialize(initSetting);
前台消息展示配置
前台收到消息触发onMessage监听、手动弹本地通知时,才需要给Android渠道配置加clickAction参数,保证点击事件能回传给Firebase:
FirebaseMessaging.onMessage.listen((RemoteMessage message) { final RemoteNotification? notification = message.notification; final AndroidNotification? androidConfig = message.notification?.android; if (notification != null && androidConfig != null) { flutterLocalNotificationsPlugin.show( notification.hashCode, notification.title, notification.body, NotificationDetails( android: AndroidNotificationDetails( 'high_importance_channel', '高优先级通知', importance: Importance.max, priority: Priority.high, // 仅在这里加clickAction,不要在推送载荷里加 clickAction: 'FLUTTER_NOTIFICATION_CLICK', ), ), ); } });
改完这部分,后台状态下Firebase自动弹出的通知、前台状态下你手动弹的本地通知,点击后都会正常触发onMessageOpenedApp监听。
第三步:修正终止态跳转时序
getInitialMessage必须在应用启动的第一时间调用,不能等SplashScreen的定时跳转逻辑执行完再调用,跳转逻辑要等导航栈挂载完成后再执行:
- 在
main函数中初始化Firebase后立刻获取终止态点击的消息,存为全局变量:
RemoteMessage? initialMessage; Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); // 启动第一时间获取终止态通知点击的消息 initialMessage = await FirebaseMessaging.instance.getInitialMessage(); // 注册后台消息处理器 FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); runApp(const MyApp()); }
- 在根路由(或MaterialApp的home组件)的初始化逻辑中,等第一帧渲染完成、导航栈可用后再执行跳转:
@override void initState() { super.initState(); // 监听前后台运行状态下的通知点击事件 FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { _navigateToTargetPage(message.data); }); // 等页面渲染完成后处理终止态跳转 WidgetsBinding.instance.addPostFrameCallback((_) { if (initialMessage != null) { _navigateToTargetPage(initialMessage!.data); } }); } // 统一封装跳转逻辑,根据消息里的自定义参数跳转指定页 void _navigateToTargetPage(Map<String, dynamic> msgData) { if(msgData['page'] == 'detail') { Navigator.push(context, MaterialPageRoute( builder: (context) => DetailPage(contentId: msgData['id']) )); } // 其他页面路由逻辑按需补充 }
第四步:版本校验
你通过dependency_overrides锁定firebase_messaging_platform_interface: 3.1.6的配置是兼容的,改完代码后执行flutter clean再重新编译,执行flutter pub deps确认依赖树中firebase_messaging_platform_interface版本确实为3.1.6,没有被其他依赖覆盖即可。
测试时不要用Flutter的热重载/热重启功能,每次修改配置后要完全停止应用重新启动——Firebase的消息监听在热重载后不会重新注册,会出现事件不触发的假象。验证顺序:
- 完全杀掉应用,发送推送,点击通知确认能直接打开应用跳转至目标页
- 应用在前台停留时收到推送,点击通知确认触发监听、正常跳转
- 应用切到后台停留时收到推送,点击通知确认触发监听、正常跳转
内容的提问来源于stack exchange,提问作者Ahmed Elsayed

