Flutter定时通知遇两类PlatformException:求错误分析与解决方案
解决Flutter定时通知的两类PlatformException错误
错误一:应用启动时的invalid_icon异常
报错信息
E/flutter ( 7984): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(invalid_icon, The resource flutter_logo could not be found. Please make sure it has been added as a drawable resource to your Android head project., null, null) E/flutter ( 7984): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:651:7) E/flutter ( 7984): #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:322:18) E/flutter ( 7984): <asynchronous suspension> E/flutter ( 7984): #2 AndroidFlutterLocalNotificationsPlugin.initialize (package:flutter_local_notifications/src/platform_flutter_local_notifications.dart:142:12) E/flutter ( 7984): <asynchronous suspension> E/flutter ( 7984): #3 NotificationService.initNotification (package:agriplus/Screens/Schedule%20Notification/notificationService.dart:23:5) E/flutter ( 7984): <asynchronous suspension>
原因
初始化flutter_local_notifications时,Android端指定的图标flutter_logo不存在于项目的drawable资源目录中。
代码问题
在NotificationService的initNotification方法里,AndroidInitializationSettings传入了不存在的图标名称:
AndroidInitializationSettings initializationSettingsAndroid = const AndroidInitializationSettings('flutter_logo');
解决方案
有两种处理方式:
- 添加图标资源:将名为
flutter_logo的png图片放到Android项目的android/app/src/main/res/drawable目录下。 - 使用默认/现有图标:改为使用应用启动图标或系统默认图标:
// 使用应用启动图标(需确保mipmap目录有ic_launcher) AndroidInitializationSettings initializationSettingsAndroid = const AndroidInitializationSettings('@mipmap/ic_launcher'); // 或者使用系统默认图标 AndroidInitializationSettings initializationSettingsAndroid = const AndroidInitializationSettings('');
错误二:点击定时按钮时的exact_alarms_not_permitted异常
报错信息
E/flutter ( 7984): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(exact_alarms_not_permitted, Exact alarms are not permitted, null, null) E/flutter ( 7984): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:651:7) E/flutter ( 7984): #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:322:18) E/flutter ( 7984): <asynchronous suspension> E/flutter ( 7984): #2 AndroidFlutterLocalNotificationsPlugin.zonedSchedule (package:flutter_local_notifications/src/platform_flutter_local_notifications.dart:191:5) E/flutter ( 7984): <asynchronous suspension> E/flutter ( 7984): #3 FlutterLocalNotificationsPlugin.zonedSchedule (package:flutter_local_notifications/src/flutter_local_notifications_plugin.dart:352:7) E/flutter ( 7984): <asynchronous suspension>
原因
Android 12(API 31)及以上版本,使用精确定时闹钟需要SCHEDULE_EXACT_ALARM权限,仅在AndroidManifest.xml中声明权限不够,还需要动态向用户申请权限,部分系统会限制该权限的自动授予。
代码问题
- 仅在Manifest中声明了权限,但未实现动态权限申请逻辑。
- 调用
zonedSchedule时直接执行,未检查权限是否已授予。
解决方案
步骤1:添加权限处理依赖
在pubspec.yaml中添加permission_handler包:
dependencies: permission_handler: ^10.2.0
步骤2:在NotificationService中新增权限检查方法
import 'package:permission_handler/permission_handler.dart'; class NotificationService { // ... 原有代码 ... Future<bool> requestExactAlarmPermission() async { if (await Permission.scheduleExactAlarm.isGranted) { return true; } else { var status = await Permission.scheduleExactAlarm.request(); return status.isGranted; } } // ... 原有代码 ... }
步骤3:修改定时通知方法,先校验权限
Future scheduleNotification( {int id = 0, String? title, String? body, String? payLoad, required DateTime scheduledNotificationDateTime}) async { // 先检查权限 bool hasPermission = await requestExactAlarmPermission(); if (!hasPermission) { debugPrint("精确闹钟权限未授予,无法创建定时通知"); // 可选:引导用户到设置页面开启权限 // await openAppSettings(); return; } return notificationsPlugin.zonedSchedule( id, title, body, tz.TZDateTime.from( scheduledNotificationDateTime, tz.local, ), await notificationDetails(), androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime); }
额外优化建议
- 调整main函数初始化顺序,确保时区初始化完成后再初始化通知:
void main() async { WidgetsFlutterBinding.ensureInitialized(); tz.initializeTimeZones(); // 先初始化时区 await NotificationService().initNotification(); // 等待通知初始化完成 // ... 其他代码 ... }
- iOS平台需在
Info.plist中添加权限描述:
<key>NSAlertUsageDescription</key> <string>需要发送通知提醒您</string> <key>NSBadgeUsageDescription</key> <string>需要更新应用角标</string> <key>NSSoundUsageDescription</key> <string>需要播放通知声音</string>
内容的提问来源于stack exchange,提问作者Ahmed Raza
相关产品推荐
相关产品推荐

