Alarm是一种预先确定的时间或时间间隔内激活Intent的方式。和Timer不同,Alarm是在应用程序之外操作的,所以即使应用程序关闭,它们也仍然能够用来激活应用程序事件或操作。当它们和Broadcast Receiver一起使用时会更加强大,允许设置能够激活广播Intent、启动Service、甚至启动Activity的Alarm,而不需要打开或者运行应用程序。
Alarm是降低应用程序资源需求的一种极为有效的方式,它允许停止Service和清除定时器,同时仍然可以执行调度的操作。可以使用Alarm实现基于网络查找的定时更新,或者把费时的或者成本受约束的操作安排在“非高峰”时期运行,又或者对失败的操作调度重试。
对于那些只在应用程序的生命周期内发生的定时操作,将Handler类和Timer以及Thread组合起来使用是一种比使用Alarm更好的方法,因为这样做允许Android更好地控制系统资源。通过把调度事件移出应用程序的控制范围,Alarm提供了一种缩短应用程序生命周期的机制。
Android中的Alarm在设备处于休眠状态时依然保持活动状态,可以有选择地设置Alarm来唤醒设备;然而,无论何时重启设备,所有的Alarm都会被取消。Alarm操作是通过AlarmManager进行处理的,AlarmManager是一个通过getSystemService访问的系统Service
一次性Alarm
要创建一个新的只激活一次的Alarm,可以使用set方法并给它指定一个Alarm类型、触发时间和一个要激活的Pending Intent。如果把Alarm的触发时间设置为过去的时间,那么它将会被立即触发。
以下是4种可用的Alarm类型:
RTC_WAKEUP: 在指定的时间唤醒设备,并激活Pending Intent
RTC: 在指定的时间点激活Pending Intent,但是不会唤醒设备
ELAPSED_REALTIME: 根据设备启动之后经过的时间激活Pending Intent,但是不会唤醒设备。经过的时间包含设备休眠的所有时间。
ELAPSED_REALTIME_WAKEUP: 在设备启动并经过指定的时间之后唤醒设备和激活Pending Intent
你的选择将会决定传递给set方法的时间值是一个特定的时间,还是一个已经过去的等待时间。当触发Alarm时,就会广播指定的Pending Intent。因此,使用相同的Pending Intent设置第二个Alarm会代替已经存在的Alarm。要取消一个Alarm,需要调用Alarm Manager的cancel方法,并传递给它不再想触发的Pending Intent。
示例
//设备如果处于休眠状态,设置Alarm来唤醒设备 int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP; //10秒后触发设备 long timeOrLengthOfWait = 10000; //创建能够广播和操作的Pending Intent String ALARM_ACTION = "ALARM_ACTION"; Intent intentToFire = new Intent(ALARM_ACTION); PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, intentToFire, 0); //设置Alarm alarmManager.set(alarmType, timeOrLengthOfWait, alarmIntent); //要取消一个Alarm //alarmManager.cancel(alarmIntent);
重复Alarm
重复Alarm和一次性Alarm具有相同的工作方式,不过会在指定的时间间隔重复触发。因为Alarm是应用程序生命周期之外设置的,所以它们十分适合于调度定时更新或者数据查找,从而避免了在后台持续运行Service。要想设置重复Alarm,可以使用Alarm Manager的setRepeating或setInexactRepeating方法。两种方法都支持指定Alarm类型、第一次触发的时间和Alarm触发时激活的Pending Intent当需要对重复Alarm的精确时间间隔进行细粒度的控制时,可以使用setRepeating方法。传入这个方法的时间间隔值可以用于指定Alarm的确切时间间隔,最多可以精确到毫秒。当按照计划定时唤醒设备来执行更新时会消耗电池的电量,setInexactRepeating方法能够帮助减少这种电量消耗。在运行时Android会同步多个没有精确指定时间间隔的重复Alarm,并同时触发它们。
setInexactRepeating方法接受下面列出的一个Alarm Manager常量,所以不必为它指定精确的时间间隔:
INTERVAL_FIFTEEN_MINUTES
INTERVAL_HALF_HOUR
INTERVAL_HOUR
INTERVAL_HALF_DAY
INTERVAL_DAY
使用没有精确指定时间间隔的重复Alarm,可以避免每个应用程序在类似但不重叠的时间段内独立唤醒设备。
通过同步这些Alarm,系统可以限制定期重复事件对电池电量的影响。
示例
//获取一个Alarm Manager的引用。 AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE); //如果设备处于休眠状态,设置Alarm来唤醒设备。 int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP; //调度Alarm以每半小时重复一次。 long timeOrLengthOfWait = AlarmManager.INTERVAL_HALF_HOUR; //创建能够广播和操作的Pending Intent String ALARM_ACTION = "ALARM_ACTION"; Intent intentToFire = new Intent(ALARM_ACTION); PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, intentToFire, 0); //每半小时唤醒设备以激活一个Alarm alarmManager.setInexactRepeating(alarmType, timeOrLengthOfWait, timeOrLengthOfWait, alarmIntent); //取消Alarm //alarmManager.cancel(alarmIntent);