Flutter使用flutter_local_notifications遇精确闹钟权限报错问题
解决Flutter Local Notifications精确闹钟权限异常问题
错误原因
你遇到的PlatformException(exact_alarms_not_permitted)是因为Android 12(API 31)及以上版本对精确闹钟做了权限限制:当使用AndroidScheduleMode.exactAllowWhileIdle这类精确调度模式时,必须提前申请SCHEDULE_EXACT_ALARM权限,否则系统会拒绝调度请求并抛出异常,导致应用冻结。
解决步骤
1. 添加静态权限到AndroidManifest.xml
打开android/app/src/main/AndroidManifest.xml,在<manifest>标签内添加权限声明:
<!-- Android 12+ 精确闹钟权限 --> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> <!-- Android 14+ 新增的精确闹钟权限 --> <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
2. 动态请求权限
使用permission_handler包动态向用户申请权限(需先在pubspec.yaml添加依赖):
dependencies: flutter_local_notifications: ^16.1.0 permission_handler: ^11.0.1
修改你的通知调度代码,先检查并请求权限:
import 'package:permission_handler/permission_handler.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'dart:math' as math; int id = 0; final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); Future<void> repeatNotification() async { // 请求精确闹钟权限 final permissionStatus = await Permission.scheduleExactAlarm.request(); if (!permissionStatus.isGranted) { print("精确闹钟权限被拒绝,无法调度通知"); return; } const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'repeating_channel_id', '每日签到通知', channelDescription: '用于发送每日签到提醒的通知渠道', importance: Importance.high, priority: Priority.high, ); const NotificationDetails notificationDetails = NotificationDetails(android: androidDetails); // 随机问候语和签到消息逻辑 final List<String> greetings = [ "Hi!", "Hey there!", "Hello!", "Hi there!", "What's up?", "Howdy!" ]; final List<String> checkInMessages = [ "It's time for your daily check in.", "Don't forget to check in today.", "Remember to take a moment to check in.", "How are you doing today?", "Time for your daily mindfulness moment.", "Can we chat?", "Let's talk!", ]; final rng = math.Random(); final randomGreeting = greetings[rng.nextInt(greetings.length)]; final randomCheckInMsg = checkInMessages[rng.nextInt(checkInMessages.length)]; // 捕获异常避免应用冻结 try { await flutterLocalNotificationsPlugin.periodicallyShow( id++, randomGreeting, randomCheckInMsg, RepeatInterval.daily, // 改为每日重复,符合你的需求 notificationDetails, androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, ); } catch (e) { print("调度通知失败:$e"); } }
3. 可选:调整调度模式(如果不需要严格精确)
如果你的每日通知不需要精确到分秒,可以改用非精确调度模式,避免权限申请:
await flutterLocalNotificationsPlugin.periodicallyShow( id++, randomGreeting, randomCheckInMsg, RepeatInterval.daily, notificationDetails, // 改用非精确模式,无需申请权限 androidScheduleMode: AndroidScheduleMode.inexactAllowWhileIdle, );
内容的提问来源于stack exchange,提问作者Jerry Yao
相关产品推荐
相关产品推荐

