Android12版本闹钟服务崩溃问题

文章讲述了项目app因未适配Android14及以上版本的新权限而引发崩溃,重点在于`SCHEDULE_EXACT_ALARM`和`USE_EXACT_ALARM`权限的使用,以及如何通过代码调整闹钟设置以避免SecurityException。推荐使用权限申请框架如getActivity/XXPermissions来处理权限问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目app线上出现的崩溃记录问题,崩溃日志如下所示:

Caused by java.lang.SecurityException: Caller com.health.trackeranz needs to hold android.permission.SCHEDULE_EXACT_ALARM or android.permission.USE_EXACT_ALARM to set exact alarms.

一看到是安全异常,估计就是高版本android系统加的限制了,原因就是没正确适配新权限导致的崩溃问题

先贴下已解决的代码:

//在第二天的0:00清理发出清理数据的广播
val calendar: Calendar = Calendar.getInstance()
calendar.set(Calendar.HOUR_OF_DAY, 0)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
calendar.add(Calendar.DAY_OF_MONTH, 1)

//测试用的数据,闹钟定为60s后
//val calendar: Calendar = Calendar.getInstance()
//calendar.add(Calendar.SECOND, 60)

val alarmManager = application.getSystemService<AlarmManager>()

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && alarmManager?.canScheduleExactAlarms()==false) {
	alarmManager.setExactAndAllowWhileIdle(
		AlarmManager.RTC_WAKEUP,
		calendar.getTimeInMillis(),
		pendingIntent
	)
} else {
	alarmManager?.setExact(
		AlarmManager.RTC_WAKEUP,
		calendar.getTimeInMillis(),
		pendingIntent
	)
}
LogUtils.d("闹钟已启动,预定触发时间:" + TimeUtils.date2String(calendar.time))

这里代码注意alarmManager?.canScheduleExactAlarms()==false这个判断,之前没有添加次判断,于是就有了上文提及的崩溃问题

复现的话很容易,去设置页面里,把应用的闹钟服务关闭就会出现了,如下图所示

原因

首先,了解下alarmManager设置定时的3个方法:

  • setExactAndAllowWhileIdle(long triggerAtMillis, PendingIntent operation):这个方法用于设置精确的闹钟,即你可以指定闹钟触发的特定时间。它会在设备进入低功耗模式时仍然触发闹钟。但是,如果你的应用程序在后台运行并且设备处于省电模式,则可能不会触发闹钟。
  • setExact(long triggerAtMillis, PendingIntent operation):这个方法也用于设置精确的闹钟,与 setExactAndAllowWhileIdle 方法类似,允许你指定特定的触发时间。但是,它不会在设备处于低功耗模式时触发闹钟。如果你的应用程序在后台运行并且设备处于省电模式,则闹钟可能会被延迟执行。
  • setAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation):这个方法允许你设置具有弹性的触发时间的闹钟,以适应设备的省电模式。它提供了三种可能的触发类型:ELAPSED_REALTIME_WAKEUPRTC_WAKEUP 或 RTC。它会在设备处于低功耗模式时仍然触发闹钟。

需要注意的是,如果 targetSdkVersion >= 33,且在 Android14 设备上没有显式申请该权限,调用上面的3个方法,则会抛出一个 SecurityException 异常

不过Android13新增android.permission.USE_EXACT_ALARM,用了模拟机的Android13版本测试,如果不写android.permission.USE_EXACT_ALARM还是会出现上面的错误

所以最终做法,就是2个权限android.permission.SCHEDULE_EXACT_ALARMandroid.permission.USE_EXACT_ALARM都申请才不会有问题,这里推荐权限申请框架可以使用getActivity/XXPermissions: Android 权限请求框架,已适配 Android 14这个开源库

应该是setExact方法的限制稍微松一些吧,上面的方法可以使用,不过实际没有太高精度要求,只使用setExact应该也能达到效果

像上述的app,只是在第二日凌晨进行通知栏的数据更新(类似每日提醒那种感觉)

至于保活方面,高版本的Android限制太多,产品也没有其他要求,就先这样,只要app后台没被杀死,每日通知还是有的

不过看了其他文章,说到:

日历或闹钟应用需要在应用停止运行时发送日历提醒、唤醒闹钟或提醒。这些应用可以请求 USE_EXACT_ALARM 常规权限。系统将在安装时授予 USE_EXACT_ALARM 权限,拥有此权限的应用将能够像具有 SCHEDULE_EXACT_ALARM 权限的应用一样设置精确闹钟。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值