在Java中我们是通过Timer类来实现定时任务的,但是Android手机会在长时间不操作的情况下自动让cpu进入到睡眠状态,从而延长待机时间,这样一来就有可能导致Timer类的定时任务无法正常运行。而Alarm则具有唤醒cpu的功能。
1.获取AlarmManager的实例
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
这里获取AlarmManager实例的方法和获取NotificationManager实例的方法类似,都是通过调用Context.getSystemService()方法,然后传入Context.ALARM_SERVICE来获取。
2.设置定时任务
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pendingIntent);
设置定时任务的时候,有四种方法,分别为set()、setExact()、setAndAllowWhileIdle()、setExactAndAllowWhileIdle()。这四种方法的区别一会再说,先看看它们的参数列表。一般而言它们都接收三个参数,分别为:定时任务工作类型、定时任务触发的时间(毫秒为单位)以及PendingIntent。其中工作类型又有以下四种情况:
因为有两种计时方式,在传入第二个参数时,我们也应该与计时方式对应,例如延时一小时执行定时任务的话,我们可以这么写:
从系统开机开始计时
int anHour = 60*60*1000;
long triggerAtTime = SystemClock.elapsedRealtime()+anHour;
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pendingIntent);
从1970年1月1日0点开始计时
int anHour = 60*60*1000;
long triggerAtTime = System.currentTimeMillis()+anHour;
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,triggerAtTime,pendingIntent);
之前说到设置定时任务时有四种方法,观察方法名可以发现 set() 和 setExact() 为一组,setAndAllowWhileIdle() 和 setExactAndAllowWhileIdle() 为一组。其中带有Exact的是为了让定时任务准时执行的。因为从Android4.4开始,系统在耗电性方面进行了优化,系统会自动检测目前有多少Alarm任务存在,然后将触发时间相近的几个任务放在一起执行,这样就可以大幅度地减少CPU被唤醒的次数,从而有效延长电池使用时间,但是Alarm任务的触发时间将会变得不准确。
set() 和 setAndAllowWhileIdle() 的区别在于,前者是普通的定时任务而后者是用于Doze模式下的定时任务。
当用户的设备是Android6.0或以上系统时,如果该设备为插接电源,处于静止状态(Android7.0中删除了这一条件),并且屏幕关闭了一段时间之后,就会进入到Doze模式。在该模式下,系统会对以下功能进行限制,从而延长电视使用寿命。
当然,系统并不会一直处于Doze模式,而是会间歇性地退出一小段时间来完成上述被限制的功能。