Flutter安卓应用onBackgroundMessage无法触发,求解决方案
解决Firebase后台通知接收失败问题
针对你遇到的前台能收到Firebase通知、后台无法接收的问题,以下是具体排查和修复方案:
1. 修复后台回调的隔离性问题
Firebase的onBackgroundMessage回调运行在单独的Isolate环境中,不能依赖类实例或全局变量,必须是顶级函数且内部完成所有必要初始化。你的代码中直接调用notificationService.showNotification会失败,因为后台环境无法访问这个类实例。
修改_onBackgroundMessage为独立初始化通知:
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:souhi/firebase_options.dart'; // 必须是顶级函数,不能放在类内部 Future<void> _onBackgroundMessage(RemoteMessage message) async { // 后台环境必须重新初始化Firebase await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); // 初始化本地通知插件 final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); const AndroidInitializationSettings androidInitSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); final InitializationSettings initSettings = InitializationSettings(android: androidInitSettings); await flutterLocalNotificationsPlugin.initialize(initSettings); // 创建通知渠道(Android 8.0+必填) const AndroidNotificationChannel channel = AndroidNotificationChannel( 'background_notification_channel', '后台通知渠道', description: '用于接收后台推送通知', importance: Importance.max, priority: Priority.high, ); await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.createNotificationChannel(channel); // 显示通知 const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'background_notification_channel', '后台通知渠道', importance: Importance.max, priority: Priority.high, ); const NotificationDetails notificationDetails = NotificationDetails(android: androidDetails); await flutterLocalNotificationsPlugin.show( message.messageId.hashCode, message.notification?.title ?? '新通知', message.notification?.body ?? '', notificationDetails, ); }
2. 确保通知渠道配置正确
Android 8.0及以上版本必须配置通知渠道,否则后台通知无法显示。在你的NotificationService中添加渠道创建逻辑,确保前台和后台使用同一渠道ID:
class NotificationService { final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); Future<void> initialize() async { // 初始化前台通知 const AndroidInitializationSettings androidInitSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); final InitializationSettings initSettings = InitializationSettings(android: androidInitSettings); await _flutterLocalNotificationsPlugin.initialize(initSettings); // 创建统一的通知渠道 await _createNotificationChannel(); } Future<void> _createNotificationChannel() async { const AndroidNotificationChannel channel = AndroidNotificationChannel( 'background_notification_channel', // 和后台回调用的渠道ID一致 '后台通知渠道', description: '用于接收所有推送通知', importance: Importance.max, priority: Priority.high, ); await _flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.createNotificationChannel(channel); } // 前台显示通知的方法 Future<void> showNotification(RemoteMessage message) async { const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'background_notification_channel', '后台通知渠道', importance: Importance.max, priority: Priority.high, ); const NotificationDetails notificationDetails = NotificationDetails(android: androidDetails); await _flutterLocalNotificationsPlugin.show( message.messageId.hashCode, message.notification?.title, message.notification?.body, notificationDetails, ); } }
3. 检查Firebase消息Payload格式
- 如果发送的是通知消息(包含
notification字段),Firebase会自动在后台显示通知,但需要确保渠道ID匹配。 - 如果发送的是数据消息(只有
data字段),必须在onBackgroundMessage中手动处理并显示通知,Firebase不会自动弹出。
4. 处理厂商后台限制
国内Android厂商(小米、华为、OPPO等)默认会限制应用后台运行,需要手动开启权限:
- 进入手机「设置」→「应用管理」→ 找到你的应用 → 开启「后台运行权限」「自启动权限」
- 部分机型需要开启「弹出通知权限」
5. 修正Firebase初始化逻辑
确保Firebase.initializeApp只执行一次,且在注册回调之前完成:
class FirebaseMessagingService { final NotificationService _notificationService; FirebaseMessagingService(this._notificationService); Future<void> initialize() async { print('firebase_messaging initialize'); // 先初始化Firebase await Firebase.initializeApp( name: 'Monitorer', options: DefaultFirebaseOptions.currentPlatform, ); // 设置前台通知展示选项 await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions( badge: true, sound: true, alert: true, ); // 注册后台和前台回调 FirebaseMessaging.onBackgroundMessage(_onBackgroundMessage); _registerForegroundMessageListener(); } void _registerForegroundMessageListener() { FirebaseMessaging.onMessage.listen((RemoteMessage message) async { print('firebase_messaging onMessage listen'); await _notificationService.showNotification(message); }); } }
内容的提问来源于stack exchange,提问作者César Espíndola
相关产品推荐
相关产品推荐

