iOS端未收到flutter_local_notifications本地通知的原因排查
针对你的代码和iOS平台特性,以下是核心问题点及修复方案:
1. 初始化阶段未正确请求核心通知权限
你的DarwinInitializationSettings里将requestAlertPermission、requestSoundPermission、requestBadgePermission全部设为false,这意味着App初始化时不会主动向用户申请这些权限。即便用户手动在系统设置中开启了权限,也需要确保代码能正确识别权限状态,或在触发通知前主动补请求权限。
修复方案:
- 初始化时将权限请求改为
true:
DarwinInitializationSettings iosInit = DarwinInitializationSettings( requestSoundPermission: true, requestBadgePermission: true, requestAlertPermission: true, onDidReceiveLocalNotification: (id, title, body, payload) => null, );
- 或在调用通知方法前主动请求权限:
await _localNotificationPlugin.requestPermissions( alert: true, badge: true, sound: true, );
2. 时区初始化时机错误
你在showScheduleNotification方法内部才调用tz.initializeTimeZones(),这会导致时区初始化不及时,可能让定时通知的时间计算出现偏差,甚至无法触发。
修复方案:
把时区初始化移到App启动入口(比如main函数),确保在任何通知逻辑执行前完成初始化:
void main() async { WidgetsFlutterBinding.ensureInitialized(); tz.initializeTimeZones(); // 移至此处 await NotificationService().initialize(); runApp(const MyApp()); }
3. iOS前台运行时默认不展示通知
iOS默认禁止App在前台弹出通知,需要额外配置才能让前台通知正常显示。
修复方案:
- 在
DarwinInitializationSettings中添加通知类别和点击回调:
DarwinInitializationSettings iosInit = DarwinInitializationSettings( // 其他参数... notificationCategories: [ DarwinNotificationCategory( 'default_category', actions: [], options: {DarwinNotificationCategoryOption.customDismissAction}, ), ], onDidReceiveNotificationResponse: (response) { // 处理通知点击逻辑 }, );
- 同时在
Info.plist中添加后台模式配置:
<key>UIBackgroundModes</key> <array> <string>remote-notification</string> </array>
4. 重复通知ID导致通知被覆盖
你的showScheduleNotification方法固定使用id: 0,多次调用时新通知会直接覆盖旧通知,导致之前的定时通知无法触发。
修复方案:
使用唯一的通知ID,比如根据时间戳生成:
await _localNotificationPlugin.zonedSchedule( DateTime.now().millisecondsSinceEpoch, // 用当前时间戳作为唯一ID title, body, // 其他参数... );
5. iOS对重复通知的限制
periodicallyShow方法在iOS上依赖系统重复通知机制,iOS对重复间隔有严格限制(最短为60秒),且仅支持官方枚举定义的间隔。如果测试间隔不符合要求,通知可能无法按时触发。
验证方案:
确保使用官方支持的RepeatInterval枚举值(比如RepeatInterval.everyMinute),同时测试时保持App在后台或锁屏状态(前台通知需额外配置)。
内容的提问来源于stack exchange,提问作者Max

