Android之Alarm

jopen 10年前

1 简介

        Alarm是在预定的时间上触发Intent的一种独立的方法。

        Alarm 超出了应用程序的作用域,所以它们可以用于触发应用程序事件或动作。在应用程序关闭之后,与Broadcast Receiver结合,它们可以变得尤其的强大,可以通过设置Alarm来启动应用程序或者执行动作,而应用程序不需要打开或者处于活跃状态。
        举个例子,你可以使用Alarm来实现一个闹钟程序,执行正常的网络查询,或者在“非高峰”时间安排耗时或有代价的操作。
        对于仅在应用程序生命周期内发生的定时操作,Handler类与Timer和Thread类的结合是一个更好的选择,它允许Android更好地控制系统资源。
        Android中的Alarm在设备处于睡眠模式时仍保持活跃,它可以设置来唤醒设备;然而,所有的Alarm在设备重启时都会被取消。

 

2 实现方法

        Alarm的操作通过AlarmManager来处理,通过getSystemService可以获得其系统服务,如下所示:
AlarmManager alarms = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

2.1 添加Alarm

2.1.1 需要定义一个日历对象mCal

        private Calendar mCal = Calendar.getInstance();

2.1.2 获取AlarmManager

        AlarmManager alarms = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

2.1.3 设置警告时间

    //Sets the time of this Calendar.
    mCal.setTimeInMillis(System.currentTimeMillis());
    //Sets a field to the specified value.
    mCal.set(Calendar.HOUR_OF_DAY, tPicker.getCurrentHour());
    mCal.set(Calendar.MINUTE, tPicker.getCurrentMinute());
    mCal.set(Calendar.SECOND, 0);
    mCal.set(Calendar.MILLISECOND, 0);

 

2.1.4 注册intent

需要注意的有两点:第一,为什么要使用PendingIntent ;第二,PendingIntent获取。

        //由于Alarm是在预定的时间上触发Intent的一种独立的方法,所以需要使用PendingIntent,而且需要设定负责处理该PendingIntent的广播类AlarmCaller.class。
        Intent intent = new Intent(SettingsActivity.this, AlarmCaller.class);
        PendingIntent sender = PendingIntent.getBroadcast(SettingsActivity.this, id, intent, 0);

1) PendingIntent和Intent的区别

        Intent 表示一个目的,第一个参数表示所在类,第二个参数表示目标类。Intent 字面意思是意图,即我们的目的,我们想要做的事情,在activity中,我们可以立即执行它。
        PendingIntent 即是一个Intent的描述。PendingIntent 相当于对intent执行了包装,我们不一定一定要马上执行它,我们将其包装后,传递给其他activity或application。这时,获取到 PendingIntent  的application 能够根据里面的intent 来得知发出者的意图,选择拦击或者继续传递或者执行。

2) PendingIntent的获取

public static PendingIntent getBroadcast (Context context, int requestCode, Intent intent, int flags) 
Retrieve a PendingIntent that will perform a broadcast, like calling Context.sendBroadcast().

Parameters
context             The Context in which this PendingIntent should perform the broadcast. 
requestCode     Private request code for the sender (currently not used). 
intent                 The Intent to be broadcast. 
flags                  May be FLAG_ONE_SHOT, FLAG_NO_CREATE, FLAG_CANCEL_CURRENT, FLAG_UPDATE_CURRENT, or any of the flags as supported by Intent.fillIn() to control which unspecified parts of the intent that can be supplied when the actual send happens. 

Returns
Returns an existing or new PendingIntent matching the given parameters. May return null only if FLAG_NO_CREATE has been supplied.

2.1.5 注册Alarm

注册Alarm有3种方法。

1) public void set (int type, long triggerAtTime, PendingIntent operation) 
设置Alarm,但是只提醒一次。

If there is already an alarm scheduled for the same IntentSender, it will first be canceled. 
If the time occurs in the past, the alarm will be triggered immediately.

If there is already an alarm for this Intent scheduled (with the equality of two intents being defined by filterEquals(Intent)), then it will be removed and replaced by this one.

 

2) public void setInexactRepeating (int type, long triggerAtTime, long interval, PendingIntent operation) 

设置Alarm,可以重复提醒多次,时间间隔由interval确定,但是这种重复提醒是不精确的。
Schedule a repeating alarm that has inexact trigger time requirements; for example, an alarm that repeats every hour, but not necessarily at the top of every hour. These alarms are more power-efficient than the strict recurrences supplied by setRepeating(int, long, long, PendingIntent).

 

3) public void setRepeating (int type, long triggerAtTime, long interval, PendingIntent operation) 

设置Alarm,可以精确重复提醒多次,时间间隔由interval确定。
Schedule a repeating alarm. Note: for timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.

If there is already an alarm scheduled for the same IntentSender, it will first be canceled. 

Like set(int, long, PendingIntent), except you can also supply a rate at which the alarm will repeat. This alarm continues repeating until explicitly removed with cancel(PendingIntent).

If the time occurs in the past, the alarm will be triggered immediately, with an alarm count depending on how far in the past the trigger time is relative to the repeat interval. 


        需要说明的是setRepeating的第一个参数type,主要有4种Alarm类型:


* RTC_WAKEUP
        在指定的时刻(使用UTC格式)唤醒设备来触发Intent。

        Alarm time in System.currentTimeMillis() (wall clock time in UTC), which will wake up the device when it goes off. Alarm time in System.currentTimeMillis() (wall clock time in UTC), which will wake up the device when it goes off. 

*  RTC
        在一个显式的时间(使用UTC格式)触发Intent,但不唤醒设备。

        Alarm time in System.currentTimeMillis() (wall clock time in UTC). This alarm does not wake the device up; if it goes off while the device is asleep, it will not be delivered until the next time the device wakes up.


*  ELAPSED_REALTIME
        从设备启动后,如果流逝的时间达到总时间,那么触发Intent,但不唤醒设备。流逝的时间包括设备睡眠的任何时间。注意一点的是,时间流逝的计算点是自从它最后一次启动算起。

        Alarm time in SystemClock.elapsedRealtime() (time since boot, including sleep). This alarm does not wake the device up; if it goes off while the device is asleep, it will not be delivered until the next time the device wakes up. 

*  ELAPSED_REALTIME_WAKEUP
        从设备启动后,达到流逝的总时间后,如果需要将唤醒设备并触发Intent。

        Alarm time in SystemClock.elapsedRealtime() (time since boot, including sleep), which will wake up the device when it goes off. 

 

        //定义重启Alarm的时间间隔
        int mTimeInterval = 60 * 60 * 24 * 1000;
        alarms.setRepeating(AlarmManager.RTC_WAKEUP, mCal.getTimeInMillis(), mTimeInterval,sender);


2.2 删除Alarm

2.2.1 获取AlarmManager 

    AlarmManager alarms = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

2.2.2 注册intent

    Intent intent = new Intent(SettingsActivity.this, AlarmCaller.class);
    PendingIntent sender = PendingIntent.getBroadcast(SettingsActivity.thisid, intent, 0);

2.2.3 取消Alarm注册

    alarms.cancel(sender);

 

public void cancel (PendingIntent operation) 
Remove any alarms with a matching Intent. Any alarm, of any type, whose Intent matches this one (as defined by filterEquals(Intent)), will be canceled.

Parameters
operation IntentSender which matches a previously added IntentSender.