• Android12版本闹钟服务崩溃问题


    本文为作者原创,允许转载,不过请在文章开头明显处注明链接和出处!!! 谢谢配合~
    作者:stars-one
    链接:https://www.cnblogs.com/stars-one/p/17808026.html

    本篇大约有2728个字,阅读预计需要3.41分钟


    原文地址: Android12版本闹钟服务崩溃问题 - Stars-One的杂货小窝

    公司项目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()
    
    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_WAKEUPRTC。它会在设备处于低功耗模式时仍然触发闹钟。

    需要注意的是,如果 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 权限的应用一样设置精确闹钟。

    参考

  • 相关阅读:
    adb 命令速查(下)
    java基于SpringBoot+Vue的学生选课作业系统 element
    零号培训平台课程-1、SQL注入基础
    Mysql 45讲学习笔记(二十五)MYSQL保证高可用
    .NET 8 Video教程介绍(开篇)
    SPA项目之主页面--Mock.js以及组件通信(总线)的运用
    浅谈产业园区规划的意义、分类及功能!
    mysql数据库开放对外访问
    数据分析 | Pandas 200道练习题 进阶篇(3)
    数字图像处理笔记(二)图像增强-直方图修改技术
  • 原文地址:https://www.cnblogs.com/stars-one/p/17808026.html