关于闹钟的AlarmManager的type选择??到底该用哪个啊?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于闹钟的AlarmManager的type选择??到底该用哪个啊?相关的知识,希望对你有一定的参考价值。

看到别人很多帖子说AlarmManager 说到:setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi);其中的第一个参数type有3种,很多帖子都说:AlarmManager.POWER_OFF_WAKEUP:"表示闹钟在手机关机状态下也能正常进行提示功能,所以是5个状态中用的最多的状态之一,该状态下闹钟也是用绝对时间,状态值为4;不过本状态好像受SDK版本影响,某些版本并不支持;"但是看很多例子或者Demo很多都用:AlarmManager.RTC_WAKEUP :表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,状态值为0;请问兄弟们,做一个 闹钟 或 者日程提醒的应用 到底该用哪个啊??在线等回答.........!

    如你所述,如果不是设置关机闹钟(即手机关机下,闹钟到时间会开机响应),就用AlarmManager.RTC_WAKEUP ;要是设置关机闹钟,就要用AlarmManager.RTC_POWEROFF_WAKEUP,我记得这个值好像是5.

    但根据你的需求,我觉得用AlarmManager.RTC_WAKEUP即可

参考技术A 同问AlarmManager alarmManager = (AlarmManager) this .getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(UserAlarmActivity.this, AlarmReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast( UserAlarmActivity.this, 0, intent, 0); Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(System.currentTimeMillis()); cal.set(Calendar.HOUR_OF_DAY, hour); cal.set(Calendar.MINUTE, minute); alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);触发不了广播,求解 参考技术B 顶,不错的帖子,支持楼主

AlarmManager set 设置定时闹钟,延时执行的问题

背景:使用 AlarmManager 给系统设置定时关机,延时了1个多小时的才执行的问题

接到问题后,首先排查了代码,看到代码使用的是 Android 自带的 AlarmManager 设置一个服务的 PendingIntent,当时间到了,则执行关机程序。代码如下:

    /**
     * 设置定时关机
     * @param time 多少ms后关机
     */
    fun shutDownSystem(time: Long) {
        val intent = Intent(WebConfigApi.context,ShutdownService::class.java)
        val pendingIntent = PendingIntent.getService(
            context, 0, intent,
            PendingIntent.FLAG_UPDATE_CURRENT
        )
        if (time <= 0) {
            alarm.cancel(pendingIntent)
        } else {
            alarm.set(AlarmManager.RTC_WAKEUP, time, pendingIntent)
        }

    }

从代码逻辑看,没啥问题。
一开始怀疑是客户设置了 ntp 服务,导致系统时间延时引起,但 ntp 只是为了校准时间,问了客户时间也是正常的。
从日志看,也不是必现的,所以写了一个定时开关机的脚本去压测,每次开机后对当前时间+5分钟,做定时开关机压测,测试了两天,都能开机关机。

从这里反应,程序应该是没问题,而且出货之前也测试过这块内容。

但从客户日志来,有一个跟脚本和测试明显的不同的区分,就是客户设置定时关机的跨度比较大,且设完一段时间未使用设备。

所以找了几个盒子,进行煲机,确实复现到了

但为啥时间跨度大,未使用设备就会出现?
说明软件程序确实有问题,跟踪进去,发现 set 方法,在 API 19,使用这个方法传递的时间视为不准确,系统为了减少电池消耗,可能会把这个 set 推迟,然后批量发送;

从这里可以看到,确实是set 这个方法引起的

所以,从源码出发,发现 setExact 这个方法,该方法指定系统在规定时间内发出,不允许系统调整交付时间。

修改后,问题解决。

思考:set 方法有问题,那可能标志位也有问题。可以发现 RTC_WAKEUP 标识使用的是 系统时间,也就是 System.currentTimeMillis(),这样设置的时间,容易被人修改;所以采用 ELAPSED_REALTIME_WAKEUP 这个标志位,它根据系统开机时间来计算,也就是 SystemClock.elapsedRealtime()。
所以,代码这里,关机的时间也需要改一下,从开机时间+设置的时间即可,如下:

    /**
     * 设置定时关机
     * @param time 多少ms后关机
     */
    fun shutDownSystem(time: Long) {
        val elapsedTime = SystemClock.elapsedRealtime()
        //开机时间 + 延时时间
        val alarmTime = elapsedTime + time
        val intent = Intent(
            WebConfigApi.context,
            ShutdownService::class.java
        )
        val pendingIntent = PendingIntent.getService(
            context, 0, intent,
            PendingIntent.FLAG_UPDATE_CURRENT
        )
        if (alarmTime <= 0) {
            alarm.cancel(pendingIntent)
            isDelayShutdown = false
        } else {
            //ELAPSED_REALTIME_WAKEUP 自开机其开始算时间,RTC_WAKEUP 则是根据系统时间有关
              //  alarm.setExact()
            alarm.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, pendingIntent)
        }

    }

以上是关于关于闹钟的AlarmManager的type选择??到底该用哪个啊?的主要内容,如果未能解决你的问题,请参考以下文章

Android闹钟 AlarmManager的使用

Android,如何取消闹钟? alarmManager.cancel 不工作

AlarmManager的使用 2019-03-25

AlarmManager定时闹钟

闹钟--alarmManager

AlarmManager手机闹钟简介