Flutter中如何仅在App终止时接收FCM通知,后台不接收?
解决方案:仅在App终止状态接收FCM定时通知
要实现只在App终止时接收通知、后台不接收的需求,核心是完全接管FCM通知的展示逻辑,避免系统自动处理后台通知。具体步骤如下:
1. 后端调整:发送数据消息而非通知消息
FCM分为两种消息类型:
- 通知消息:后台状态下系统会自动弹出通知,无法通过Flutter代码拦截。
- 数据消息:仅携带自定义数据,系统不会自动展示通知,完全由我们的代码控制展示时机。
要求后端发送FCM时,只包含data字段,不要包含notification字段。示例请求体:
{ "to": "device_token", "data": { "title": "定时通知标题", "body": "定时通知内容" } }
2. Flutter代码修改
依赖引入
添加本地通知插件,用于手动展示通知:
dependencies: flutter_local_notifications: ^16.1.0 # 替换为最新版本
完整代码实现
import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; final FlutterLocalNotificationsPlugin _localNotificationsPlugin = FlutterLocalNotificationsPlugin(); // 初始化本地通知配置 Future<void> _initLocalNotifications() async { const AndroidInitializationSettings androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); // 替换为你的通知图标 const InitializationSettings initSettings = InitializationSettings(android: androidSettings); await _localNotificationsPlugin.initialize(initSettings); } // 后台消息回调:后台状态下不做任何通知处理 Future<void> _backgroundMessageHandler(RemoteMessage message) async { await Firebase.initializeApp(); // 此处不执行任何通知展示逻辑,直接返回 } void main() async { WidgetsFlutterBinding.ensureInitialized(); // 初始化Firebase await Firebase.initializeApp(options: const FirebaseOptions( apiKey: "apikey", appId: "appid", messagingSenderId: "senderid", projectId: "projid", )); // 初始化本地通知 await _initLocalNotifications(); // 处理App终止状态下的推送:仅在此时展示通知 RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage(); if (initialMessage != null) { // 构建本地通知参数 const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'timed_notification_channel', // 渠道ID '定时通知', // 渠道名称 importance: Importance.max, priority: Priority.high, ); const NotificationDetails notificationDetails = NotificationDetails(android: androidDetails); // 展示本地通知 await _localNotificationsPlugin.show( DateTime.now().millisecondsSinceEpoch % 10000, // 唯一通知ID initialMessage.data['title'] ?? '默认标题', initialMessage.data['body'] ?? '默认内容', notificationDetails, ); } // 注册后台消息回调(后台状态下不处理通知) FirebaseMessaging.onBackgroundMessage(_backgroundMessageHandler); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold(appBar: AppBar(title: const Text('FCM示例'))), ); } }
关键逻辑说明
getInitialMessage():仅在App从终止状态被推送唤醒时触发,此时我们手动展示本地通知。onBackgroundMessage():App处于后台状态时触发,但此处不执行任何通知展示操作,因此后台不会收到通知。- 本地通知插件:用于在终止状态下手动弹出通知,完全替代系统自动展示逻辑。
关于状态区分
可以明确区分App的终止和后台状态:
- 终止状态:App进程已被杀死,通过
getInitialMessage()获取推送。 - 后台状态:App在后台运行但不可见,通过
onBackgroundMessage()接收推送。
内容的提问来源于stack exchange,提问作者Samah Ahmed
相关产品推荐
相关产品推荐

