前言
我们在应用开发的过程中常常需要使用定时操作,如果是短时间的比如几秒,几分的,我们可以使用的方法就有很多了,比如Thread,Timer,Handler等等,可是如果是闹钟应用呢,需要在几小时甚至几天以后进行操作,那前面提到的方法就不适用了,这种时候我们需要使用系统服务AlarmManager来实现了。
使用
创建AlarmManager
和使用其他系统服务一样:
AlarmManager mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
闹钟类型
- AlarmManager.ELAPSED_REALTIME 休眠状态下不可用,使用相对开机时间
- AlarmManager.ELAPSED_REALTIME_WAKEUP 休眠状态可用,使用相对开机时间
- AlarmManager.RTC 休眠状态下不可用,使用绝对时间
- AlarmManager.RTC_WAKEUP 休眠状态下可用,使用绝对时间
休眠状态:屏幕不亮(按下电源键)
相对开机时间:手机开机到现在的时间(手机关于里面的已开机时间)
绝对时间:手机的时间(手机的当前时间)
测试结果:如果使用休眠状态不可用的类型,当闹钟时间到的时候,不会执行操作,会一直延迟,直到手机屏幕点亮(解除休眠状态)的一瞬间发出。非定时闹钟事件发出的最短间隔为5秒(小米 Android6.0测试)
上文中一直提到了相对时间,如何相对当前时间?举个栗子
Intent intent = new Intent(); intent.putExtra("extras", "hello"); intent.setAction("action"); PendingIntent broadcast = PendingIntent.getBroadcast(this, 11, intent, 0); // 最低间隔5秒 mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 5000, broadcast);
我们可以使用SystemClock.elapsedRealtime()获取到系统的开机时间,然后在这个基础上加上我们需要的时间即可。
常用方法
设置一次性闹钟
方法一
int type 闹钟类型 long triggerAtTime 触发时间(毫秒为单位) PendingIntent operation 触发的动作 mAlarmManager.set(int type, long triggerAtTime, PendingIntent operation)
方法二:参数含义与方法一相同,不过在targetSdkVersion >= 19时推荐使用方法二,原因在下文提到
setExact(int type, long triggerAtMillis, PendingIntent operation)
设置重复闹钟
方法一
int type 闹钟类型 long triggerAtTime 触发时间(毫秒为单位) PendingIntent operation 触发的动作 long intervalMillis 两次触发的间隔(毫秒为单位) setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
方法二:参数含义与方法一相同,不过在targetSdkVersion >= 19时推荐使用方法二,原因在下文提到
setRepeating(int type, long triggerAtMillis,long intervalMillis, PendingIntent operation)
重复闹钟有一个最短发出时间间隔,在小米3 Android6.0上测试为1分钟,根据官方文档,可被精确识别的常量如下
/** * Available inexact recurrence intervals recognized by */ public static final long INTERVAL_FIFTEEN_MINUTES = 15 * 60 * 1000; public static final long INTERVAL_HALF_HOUR = 2*INTERVAL_FIFTEEN_MINUTES; public static final long INTERVAL_HOUR = 2*INTERVAL_HALF_HOUR; public static final long INTERVAL_HALF_DAY = 12*INTERVAL_HOUR; public static final long INTERVAL_DAY = 2*INTERVAL_HALF_DAY;
为什么在在targetSdkVersion >= 19时推荐使用方法二?
根据官方文档:系统为了省电,在targetSdkVersion >= 19时,使用方法一可能将几个间隔时间差不多的闹钟事件和为一个发出。
取消重复闹钟
取消重复闹钟只需要调用如下方法,传入的参数为匹配的PendingIntent。
public void cancel(PendingIntent operation)
PendingIntent的匹配规则
PendingIntent的匹配规则为:如果两个PendingIntent它们内部的Intent相同并且requestCode也相同,那么这两个PendingIntent就是匹配的,requestCode比较好理解,Intent的匹配规则是:如果两个Intent的ComponentName和Intent-filter都相同,那么这两个Intent也就是相同的,需要注意的是,Extras不参与Intent是否匹配的比较。
参考链接:许宏川的简书、editor1994的博客