Flutter本地通知:实现前后台差异化通知展示逻辑
实现Flutter本地通知:前台自定义弹窗/后台默认展示
核心思路
借助flutter_local_notifications包的前台通知回调拦截机制:应用处于前台时,阻止系统默认通知展示,转而弹出自定义Dialog;后台时让系统按默认逻辑处理通知。
步骤1:添加依赖与基础配置
在pubspec.yaml中引入依赖:
dependencies: flutter_local_notifications: ^16.1.0
安卓配置(android/app/src/main/AndroidManifest.xml)
添加必要权限:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
iOS配置(ios/Runner/Info.plist)
添加通知权限描述与后台模式:
<key>NSUserNotificationUsageDescription</key> <string>需要通知权限来推送提醒</string> <key>UIBackgroundModes</key> <array> <string>fetch</string> <string>remote-notification</string> </array>
步骤2:初始化通知插件
创建全局通知实例,初始化时配置前台通知处理逻辑:
import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:timezone/timezone.dart' as tz; final FlutterLocalNotificationsPlugin notificationsPlugin = FlutterLocalNotificationsPlugin(); // 初始化通知插件 Future<void> initNotifications() async { // 安卓初始化设置 const AndroidInitializationSettings androidInit = AndroidInitializationSettings('@mipmap/ic_launcher'); // iOS初始化设置 const DarwinInitializationSettings iosInit = DarwinInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, ); const InitializationSettings initSettings = InitializationSettings( android: androidInit, iOS: iosInit, ); // 初始化并设置通知点击回调 await notificationsPlugin.initialize( initSettings, onDidReceiveNotificationResponse: (response) { if (response.payload != null) { debugPrint('通知负载:${response.payload}'); } }, ); // 请求安卓通知权限 await notificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>() ?.requestNotificationsPermission(); // 请求iOS通知权限 await notificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>() ?.requestPermissions(alert: true, badge: true, sound: true); }
步骤3:前台拦截与自定义弹窗实现
通过监听应用生命周期和通知流,实现前台拦截逻辑:
class _HomePageState extends State<HomePage> with WidgetsBindingObserver { @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); initNotifications(); // iOS前台禁用默认通知弹窗 notificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>() ?.setForegroundNotificationPresentationOptions(alert: false, badge: true, sound: true); // 注册前台通知监听 _setupForegroundNotificationHandler(); } void _setupForegroundNotificationHandler() { // 监听通知到达事件 notificationsPlugin.notificationStream.listen((response) { if (WidgetsBinding.instance.lifecycleState == AppLifecycleState.resumed) { // 应用在前台,弹出自定义弹窗 _showCustomDialog(response); // 取消系统默认通知(安卓需要手动取消) notificationsPlugin.cancel(response.id!); } }); } void _showCustomDialog(NotificationResponse response) { showDialog( context: context, builder: (_) => AlertDialog( title: Text(response.notificationTitle ?? '新通知'), content: Text(response.notificationBody ?? ''), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('关闭'), ), ], ), ); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); // 应用回到前台时重新监听 if (state == AppLifecycleState.resumed) { _setupForegroundNotificationHandler(); } } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } }
步骤4:创建定时通知
实现定时触发逻辑,区分前后台展示规则:
Future<void> scheduleTimedNotification() async { const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'timed_notification_channel', '定时通知渠道', channelDescription: '用于展示定时提醒', importance: Importance.max, priority: Priority.high, ); const DarwinNotificationDetails iosDetails = DarwinNotificationDetails( presentAlert: false, // iOS前台不展示默认弹窗 presentBadge: true, presentSound: true, ); const NotificationDetails notificationDetails = NotificationDetails( android: androidDetails, iOS: iosDetails, ); // 10秒后触发定时通知 await notificationsPlugin.zonedSchedule( 0, '定时提醒', '这是一条前台弹窗、后台系统通知的定时消息', tz.TZDateTime.now(tz.local).add(const Duration(seconds: 10)), notificationDetails, androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, ); }
注意事项
- 安卓需确保通知渠道已创建,首次初始化插件时会自动生成渠道。
- 测试时需分别验证前台、后台状态下的通知表现,确保权限请求成功。
内容的提问来源于stack exchange,提问作者s4nk37
相关产品推荐
相关产品推荐

