Flutter本地通知权限添加:解决无声音及权限手动开启问题
Flutter本地通知:提示音修复与权限配置方案
一、解决真机通知无提示音问题
Android平台
Android 8.0(API 26)及以上依赖通知渠道,仅设置playSound: true无法保证提示音正常播放,需为渠道明确指定声音资源:
- 将自定义铃声文件(如
notification_sound.mp3)放入android/app/src/main/res/raw目录,也可直接使用系统默认铃声 - 修改
notificationDetails()方法,补充声音配置:
AndroidNotificationDetails('channelId', 'channelName', importance: Importance.max, playSound: true, // 自定义铃声配置 sound: const RawResourceAndroidNotificationSound('notification_sound'), // 或使用系统默认铃声:sound: UriAndroidNotificationSound.defaultSoundUri, channelShowBadge: true, enableVibration: true, )
注意:通知渠道一旦创建,后续通过代码修改渠道配置(如声音、震动)不会生效,需卸载重装APP或引导用户手动修改系统内的通知渠道设置
iOS平台
需确保DarwinNotificationDetails指定声音参数,同时确认权限已正常获取:
修改notificationDetails()中的iOS配置:
iOS: const DarwinNotificationDetails( sound: 'default', // 使用系统默认提示音,自定义铃声需放入iOS项目资源并配置 )
二、完善通知权限配置
Android平台
1. 配置Manifest权限
在android/app/src/main/AndroidManifest.xml中添加权限声明:
<!-- Android 13+ 必需的通知权限 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
2. 动态请求权限
添加permission_handler依赖后,在NotificationService中实现权限检查与请求逻辑:
import 'package:permission_handler/permission_handler.dart'; import 'package:flutter/foundation.dart'; // 新增:Android通知权限请求方法 Future<bool> requestAndroidNotificationPermission() async { if (await Permission.notification.isGranted) { return true; } else { PermissionStatus status = await Permission.notification.request(); return status.isGranted; } } // 修改initNotification,先请求权限再初始化 Future<void> initNotification() async { if (kIsWeb == false && defaultTargetPlatform == TargetPlatform.android) { await requestAndroidNotificationPermission(); } // 原初始化代码保留... }
iOS平台
iOS初始化阶段已请求权限,但需处理权限被拒绝的场景,引导用户前往系统设置开启:
// 新增:iOS通知权限检查方法 Future<bool> checkIOSNotificationPermission() async { NotificationSettings settings = await notificationsPlugin.getNotificationSettings(); return settings.authorizationStatus == AuthorizationStatus.authorized; } // 在initNotification末尾添加权限引导逻辑 if (kIsWeb == false && defaultTargetPlatform == TargetPlatform.iOS) { bool hasPermission = await checkIOSNotificationPermission(); if (!hasPermission) { await notificationsPlugin.openNotificationSettings(); } }
完整修改后的代码
import 'package:flutter/foundation.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:timezone/timezone.dart' as tz; class NotificationService { final FlutterLocalNotificationsPlugin notificationsPlugin = FlutterLocalNotificationsPlugin(); // Android通知权限请求 Future<bool> requestAndroidNotificationPermission() async { if (await Permission.notification.isGranted) { return true; } else { PermissionStatus status = await Permission.notification.request(); return status.isGranted; } } // iOS通知权限检查 Future<bool> checkIOSNotificationPermission() async { NotificationSettings settings = await notificationsPlugin.getNotificationSettings(); return settings.authorizationStatus == AuthorizationStatus.authorized; } Future<void> initNotification() async { // Android权限处理 if (kIsWeb == false && defaultTargetPlatform == TargetPlatform.android) { await requestAndroidNotificationPermission(); } AndroidInitializationSettings initializationSettingsAndroid = const AndroidInitializationSettings('mipmap/ic_launcher'); var initializationSettingsIOS = DarwinInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, onDidReceiveLocalNotification: (int id, String? title, String? body, String? payload) async {}); var initializationSettings = InitializationSettings( android: initializationSettingsAndroid, iOS: initializationSettingsIOS); await notificationsPlugin.initialize(initializationSettings, onDidReceiveNotificationResponse: (NotificationResponse notificationResponse) async {}); // iOS权限引导 if (kIsWeb == false && defaultTargetPlatform == TargetPlatform.iOS) { bool hasPermission = await checkIOSNotificationPermission(); if (!hasPermission) { await notificationsPlugin.openNotificationSettings(); } } } Future<NotificationDetails> notificationDetails() async { return NotificationDetails( android: AndroidNotificationDetails( 'channelId', 'channelName', importance: Importance.max, playSound: true, sound: const RawResourceAndroidNotificationSound('notification_sound'), channelShowBadge: true, enableVibration: true, ), iOS: const DarwinNotificationDetails( sound: 'default', )); } Future showNotification( {int id = 0, String? title, String? body, String? payLoad}) async { return notificationsPlugin.show( id, title, body, await notificationDetails()); } Future scheduleNotification( {int id = 0, String? title, String? body, String? payLoad, required DateTime scheduledNotificationDateTime}) async { return notificationsPlugin.zonedSchedule( id, title, body, tz.TZDateTime.from( scheduledNotificationDateTime, tz.local, ), await notificationDetails(), androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime); } }
额外注意事项
- 依赖安装:需在
pubspec.yaml中添加permission_handler包,执行flutter pub get完成安装 - Android渠道配置:首次创建的通知渠道无法通过代码修改,如需调整需卸载重装APP或引导用户手动修改系统设置
- iOS自定义铃声:需将铃声文件放入iOS项目的
Resources目录,并在Info.plist中完成配置
内容的提问来源于stack exchange,提问作者bino arin
相关产品推荐
相关产品推荐

