Flutter中如何实现带Payload数据的Firebase推送通知及页面跳转?
Flutter Firebase推送通知携带Payload并跳转页面解决方案
原代码异常原因分析
你的代码抛出异常大概率是以下几点问题:
message.data["payload"]返回的可能是JSON字符串而非直接可访问的Map,直接用typeId["type"]会触发类型错误(String没有[]运算符)。- 未处理
payload格式异常的情况,比如空值、非JSON格式字符串。 - 页面导航时未获取到有效的
BuildContext,或在非UI线程调用导航方法。 - 未覆盖Firebase通知的所有接收场景(前台、后台、应用终止)。
完整解决方案
1. 添加依赖与基础配置
确保项目已集成Firebase Messaging,并导入dart:convert用于JSON解析:
import 'dart:convert'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart';
2. 定义全局导航Key(解决上下文问题)
用全局Key获取导航上下文,避免页面跳转时的上下文异常:
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( navigatorKey: navigatorKey, // 绑定全局导航Key home: const HomeScreen(), routes: { '/target': (context) => const TargetScreen(), // 注册目标页面路由 }, ); } }
3. 处理所有通知接收场景
Firebase通知分三种场景,需分别处理:
void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); // 场景1:应用完全终止时,点击通知启动应用 RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage(); if (initialMessage != null) { _handleNotificationPayload(initialMessage.data); } // 场景2:应用后台运行时,点击通知唤醒应用 FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { _handleNotificationPayload(message.data); }); // 场景3:应用前台运行时,收到通知 FirebaseMessaging.onMessage.listen((RemoteMessage message) { // 可先展示本地通知,再处理跳转 _handleNotificationPayload(message.data); }); runApp(const MyApp()); }
4. 解析Payload并实现页面跳转
编写统一的Payload处理函数,覆盖格式校验与解析逻辑:
void _handleNotificationPayload(Map<String, dynamic> data) { // 提取并解析Payload dynamic rawPayload = data["payload"]; Map<String, dynamic>? payloadMap; // 处理Payload为字符串的情况 if (rawPayload is String) { try { payloadMap = jsonDecode(rawPayload); } catch (e) { print("Payload解析失败:$e"); return; } } // 处理Payload为Map的情况 else if (rawPayload is Map) { payloadMap = rawPayload.cast<String, dynamic>(); } // 校验Payload有效性 if (payloadMap == null || payloadMap["type"] == null) { print("Payload格式异常"); return; } // 根据type跳转对应页面 String type = payloadMap["type"]; if (type == "XYZ") { navigatorKey.currentState?.pushNamed('/target'); // 如需携带参数,可使用pushNamed的arguments: // navigatorKey.currentState?.pushNamed('/target', arguments: payloadMap["id"]); } }
5. 发送通知的Payload格式要求
确保后台发送的通知数据格式正确,两种可选格式:
- 格式1(Payload为JSON字符串):
{ "data": { "payload": "{\"type\":\"XYZ\",\"id\":\"123\"}" }, "notification": { "title": "测试通知", "body": "点击跳转至目标页面" } }
- 格式2(Payload为Map):
{ "data": { "payload": { "type": "XYZ", "id": "123" } }, "notification": { "title": "测试通知", "body": "点击跳转至目标页面" } }
关键注意事项
- Android需在
AndroidManifest.xml中配置通知渠道,iOS需在Info.plist中开启通知权限。 - 测试时需确保设备已获取FCM令牌,且通知发送目标正确。
- 若需在前台展示通知,需集成
flutter_local_notifications插件。
内容的提问来源于stack exchange,提问作者Swatantra Singh
相关产品推荐
相关产品推荐

