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

Flutter: FCM后台通知大图标显示问题解决方法

FCM后台通知自定义大图标的实现方案

核心逻辑说明

应用处于后台/进程终止状态时,FCM通知分两种渲染路径:

  • 带notification字段的通知消息:完全由FCM原生SDK接管渲染,不会触发任何Flutter层业务代码,你在前台配置的flutter_local_notifications大图标规则完全不生效
  • 仅带data字段的数据消息:会触发注册的FCM后台消息回调,你可以手动调用flutter_local_notifications渲染通知,和前台逻辑完全复用,实现100%一致的展示效果

方案1:数据消息手动渲染(推荐,支持动态大图标)

这个方案可以让后台通知和前台通知的展示效果完全一致,支持每条通知配置不同的大图标。

  1. 编写顶级后台消息处理函数(必须是顶级函数,不能放在类内部,否则系统回调找不到)
    import 'package:http/http.dart' as http;
    
    @pragma('vm:entry-point')
    Future<void> _fcmBackgroundHandler(RemoteMessage message) async {
      // 初始化Firebase
      await Firebase.initializeApp();
      // 初始化本地通知插件,配置和前台初始化逻辑保持一致
      const androidInit = AndroidInitializationSettings('@mipmap/ic_launcher');
      const iosInit = DarwinInitializationSettings();
      const initSettings = InitializationSettings(android: androidInit, iOS: iosInit);
      final localNotify = FlutterLocalNotificationsPlugin();
      await localNotify.initialize(initSettings);
    
      // 解析消息参数
      final msgData = message.data;
      final String? bigIconPath = msgData['bigIcon'];
      BigPictureStyleInformation? bigPictureStyle;
    
      // 加载大图标,支持本地资源和网络图片
      if (bigIconPath != null) {
        if (bigIconPath.startsWith('http')) {
          // 网络图片需要先下载为字节流
          final res = await http.get(Uri.parse(bigIconPath));
          final iconBitmap = ByteArrayAndroidBitmap(res.bodyBytes);
          bigPictureStyle = BigPictureStyleInformation(iconBitmap);
        } else {
          // 本地drawable/mipmap资源直接加载
          bigPictureStyle = BigPictureStyleInformation(
            DrawableResourceAndroidBitmap(bigIconPath)
          );
        }
      }
    
      // 配置通知参数,和前台配置完全对齐
      final androidDetail = AndroidNotificationDetails(
        '你的通知渠道ID',
        '你的通知渠道名称',
        channelDescription: '你的通知渠道描述',
        styleInformation: bigPictureStyle,
        importance: Importance.max,
        priority: Priority.high,
      );
      const iosDetail = DarwinNotificationDetails();
      final notifyDetail = NotificationDetails(android: androidDetail, iOS: iosDetail);
    
      // 展示通知
      await localNotify.show(
        message.messageId.hashCode,
        msgData['title'],
        msgData['body'],
        notifyDetail,
      );
    }
    
  2. 在App入口注册后台回调
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp();
      // 注册后台消息处理器
      FirebaseMessaging.onBackgroundMessage(_fcmBackgroundHandler);
      runApp(const MyApp());
    }
    
  3. 调整后端推送规则
    推送payload不要携带notification字段,所有通知参数全部放在data字段中,示例payload:
    {
      "to": "目标用户设备FCM token",
      "priority": "high",
      "data": {
        "title": "通知标题",
        "body": "通知正文内容",
        "bigIcon": "大图标地址/本地资源名"
      }
    }
    

方案2:配置FCM默认大图标(无需修改后端逻辑)

如果不需要动态切换大图标,所有通知用统一的大图标,可以直接给FCM配置全局默认大图标,不需要改动现有推送结构:

  1. 将准备好的大图标文件放到安卓项目android/app/src/main/res/drawable/目录下,文件名必须全小写、无特殊字符,例如命名为default_big_icon.png
  2. 在android/app/src/main/AndroidManifest.xml的<application>标签内添加元数据配置:
    <!-- 原有小图标配置 -->
    <meta-data
      android:name="com.google.firebase.messaging.default_notification_icon"
      android:resource="@mipmap/ic_launcher" />
    <!-- 新增默认大图标配置 -->
    <meta-data
      android:name="com.google.firebase.messaging.default_notification_big_picture"
      android:resource="@drawable/default_big_icon" />
    

注意:该方案大图标固定,无法根据推送内容动态更换,仅适用于所有通知共用统一大图标场景


效果参考

  • 前台正常展示自定义大图标效果:
    前台通知效果
  • 未配置时后台默认通知效果(无大图标):
    未配置的后台通知效果
    配置完成后后台通知可实现和前台完全一致的大图标展示效果。

注意事项

  • 安卓13及以上版本需要动态申请POST_NOTIFICATIONS运行时权限,否则通知无法正常展示
  • 后台消息处理器中不要执行耗时超过10秒的操作,否则会被系统强制终止
  • 使用方案1时,payload中只要存在notification字段,FCM就会接管通知渲染,不会走自定义的本地通知逻辑
  • iOS端大图标需要在通知payload中添加mutable-content:1字段,配合Notification Service Extension实现,配置逻辑和安卓有差异

内容的提问来源于stack exchange,提问作者Ahmed Nabil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 04:21:40