从 Android 6.0(API 级别 23)开始,Android 引入了两项省电功能,通过管理应用在设备未连接至电源时的行为方式,帮助用户延长电池寿命。当用户长时间未使用设备时,低电耗模式会延迟应用的后台 CPU 和网络活动,从而降低耗电量。应用待机模式会延迟用户近期未与之交互的应用的后台网络活动。
在低电耗模式下,标准 AlarmManager 闹钟(包括 setExact() 和 setWindow())推迟到下一个维护期。
如果您需要设置在设备处于低电耗模式时触发的闹钟,请使用 setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle()。
使用 setAlarmClock() 设置的闹钟将继续正常触发,系统会在这些闹钟触发之前不久退出低电耗模式。
这里我们来对比下setExact() 、 setWindow()、setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle()
下面是Google官方对这几个接口的解释,参考https://developer.android.com/reference/android/app/AlarmManager
setExact
安排在规定的时间准确发送警报。
该方法类似于 set(int, long, android.app.PendingIntent),但不允许操作系统调整传递时间。警报将尽可能接近请求的触发时间。
注意:只有对准确时间交付有强烈需求的警报(例如在请求的时间响起的闹钟)才应该被安排为准确的。强烈建议应用程序不要使用不必要的精确警报,因为它们会降低操作系统最大限度地减少电池使用的能力。
setWindow
安排在给定的时间窗口内发送警报。此方法类似于 set(int, long, android.app.PendingIntent),但允许应用程序精确控制操作系统可能对其传递进行调整的程度。这种方法允许应用程序利用由交付批处理产生的电池优化,即使它对其警报有适度的及时性要求。
注意:从 API Build.VERSION_CODES#S 开始,应用程序不应在少于 10 分钟的窗口内通过。如果警报应该在不久的将来触发,系统将尽最大努力适应较小的窗口,但不能保证,应用程序应该期望任何小于 10 分钟的窗口被拉长到 10 分钟。
该方法还可用于通过确保为每个警报请求的窗口不相交来实现多个警报之间的严格排序保证。
当不需要精确传递时,应用程序应该使用标准的 set(int, long, android.app.PendingIntent) 方法。这将为操作系统提供最大的灵活性,以最大限度地减少唤醒和电池使用。对于必须在精确指定的时间发送且没有可接受的变化的警报,应用程序可以使用 setExact(int, long, android.app.PendingIntent)。
setAndAllowWhileIdle
与 set(int, long, android.app.PendingIntent) 类似,但即使系统处于低功耗空闲(又名打瞌睡)模式,也允许执行此警报。这种类型的警报只能用于实际上需要在空闲时警报响起的情况——一个合理的例子是日历通知应该发出声音以便用户意识到它。当警报发出时,该应用程序还将被添加到系统的临时电源豁免列表中大约 10 秒,以允许该应用程序获取更多唤醒锁以完成其工作。
这些警报在空闲时会显着影响设备的电源使用(从而导致应用程序对其进行调度),因此应谨慎使用它们。为了减少滥用,对特定应用程序的这些警报的触发频率有限制。在正常的系统操作下,它不会超过大约每分钟发送这些警报(此时会发送每个此类未决警报);当处于低功耗空闲模式时,此持续时间可能会明显更长,例如 15 分钟。
与其他警报不同,系统可以自由地重新安排此类警报,使其与任何其他警报(甚至来自同一应用程序的警报)无序发生。这显然会在设备空闲时发生(因为此警报可能会在空闲时响起,当应用程序的任何其他警报将被保留到稍后时),但即使在不空闲时也可能发生。
无论应用程序的目标 SDK 版本如何,此调用始终允许批量处理警报。
setExactAndAllowWhileIdle
与 setExact(int, long, android.app.PendingIntent) 类似,但即使系统处于低功耗空闲模式,也允许执行此警报。如果您不需要精确的闹钟调度但仍需要在空闲时执行,请考虑使用 setAndAllowWhileIdle(int, long, PendingIntent)。这种类型的警报只能用于实际上需要在空闲时警报响起的情况——一个合理的例子是日历通知应该发出声音以便用户意识到它。当警报发出时,该应用程序还将被添加到系统的临时电源豁免列表中大约 10 秒,以允许该应用程序获取更多唤醒锁以完成其工作。
这些警报在空闲时会显着影响设备的电源使用(从而导致应用程序对其进行调度),因此应谨慎使用它们。为了减少滥用,对特定应用程序的这些警报的触发频率有限制。在正常的系统操作下,它不会超过大约每分钟发送这些警报(此时会发送每个此类未决警报);当处于低功耗空闲模式时,此持续时间可能会明显更长,例如 15 分钟。
与其他警报不同,系统可以自由地重新安排此类警报,使其与任何其他警报(甚至来自同一应用程序的警报)无序发生。这显然会在设备空闲时发生(因为此警报可能会在空闲时响起,当应用程序的任何其他警报将被保留到稍后时),但即使在不空闲时也可能发生。请注意,与常规的精确警报相比,操作系统将允许自己更灵活地安排这些警报,因为应用程序已选择采用此行为。当设备空闲时,它可能需要更多的调度自由,以优化电池寿命。
总结下差异:setExact和setWindow不支持低功耗空闲(又名打瞌睡)模式;
setAndAllowWhileIdle和setExactAndAllowWhileIdle支持低功耗空闲(又名打瞌睡)模式;
相对于setWindow和setAndAllowWhileIdle,setExact和setExactAndAllowWhileIdle是精确的闹钟调度。
如下分别写了4个闹钟
package com.kxf.alarmmanagertest
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Sys