摘要:目前android 中实现倒计时功能的几种方式:Timer,handler+xxx,AlarmManager 。前俩种的实现方式在系统休眠状态下也会被休眠,由此产生不准确的问题发生,这里主要介绍第三种实现方式。
大致原理:在手机中主要存在俩种类型的cpu,AP 与 BP 具体可以参考该链接,总体来说,系统在休眠状态时,AP类型cpu也会被休眠,而应用代码的运行是在AP上的,所以在应用上编写的倒计时处理代码也会被休眠。而系统在休眠状态时,BP并不会被休眠,而AlarmManager类使用的是BP芯片,所以不会被休眠。
使用方式:
- 获取AlarmManager对象:
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
-
调用对应的方法设置定时启动组件:
-
对应的主要方法如下:
set(int type, long triggerAtMillis, PendingIntent operation)
在到了triggerAtMillis 时间开始启动 operation 组件 setRepeating(int type, long triggerAtMillis,long intervalMillis, PendingIntent operation)
设置一个周期性间隔任务,在triggerAtMillis时间开始启动任务,并且间隔intervalmillis后再继续执行该任务 - 对应方法中的一些参数描述
type 定时任务的类型,可选值如下:
- ELAPSED_REALTIME:表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始)。
- ELAPSED_REALTIME_WAKEUP: 表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间。
- RTC:表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用绝对时间(即系统时间)。当系统调用System.currentTimeMillis()方法的返回值与triggerAtTime相等时启动operation所对应的组件。
- RTC_WAKEUP:表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用绝对时间。
triggerAtMillis 毫秒值,定时任务首次触发时间,格局type的不同而对应的含义不同:
type1 和 type2 使用相对系统启动时间,例如:想在开机后一分钟后执行对应的任务,则该值为:一分钟的毫秒值 即:60 000 type3 和 type4 绝对时间,相对于unix时间戳的时间,毫秒单位。
例如:想要马上执行,则用system.currentTimeMillis().如果说想一分钟后执行,则用system.currentTimeMillis()+60 000
intervalMill 间隔任务间隔的周期,单位毫秒。 operation PendingIntent对象,代表时间到了要执行的操作,比如启动activity,service或者发送广播等。
可以用如下方式获取到对应的组件操作
PendingIntent getActivity(Context context, int requestCode,Intent intent,int flags)
打开一个activity组件 PendingIntent getService(Context context, int requestCode,Intent intent,int flags)
启动一个service组件 PendingIntent getBroadcast(Context context, int requestCode, Intent intent,int flags)
发送一个广播信息来启动广播 其中flag对应的常量含义:
FLAG_CANCEL_CURRENT 如果当前系统中已经存在一个相同的PendingIntent对象,那么就将先将已有的PendingIntent取消,然后重新生成一个PendingIntent对象。 FLAG_NO_CREATE 如果当前系统中不存在相同的PendingIntent对象,系统将不会创建该PendingIntent对象而是直接返回null。 FLAG_ONE_SHOT 该PendingIntent只作用一次。在该PendingIntent对象通过send()方法触发过后,PendingIntent将自动调用cancel()进行销毁,那么如果你再调用send()方法的话,系统将会返回一个SendIntentException FLAG_UPDATE_CURRENT 如果系统中有一个和你描述的PendingIntent对等的PendingInent,那么系统将使用该PendingIntent对象,但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据,例如更新Intent中的Extras。
-
- 在实际中使用可能存在的一些问题:
- 在API19(含),即Android4.4之后,为了对电池进行优化,该计时操作可能不准确,但是保留了另外俩个接口是准确的,
setWindow(....)和setExact(....)俩个接口,具体参数形式和上面介绍的差不多。
- 在API19(含),即Android4.4之后,为了对电池进行优化,该计时操作可能不准确,但是保留了另外俩个接口是准确的,
- 取消任务
cancel(PendingIntent operation)
取消对应PendingIntent的任务,这个 intent必须要对应。
附加随笔:一般实际使用倒计时的话,目前我项目中还是偏向于使用广播来接受之后执行对应的操作,这可能就涉及到一些接受广播可能会出现的问题,建议给发送的广播增加对应的权限信息,用来确保广播在本应用中进行传递。
注:alarmManager 不适用于短周期的倒计时,例如每秒一次的倒计时,该类最短间隔为5秒。另外在使用的时候需要注意一种情况,与其他倒计时方式相比,该实现方式不会随着应用程序的杀死而结束(可能会在不同品牌手机的体现不同),那么需要注意的是如果将该方式用于某些界面的倒计时控制的话,假如手机以外断电,那么下次手机重启后,该方式始终还是会继续发送对应任务过来,需要考虑这种特殊情况的发生。