Android之Alarm
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.this, id, 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.