使用场景
设置闹铃 发送心跳包
API
1.设置定时任务
功能说明: 设置一个在未来的某个时间运行应用的PendingIntent 或者OnAlarmListener ,即使设备已经进入睡眠(Cpu休眠)已设置的闹铃也会被保持,只有当设备关闭或是重启的时候会被清除
1.1.单次定时任务 (set)
void set(@AlarmType int type, long triggerAtMillis, PendingIntent operation)
void set(@AlarmType int type, long triggerAtMillis, String tag, OnAlarmListener listener, Handler targetHandler)
含义: 设置一个闹钟,这个闹钟设置在API 19以下是准确的,API 19及以上因为系统的优化(系统要批量处理这些闹钟以减少唤醒次数,减少电池的使用),不再准确。如果想在API 19及以上的版本依然准备需要使用 setWindow 或者 setExact 。
API翻译:
安排警报。
<b>注意:对于计时操作(滴答声、超时等),使用{@linkandroid.os.Handler}更容易、更高效。
如果已经为同一个IntentSender安排了一个警报,则之前的警报将首先被取消。
如果规定的触发时间是过去的,则会立即触发报警。
如果已经计划了此意图的警报(由{@link Intent#filterEquals}定义两个意图相等),则将删除该警报并替换为此警报。
报警是一种意图广播,发送到您在{@link android.content.Context#registerReceiver}注册的广播接收器,
或通过<;接收器(>);AndroidManifest中的标记。xml文件。
报警意图与类型为int的额外数据一起传递,该数据称为{@link Intent#EXTRA_ALARM_COUNT Intent.EXTRA_ALARM_COUNT} ,指示有多少过去的报警事件累积到此意图广播中。
由于手机处于睡眠状态而无法发送的重复报警在发送时的计数可能大于1。
<b>注:从API 19开始,传递给此方法的触发时间被视为不精确:
在此时间之前不会发出警报,但可能会推迟一段时间并在稍后发出。
操作系统将使用此策略在整个系统中“批量”报警,
将设备需要“唤醒”的次数降至最低,并将电池使用降至最低。
一般来说,只要计划在遥远的将来进行报警,则不会延迟计划在不久的将来进行的报警。
有了新的批处理策略,交货订单保证不如以前那么有力。
如果应用程序设置了多个警报,则这些警报的实际交付顺序可能与其请求的交付时间顺序不匹配。
如果您的应用程序有很强的排序需求,那么您可以使用其他API来获得必要的行为;
请参阅{@link #setWindow(int, long, long, PendingIntent)}和 {@link #setExact(int, long, PendingIntent)}.
{@code targetSdkVersion}在API 19之前的应用程序将继续获得以前的报警行为:所有计划的报警都将被视为精确的。
参数:
参数 @AlarmType int type
事件参照物,以及是否在休眠时唤起
public static final int RTC_WAKEUP = 0;
public static final int RTC = 1;
public static final int ELAPSED_REALTIME_WAKEUP = 2;
public static final int ELAPSED_REALTIME = 3;
参数 long triggerAtMillis
触发执行的时间
参数 PendingIntent operation
挂起的意图
测试代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent();
intent.setClass(this, AlarmActivity.class);
intent.setAction("这是set过来的intent");
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
alarmManager.cancel(pi);
int interval = 5 * 1000;
findViewById(R.id.btn_test_1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AppLogUtils.input(TAG, "onClick btn_test_1");
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + interval, pi);
}
});
****
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
AppLogUtils.input(TAG, "onNewIntent");
AppLogUtils.input(TAG, "onNewIntent.getAction == " + intent.getAction());
((TextView) findViewById(R.id.tv_content)).setText(intent.getAction());
}
最终成功调用到 onNewIntent(),此时设置 android:launchMode=“singleTask”
1.2.设置在时间段执行的定时任务(setWindow)
void setWindow(@AlarmType int type, long windowStartMillis, long windowLengthMillis,PendingIntent operation)
void setWindow(@AlarmType int type, long windowStartMillis, long windowLengthMillis,
String tag, OnAlarmListener listener, Handler targetHandler)
含义: 如果SDK版本在 Android 4.4 (Api 19)=< SDK < Android 6.0 (Api 23)这个区间,我们对闹钟的时序性要求较高,但是对及时性要求不高时,可以使用 setWindow 。
setWindow 不会让闹钟被系统批量处理(如set方法),而是按照设置的先后顺序处理(严格的排序保证),但是同时setWindow 的闹钟及时性不准确。
翻译API:
安排在给定时间窗口内发出警报。此方法类似于{@link#set(int,long,PendingIntent)},
但允许应用程序精确控制操作系统可能调整其交付的程度。
这种方法允许应用程序利用交付批处理产生的电池优化,即使它对警报的及时性要求不高。
此方法还可用于通过确保每个报警请求的窗口不相交,在多个报警之间实现严格的排序保证。
当不需要精确传递时,应用程序应该使用标准的{@link#set(int,long,PendingIntent)}方法。
这将为操作系统提供最大的灵活性,以最小化唤醒和电池使用。
对于必须在精确指定的时间发出且没有可接受的变化的报警,应用程序可以使用{@link#setExact(int,long,PendingIntent)}。
参数:
参数 long windowStartMillis
触发执行的时间段左边界
参数 long windowLengthMillis
时间段长度
测试代码:
alarmManager.setWindow(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + interval, interval, pi);
1.3.设置单次准确的定时任务(setExact 、setAlarmClock)
void setExact(@AlarmType int type, long triggerAtMillis, PendingIntent operation)
void setExact(@AlarmType int type, long triggerAtMillis, String tag,
OnAlarmListener listener, Handler targetHandler)
void setAlarmClock(AlarmClockInfo info, PendingIntent operation)
setExact 含义:
如果SDK版本在 Android 4.4 (Api 19)=< SDK < Android 6.0 (Api 23)这个区间,我们对闹钟的时序性要求较高,同时要求及时性要求也高时,可以使用 setExact 。
setExact 不会让闹钟被系统批量处理(如set方法),而是按照设置的先后顺序处理(严格的排序保证),同时setExact 的闹钟及时性准确。
翻译API:
安排在规定的时间准确发出警报。
此方法类似于{@link#set(int,long,PendingIntent)},但不允许操作系统调整传递时间。
警报将尽可能接近请求的触发时间。
<b>注意:</b>只有对准确时间交付有强烈需求的报警(如在请求的时间闹钟响)才应安排为准确。
强烈建议应用程序不要不必要地使用精确警报,因为它们会降低操作系统将电池使用降至最低的能力。
setAlarmClock 含义:
SDK版本在 大于 Android 4.4 (Api 19),都可以使用 setAlarmClock
指定闹钟事件AlarmManager.setAlarmClock()的事件会在闹钟结束前,令系统短暂的完全退出Doze模式,并且正常处理事件,系统为了突显该闹钟事件,将会在status bar上显示物理闹钟的icon。
翻译API:
安排一个代表闹钟的闹钟,该闹钟将用于在闹钟熄灭时通知用户。
我们的期望是,当该警报触发时,
该应用程序将进一步唤醒设备,告诉用户有关警报的信息——打开屏幕、播放声音、振动等。
因此,如果合适,系统通常还会使用此处提供的信息告知用户即将发生的警报。
由于这种报警的性质类似于{@link#setExactAndAllowHileidle},
即使系统处于低功率闲置(又称打盹)模式,也允许触发这些警报。当系统看到出现此类警报时,也可能会进行一些准备工作,
为了减少在导致设备完全唤醒时可能发生的后台工作量,这是为了避免出现大量设备在早上的同一时间设置了警报的情况,
所有人都在那个时候醒来,突然间,网络上充斥着悬而未决的背景工作。
因此,这些类型的报警器在电池使用上可能非常昂贵,并且只能用于其预期用途。
此方法类似于{@link#setExact(int,long,PendingIntent)},但暗指{@link#RTC_WAKEUP}。
1.4.设置在低功耗条件下也执行的定时任务 (setAndAllowWhileIdle、setExactAndAllowWhileIdle)
Android 6.0 (Api 23)及以上,系统新增低功耗空闲(又称doze)模式, 这种模式下setExact 和 setWindow 方法失效,因为不能唤醒系统,除此模式以外的场景,依然是准确的。
如果想打破这种限制,可以唤醒系统,需要使用 setAndAllowWhileIdle 或者 setExactAndAllowWhileIdle。
setAndAllowWhileIdle 含义:
setAndAllowWhileIdle 设置的警报可以被批量处理,低功耗空闲(又称doze)模式下,准确度更低。
翻译API:
与{@link#set(int,long,PendingIntent)}类似,但即使系统处于低功耗空闲(又称doze)模式,也允许执行此警报。
这种类型的警报必须仅用于实际需要在空闲时发出警报的情况——一个合理的例子是日历通知,它应该发出声音,以便用户知道。
当警报发出时,该应用程序还将被添加到系统的临时白名单中约10秒,以允许该应用程序获取进一步的唤醒锁,从而完成其工作。
当设备闲置时,这些警报可能会严重影响设备的电源使用(从而导致调度警报的应用程序严重的电池故障),因此应谨慎使用。
为了减少滥用,对特定应用程序发出警报的频率有限制。
在正常系统运行情况下,其发出这些警报的时间不会超过大约每分钟一次(此时发出所有此类待处理警报);
在低功率怠速模式下,此持续时间可能会明显更长,例如15分钟。
与其他警报不同,该系统可以自由地重新安排此类警报与任何其他警报(甚至来自同一应用程序的警报)无序发生。
当设备空闲时,这显然会发生(因为此警报可以在空闲时熄灭,当应用程序的任何其他警报将保持到稍后),但即使在不空闲时也可能发生。
无论应用程序的目标SDK版本如何,此调用始终允许成批处理警报。
setExactAndAllowWhileIdle含义:
setExactAndAllowWhileIdle 也可以唤醒系统,和 setAndAllowWhileIdle 对比准确度更高,不会被系统批量处理。
翻译API:
与{@link#setExact(int,long,PendingIntent)}类似,但即使系统处于低功耗空闲模式,也允许执行此警报。
如果不需要精确的警报调度,但仍需要在空闲时执行,请考虑使用{@link#setAndAllowWhileIdle}。
这种类型的警报必须仅用于实际需要在空闲时发出警报的情况——一个合理的例子是日历通知,它应该发出声音,以便用户知道。
当警报发出时,该应用程序还将被添加到系统的临时白名单中约10秒,以允许该应用程序获取进一步的唤醒锁,从而完成其工作。
当设备闲置时,这些警报可能会严重影响设备的电源使用(从而导致调度警报的应用程序严重的电池故障),因此应谨慎使用。
为了减少滥用,对特定应用程序发出警报的频率有限制。
在正常系统运行情况下,其发出这些警报的时间不会超过大约每分钟一次(此时发出所有此类待处理警报);
在低功率怠速模式下,此持续时间可能会明显更长,例如15分钟。
与其他警报不同,该系统可以自由地重新安排此类警报与任何其他警报(甚至来自同一应用程序的警报)无序发生。
当设备空闲时,这显然会发生(因为此警报可以在空闲时熄灭,当应用程序的任何其他警报将保持到稍后),但即使在不空闲时也可能发生。
请注意,由于应用程序选择了这种行为,因此操作系统将允许自己比常规的精确报警更灵活地安排这些报警。
当设备空闲时,为了优化电池寿命,可能需要更多的时间安排。
1.5.设置循环的定时任务(setRepeating、setInexactRepeating)
void setRepeating(@AlarmType int type, long triggerAtMillis,
long intervalMillis, PendingIntent operation)
void setInexactRepeating(@AlarmType int type, long triggerAtMillis,
long intervalMillis, PendingIntent operation)
setRepeating、setInexactRepeating()方法用于Android 4.4(Api 19)以下,大于19的版本可以使用变通的方案:setExactAndAllowWhileIdle + pendintent.getBroadcast
1.6.设置定时任务的方法如何选择?
如果你期望每次都是按照你的设想响应定时任务:
小于 API 19 : set、setRepeating、setInexactRepeating
大于等于 API 19 小于 API 23: setWindow、setExact 、setAlarmClock
大于 API 23: 如果想要在低功耗空闲(又称doze)模式下使用 setAndAllowWhileIdle、setExactAndAllowWhileIdle、setAlarmClock
但是这样会更影响电池的使用时长,非必要可以不这么选择。
1.7.系统为我们做了版本兼容的封装
https://developer.android.google.cn/reference/androidx/core/app/AlarmManagerCompat
public final class AlarmManagerCompat {
public static void setAlarmClock(@NonNull AlarmManager alarmManager, long triggerTime,
@NonNull PendingIntent showIntent, @NonNull PendingIntent operation) {
if (Build.VERSION.SDK_INT >= 21) {
alarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(triggerTime, showIntent),
operation);
} else {
AlarmManagerCompat.setExact(alarmManager, AlarmManager.RTC_WAKEUP, triggerTime,
operation);
}
}
public static void setAndAllowWhileIdle(@NonNull AlarmManager alarmManager, int type,
long triggerAtMillis, @NonNull PendingIntent operation) {
if (Build.VERSION.SDK_INT >= 23) {
alarmManager.setAndAllowWhileIdle(type, triggerAtMillis, operation);
} else {
alarmManager.set(type, triggerAtMillis, operation);
}
}
public static void setExact(@NonNull AlarmManager alarmManager, int type, long triggerAtMillis,
@NonNull PendingIntent operation) {
if (Build.VERSION.SDK_INT >= 19) {
alarmManager.setExact(type, triggerAtMillis, operation);
} else {
alarmManager.set(type, triggerAtMillis, operation);
}
}
public static void setExactAndAllowWhileIdle(@NonNull AlarmManager alarmManager, int type,
long triggerAtMillis, @NonNull PendingIntent operation) {
if (Build.VERSION.SDK_INT >= 23) {
alarmManager.setExactAndAllowWhileIdle(type, triggerAtMillis, operation);
} else {
AlarmManagerCompat.setExact(alarmManager, type, triggerAtMillis, operation);
}
}
private AlarmManagerCompat() {
}
}
2.剩余
2.1.取消闹钟设置
cancel
2.2.获取下次闹钟
getNextAlarmClock
2.3.设置系统时间
setTime
2.4.设置系统时间时区
setTimeZone
版本变更记录
版本4.4(19)变更说明:https://developer.android.google.cn/about/versions/android-4.4
如果您的应用使用 AlarmManager… 将您的应用的 targetSdkVersion 设置为“19”或更高版本时,您使用 set() 或 setRepeating() 创建的闹铃将变得不准确。 为提高电源效率,Android 现在批处理在合理的相似时间发生的所有应用的闹铃,以便系统仅唤醒设备一次,而不是多次唤醒设备来处理每个闹铃。 如果您的闹铃没有与精确的时钟时间关联,但您的闹铃仍必须在特定时间范围(例如,在下午 2 点至 4 点之间)触发,那么您可以使用新的 setWindow() 方法,其接受闹铃的“最早”时间以及最早时间之后的一个时间“窗口”,在这个窗口内,系统应触发闹铃。 如果您的闹铃必须固定到一个精确的时钟时间(例如,日历事件提醒),那么您可以使用新的 setExact() 方法。 这个精确的批处理行为仅适用于更新后的应用。如果您已将 targetSdkVersion 设置为“18”或更低版本,那么在 Android 4.4 上运行时,您的闹铃的行为方式和在以前版本上一样。
Android 6.0 针对低电耗模式和应用待机模式进行优化:https://developer.android.google.cn/training/monitoring-device-state/doze-standby
在低电耗模式下,您的应用会受到以下限制: 标准 AlarmManager 闹钟(包括 setExact() 和 setWindow())推迟到下一个维护期。 如果您需要设置在设备处于低电耗模式时触发的闹钟,请使用 setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle()。 使用 setAlarmClock() 设置的闹钟将继续正常触发,系统会在这些闹钟触发之前不久退出低电耗模式。
*使应用适应低电耗模式 低电耗模式可能会对应用产生不同的影响,具体取决于应用提供的功能和使用的服务。许多应用无需修改即可在低电耗模式周期内正常运行。在某些情况下,您必须优化应用管理网络、闹钟、作业和同步的方式。应用应该能够在每个维护期内高效地管理活动。 低电耗模式尤其可能会影响 AlarmManager 闹钟和定时器管理的活动,因为当系统处于低电耗模式时,不会触发 Android 5.1(API 级别 22)或更低版本中的闹钟。 为了帮助安排闹钟,Android 6.0(API 级别 23)引入了两种新的 AlarmManager 方法:setAndAllowWhileIdle() 和 setExactAndAllowWhileIdle()。通过这些方法,您可以设置即使设备处于低电耗模式也会触发的闹钟。 注意:setAndAllowWhileIdle() 及 setExactAndAllowWhileIdle() 为每个应用触发闹钟的频率都不能超过每 9 分钟一次。
参考地址
AlarmManager 定时任务详解:https://blog.csdn.net/kingyc123456789/article/details/107179126
AlarmManager(系统服务之定时服务):https://blog.csdn.net/wuto_/article/details/110494026
Android后台调度任务与省电:https://www.ktanx.com/blog/p/4827
|