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

Flutter中如何实现带Payload数据的Firebase推送通知及页面跳转?

Flutter Firebase推送通知携带Payload并跳转页面解决方案

原代码异常原因分析

你的代码抛出异常大概率是以下几点问题:

  1. message.data["payload"] 返回的可能是JSON字符串而非直接可访问的Map,直接用typeId["type"]会触发类型错误(String没有[]运算符)。
  2. 未处理payload格式异常的情况,比如空值、非JSON格式字符串。
  3. 页面导航时未获取到有效的BuildContext,或在非UI线程调用导航方法。
  4. 未覆盖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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:31:35