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

Flutter点击FCM通知打开APP后未弹窗的问题排查

问题原因

当APP处于完全关闭(终止)状态时,点击FCM通知启动APP,消息不会触发前台场景的onMessage回调,而是需要通过FirebaseMessaging.instance.getInitialMessage()获取启动时的消息。你当前的代码仅处理了前台接收消息的逻辑,缺失冷启动场景的消息处理,导致弹窗不出现。

修复步骤

1. 在main.dart中处理冷启动消息

初始化Firebase后,检查是否是通过点击FCM通知启动的APP,若存在启动消息,将其传递给后续页面:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  // 获取冷启动时的FCM消息
  RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage();
  
  runApp(MyApp(initialNotification: initialMessage));
}

class MyApp extends StatelessWidget {
  final RemoteMessage? initialNotification;

  const MyApp({super.key, this.initialNotification});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: LoadingScreen(initialNotification: initialNotification),
    );
  }
}

2. 在LoadingScreen中传递消息到HomeScreen

由于页面流程是main→loading→home,需在LoadingScreen完成加载逻辑后,将启动消息传递给HomeScreen:

class LoadingScreen extends StatefulWidget {
  final RemoteMessage? initialNotification;

  const LoadingScreen({super.key, this.initialNotification});

  @override
  State<LoadingScreen> createState() => _LoadingScreenState();
}

class _LoadingScreenState extends State<LoadingScreen> {
  @override
  void initState() {
    super.initState();
    // 模拟加载流程(如登录校验)
    Future.delayed(const Duration(seconds: 2), () {
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(
          builder: (context) => HomeScreen(initialNotification: widget.initialNotification),
        ),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(child: CircularProgressIndicator()),
    );
  }
}

3. 在HomeScreen中统一处理所有场景的消息

修改HomeScreen,同时处理冷启动消息、前台消息、后台点击通知的消息:

class HomeScreen extends StatefulWidget {
  final RemoteMessage? initialNotification;

  const HomeScreen({super.key, this.initialNotification});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  void initState() {
    super.initState();
    // 处理冷启动带来的消息
    if (widget.initialNotification != null) {
      _showNotificationDialog(widget.initialNotification!);
    }

    // 处理前台实时接收的消息
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      _showNotificationDialog(message);
    });

    // 处理APP在后台时点击通知的情况
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      _showNotificationDialog(message);
    });
  }

  void _showNotificationDialog(RemoteMessage message) {
    // 弹窗展示逻辑,示例使用AlertDialog
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text(message.notification?.title ?? '通知'),
        content: Text(message.notification?.body ?? ''),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('关闭'),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(child: Text('首页')),
    );
  }
}

4. 检查FCM通知Payload配置

确保发送的FCM通知包含click_action: FLUTTER_NOTIFICATION_CLICK(Android端必填),否则点击通知可能无法正确触发回调,示例Payload:

{
  "notification": {
    "title": "测试通知",
    "body": "这是一条测试消息",
    "click_action": "FLUTTER_NOTIFICATION_CLICK"
  },
  "data": {
    "key": "value"
  },
  "to": "目标设备Token"
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 05:33:25