You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 14应用更新后AlarmManager权限(SCHEDULE_EXACT_ALARM)异常求助

修复Android 14下BootCompletedReceiver中AlarmManager.setExact的SecurityException问题

问题核心

升级到Android 14后,在BootCompletedReceiver.onReceive中调用AlarmManager.setExact触发SecurityException,异常明确提示:Caller com.eup.faztaa needs to hold android.permission.SCHEDULE_EXACT_ALARM or android.permission.USE_EXACT_ALARM to set exact alarms。这是因为Android 14对精确闹钟的权限管控进一步收紧。

异常信息

Exception : java.lang.SecurityException Remote stack trace
  at com.android.server.alarm.AlarmManagerService$5.set (AlarmManagerService.java:3240)
  at android.app.IAlarmManager$Stub.onTransact (IAlarmManager.java:262)
  at android.os.Binder.execTransactInternal (Binder.java:1405)
  at android.os.Binder.execTransact (Binder.java:1341)
Caused by java.lang.SecurityException: Caller com.eup.faztaa needs to hold android.permission.SCHEDULE_EXACT_ALARM or android.permission.USE_EXACT_ALARM to set exact alarms.
  at android.os.Parcel.createExceptionOrNull (Parcel.java:3071)
  at android.os.Parcel.createException (Parcel.java:3055)
  at android.os.Parcel.readException (Parcel.java:3038)
  at android.os.Parcel.readException (Parcel.java:2980)
  at android.app.IAlarmManager$Stub$Proxy.set (IAlarmManager.java:487)
  at android.app.AlarmManager.setImpl (AlarmManager.java:1110)
  at android.app.AlarmManager.setImpl (AlarmManager.java:1070)
  at android.app.AlarmManager.setExact (AlarmManager.java:834)
  at com.eup.faztaa.receiver.BootCompletedReceiver.onReceive
  at android.app.ActivityThread.handleReceiver (ActivityThread.java:4975)
Caused by android.os.RemoteException: Remote stack trace:
  at com.android.server.alarm.AlarmManagerService$5.set (AlarmManagerService.java:3240)
  at android.app.IAlarmManager$Stub.onTransact (IAlarmManager.java:262)
  at android.os.Binder.execTransactInternal (Binder.java:1405)
  at android.os.Binder.execTransact (Binder.java:1341)

修复方案

1. 声明权限(二选一)

在AndroidManifest.xml中添加对应权限:

  • 大部分普通应用使用SCHEDULE_EXACT_ALARM(需要用户手动授权):
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
  • 仅闹钟、日历等核心时间类应用可申请USE_EXACT_ALARM(需Google Play审核通过):
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />

2. 检查并请求用户授权(针对SCHEDULE_EXACT_ALARM)

由于SCHEDULE_EXACT_ALARM是特殊权限,无法通过常规权限请求弹窗获取,需跳转到系统设置让用户开启:

// 在需要设置精确闹钟的地方先检查权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    if (!alarmManager.canScheduleExactAlarms()) {
        // 跳转到系统设置开启权限
        Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
        intent.setData(Uri.parse("package:" + getPackageName()));
        // 若在Receiver中调用,需添加FLAG_ACTIVITY_NEW_TASK
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        return;
    }
}
// 权限已开启,正常设置精确闹钟
alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);

3. 替代方案:使用非精确闹钟(无需权限)

如果业务场景不需要毫秒级精确触发,建议改用非精确闹钟API,Android 14无需额外权限即可使用:

// 使用setAndAllowWhileIdle(低电量时也能触发,非精确)
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);

// 或者使用重复非精确闹钟
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmManager.INTERVAL_DAY, pendingIntent);

4. BootCompletedReceiver适配

在BootCompletedReceiver.onReceive中,先判断Android版本并检查权限,再执行闹钟设置逻辑,避免崩溃:

@Override
public void onReceive(Context context, Intent intent) {
    if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            if (!alarmManager.canScheduleExactAlarms()) {
                Log.w("BootReceiver", "精确闹钟权限未授予,无法设置闹钟");
                return;
            }
        }
        // 权限校验通过,设置闹钟
        setExactAlarm(context);
    }
}

private void setExactAlarm(Context context) {
    long triggerAtMillis = System.currentTimeMillis() + 1000 * 60; // 1分钟后触发
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, 
            new Intent(context, YourAlarmReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
}

内容的提问来源于stack exchange,提问作者Minh Tiến Đào

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:52:06