Flutter: FCM后台通知大图标显示问题解决方法
FCM后台通知自定义大图标的实现方案
核心逻辑说明
应用处于后台/进程终止状态时,FCM通知分两种渲染路径:
- 带
notification字段的通知消息:完全由FCM原生SDK接管渲染,不会触发任何Flutter层业务代码,你在前台配置的flutter_local_notifications大图标规则完全不生效 - 仅带
data字段的数据消息:会触发注册的FCM后台消息回调,你可以手动调用flutter_local_notifications渲染通知,和前台逻辑完全复用,实现100%一致的展示效果
方案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, ); } - 在App入口注册后台回调
void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); // 注册后台消息处理器 FirebaseMessaging.onBackgroundMessage(_fcmBackgroundHandler); runApp(const MyApp()); } - 调整后端推送规则
推送payload不要携带notification字段,所有通知参数全部放在data字段中,示例payload:{ "to": "目标用户设备FCM token", "priority": "high", "data": { "title": "通知标题", "body": "通知正文内容", "bigIcon": "大图标地址/本地资源名" } }
方案2:配置FCM默认大图标(无需修改后端逻辑)
如果不需要动态切换大图标,所有通知用统一的大图标,可以直接给FCM配置全局默认大图标,不需要改动现有推送结构:
- 将准备好的大图标文件放到安卓项目
android/app/src/main/res/drawable/目录下,文件名必须全小写、无特殊字符,例如命名为default_big_icon.png - 在
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
相关产品推荐
相关产品推荐

