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

Flutter中FCM后台通知重复显示问题求助

解决FCM后台接收时显示两条通知的问题

核心原因

当FCM发送包含notification字段的通知类型消息时,Android系统会在应用后台/进程杀死状态下自动展示原生通知;同时你的自定义MonServiceMessagingFirebase服务又会触发自定义通知逻辑,最终导致两条通知重复出现。

分步解决方案

1. 切换为纯数据消息格式

修改FCM发送端的消息结构,去掉notification字段,仅保留data字段。这样系统不会自动生成原生通知,所有消息都会交由你的自定义逻辑处理。
示例发送payload:

{
  "to": "目标设备令牌",
  "data": {
    "title": "自定义通知标题",
    "body": "自定义通知内容",
    "click_action": "FLUTTER_NOTIFICATION_CLICK",
    // 按需添加其他自定义业务字段
  }
}

2. 配置Flutter后台消息处理器

在Flutter层注册后台消息处理回调,确保后台收到数据消息时触发自定义通知:

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter/material.dart';
import 'dart:convert';

// 后台消息处理回调
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  
  // 配置Android通知渠道(需与前台通知渠道一致)
  const AndroidNotificationDetails androidChannel = AndroidNotificationDetails(
    'custom_notification_channel', // 自定义渠道ID
    '自定义通知渠道',
    channelDescription: '用于展示FCM自定义通知',
    importance: Importance.max,
    priority: Priority.high,
  );
  const NotificationDetails notificationDetails = NotificationDetails(android: androidChannel);
  
  // 展示自定义通知
  await flutterLocalNotificationsPlugin.show(
    DateTime.now().millisecondsSinceEpoch % 10000, // 唯一ID避免重复覆盖
    message.data['title'],
    message.data['body'],
    notificationDetails,
    payload: jsonEncode(message.data),
  );
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  
  // 注册后台消息处理器
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  
  // 初始化flutter_local_notifications(前台通知也依赖此初始化)
  const AndroidInitializationSettings androidInit = AndroidInitializationSettings('@mipmap/ic_launcher');
  const InitializationSettings initSettings = InitializationSettings(android: androidInit);
  await FlutterLocalNotificationsPlugin().initialize(initSettings);
  
  runApp(const MyApp());
}

3. 修正AndroidManifest配置

  • 移除AndroidManifest.xml中默认的FirebaseMessagingService声明(如果存在);
  • 确保自定义MonServiceMessagingFirebase服务配置正确,适配Android 12+的权限要求:
<service
    android:name=".MonServiceMessagingFirebase"
    android:exported="true">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>
  • 检查自定义服务代码,确保没有重复发送通知的逻辑(所有通知展示统一由Flutter层的前台/后台处理器完成)。

4. 统一前台通知逻辑

前台接收消息时,通过FirebaseMessaging.onMessage监听并使用相同的flutter_local_notifications逻辑展示通知,保持前后台通知样式一致:

FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  const AndroidNotificationDetails androidChannel = AndroidNotificationDetails(
    'custom_notification_channel',
    '自定义通知渠道',
    channelDescription: '用于展示FCM自定义通知',
    importance: Importance.max,
    priority: Priority.high,
  );
  const NotificationDetails notificationDetails = NotificationDetails(android: androidChannel);
  
  flutterLocalNotificationsPlugin.show(
    DateTime.now().millisecondsSinceEpoch % 10000,
    message.data['title'],
    message.data['body'],
    notificationDetails,
    payload: jsonEncode(message.data),
  );
});

关键注意事项

  • 若业务必须使用notification字段的消息,可在发送时添加click_action: "FLUTTER_NOTIFICATION_CLICK"并在AndroidManifest中配置对应Activity的intent-filter,但这种方式仍可能触发系统原生通知,优先推荐纯数据消息方案;
  • 测试时需覆盖应用前台、后台、进程杀死三种状态,确保所有场景下仅展示一条自定义通知;
  • 确保flutter_local_notifications初始化时使用的图标资源存在,避免通知图标异常。

内容的提问来源于stack exchange,提问作者pierre pontfort

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 23:14:51