Flutter:应用后台/终止状态下如何正确配置Pusher Beams?
问题描述
已完成Firebase控制台、Pusher Beams的注册与配置,复制flutter pusher_beams包示例项目后,实现了前台接收通知弹窗、后台通知显示在通知栏的功能,但遇到以下问题:
- 应用处于后台时点击通知,无法识别点击的通知内容,调用
PusherBeams.instance.getInitialMessage()返回null,添加延迟也无效果,断点未触发; - 应用被杀死后不知如何处理通知:使用
flutter_background_service时,设置isForegroundMode: true会出现无法隐藏的通知;设为false时,应用被杀死后服务也会停止;workmanager最快15分钟调用一次,无法满足实时需求。
现有代码
class _MyHomePageState extends State<MyHomePage> { @override initState() { super.initState(); initPusherBeams(); } initPusherBeams() async { // 查看当前订阅的兴趣组 print(await PusherBeams.instance.getDeviceInterests()); // Web端不适用 if (!kIsWeb) { await PusherBeams.instance .onInterestChanges((interests) => { print('Interests: $interests')}); await PusherBeams.instance .onMessageReceivedInTheForeground(_onMessageReceivedInTheForeground); } await _checkForInitialMessage(); } Future<void> _checkForInitialMessage() async { await Future.delayed(const Duration(seconds: 1)); final initialMessage = await PusherBeams.instance.getInitialMessage(); if (initialMessage != null) { _showAlert('Initial Message Is:', initialMessage.toString()); } } void _onMessageReceivedInTheForeground(Map<Object?, Object?> data) { _showAlert(data["title"].toString(), data["body"].toString()); } void _showAlert(String title, String message) { AlertDialog alert = AlertDialog( title: Text(title), content: Text(message), actions: const []); showDialog( context: context, builder: (BuildContext context) { return alert; }, ); } }
解决方案
问题1:后台点击通知无法获取内容
核心原因
getInitialMessage()仅针对应用完全被杀死后点击通知启动的场景,后台状态下点击通知不属于该范畴,需通过后台消息回调处理。
修复步骤
- 注册后台消息回调:在
initPusherBeams()中添加onMessageReceivedInTheBackground监听(注意该方法需为全局静态函数,避免上下文绑定问题)。 - 处理后台点击逻辑:在回调中获取通知内容,结合全局状态管理或
NavigatorKey实现UI更新或页面跳转。
修改后的代码示例:
// 全局静态函数,处理后台消息 Future<void> _onMessageReceivedInTheBackground(Map<Object?, Object?> data) async { print('后台收到通知:$data'); // 将通知数据存入全局变量,供应用前台后处理 GlobalNotificationData.notificationData = data; } class _MyHomePageState extends State<MyHomePage> { @override void initState() { super.initState(); initPusherBeams(); // 监听应用从后台回到前台的事件 WidgetsBinding.instance.addObserver(AppLifecycleObserver()); } initPusherBeams() async { print(await PusherBeams.instance.getDeviceInterests()); if (!kIsWeb) { await PusherBeams.instance.onInterestChanges((interests) => { print('Interests: $interests') }); await PusherBeams.instance .onMessageReceivedInTheForeground(_onMessageReceivedInTheForeground); // 注册后台消息回调 await PusherBeams.instance .onMessageReceivedInTheBackground(_onMessageReceivedInTheBackground); } await _checkForInitialMessage(); } // 保留原有_showAlert、_checkForInitialMessage等方法 @override void dispose() { WidgetsBinding.instance.removeObserver(AppLifecycleObserver()); super.dispose(); } } // 应用生命周期监听类 class AppLifecycleObserver extends WidgetsBindingObserver { @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { // 应用回到前台,检查未处理的通知数据 if (GlobalNotificationData.notificationData != null) { final context = GlobalNavigator.navigatorKey.currentContext; if (context != null) { showDialog( context: context, builder: (ctx) => AlertDialog( title: Text(GlobalNotificationData.notificationData!["title"].toString()), content: Text(GlobalNotificationData.notificationData!["body"].toString()), ), ); } // 处理完清空数据 GlobalNotificationData.notificationData = null; } } } } // 全局存储类 class GlobalNotificationData { static Map<Object?, Object?>? notificationData; } // 全局NavigatorKey,需在MaterialApp中配置 class GlobalNavigator { static final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); }
同时在MaterialApp中配置navigatorKey:
MaterialApp( navigatorKey: GlobalNavigator.navigatorKey, // 其他配置项 )
问题2:应用被杀死后处理通知
核心原因
flutter_background_service前台模式必须显示通知是Android API 26+的强制要求;后台模式下应用被杀死后服务会被系统回收。workmanager的15分钟限制是Android系统对后台任务的管控,无法突破。
解决方案
利用Pusher Beams本身的推送唤醒机制,结合轻量级后台回调处理:
Android端配置:
在AndroidManifest.xml中添加权限:<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />确保Pusher Beams的
PusherBeamsMessagingService已在清单中注册(通常包会自动配置)。Flutter端处理:
扩展onMessageReceivedInTheBackground回调,应用被杀死后收到通知时,系统会唤醒该回调执行轻量级任务(如更新本地数据、触发本地通知)。
示例代码:
Future<void> _onMessageReceivedInTheBackground(Map<Object?, Object?> data) async { print('应用杀死后收到通知:$data'); // 示例:更新本地数据库 await LocalDatabase.saveNotification(data); // 示例:触发本地通知 final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); await flutterLocalNotificationsPlugin.initialize( InitializationSettings( android: AndroidInitializationSettings('@mipmap/ic_launcher'), ), ); await flutterLocalNotificationsPlugin.show( DateTime.now().millisecondsSinceEpoch, data["title"].toString(), data["body"].toString(), NotificationDetails( android: AndroidNotificationDetails( 'pusher_beams_channel', 'Pusher Beams通知', importance: Importance.max, priority: Priority.high, ), ), ); }
注意:系统唤醒的回调执行时间有限(通常几秒),仅适合处理轻量级任务,无法执行耗时操作。若需复杂逻辑,可考虑在回调中启动临时isolate处理,但需注意系统资源限制。
内容的提问来源于stack exchange,提问作者Jakub Rony Roncak
相关产品推荐
相关产品推荐

