有一些特點:
1. 在設定時間或週期啟動 Intent
2. 搭配 broadcast receiver 來啟動 service 及進行其他操作
3. 由於它在 app 之外運行,即使 app 沒有運行或休眠中我們仍可以用來觸發事件
4. 因為可以週期喚醒,所以 app 不用常駐而可以節省系統資源(比 Handler + Timer + Thread 省資源)
repeating alarm 是一個靈活度有限的簡單機制
如果需要網路操作的話這可能不會是一個最佳選擇
設計不當的話甚至會榨乾電池及造成系統負載
常見的狀況是在 app 外觸發操作去跟 server 進行資料同步
但如果你對 server 有足夠的掌控權的話應該使用 Google Cloud Messaging (GCM) 搭配 sync adapter 會比較好
sync adapter 比 AlarmManager 更有靈活性
官方建議了一些關於 alarm 的 Best practices:
* 對任何 network requests 加入隨機性觸發
- 當 alarm 觸發時執行任何 local (不須網路的)工作
- 同時安排一個在隨機時間觸發的 alarm 去執行 network requests
* alarm 越少、越不頻繁,越好
* 若無必要不要喚醒 device
* 使用 setInexactRepeating() 取代 setRepeating()
android 可以把不同 app 的 repeating alarm 同步及同時觸發,這會減少系統喚醒 device 的次數並改善電池消耗
(在 Android 4.4 (API Level 19)之後,所有的 repeating alarms 都是 inexact)
* 盡量避免根據時鐘的時間設定 alarm
定義精確時間的 alarm 比較無法展延,可能的話使用 ELAPSED_REALTIME 這個 alarm type
一個 repeating alarm 有以下幾個屬性:
* alarm type
- ELAPSED_REALTIME (建議選項,適合間隔時間的鬧鐘,以 time since system boot 作為參照,所以不受時區影響)
- ELAPSED_REALTIME_WAKEUP (WAKEUP 版本會在 screen off 狀況下喚醒 CPU,以確保能準時觸發)
- RTC (real time clock) 適合固定時間的鬧鐘或與地區相關的運用,使用 UTC (wall clock)為參照
- RTC_WAKEUP (RTC 的 WAKEUP 版本)
* trigger time - 如果時間已經過了,alarm 會立即觸發
* interval(間隔)
* PendingIntent - alarm 觸發時會啟動。你的第二個 alarm 也會使用同一個 PendingIntent(把原本的蓋過)
接下來看一下官方提供的範例
ELAPSED_REALTIME_WAKEUP:
30 分鐘後喚醒設備並啟動鬧鐘,每 30 分鐘重複一次
// 每半小時喚醒還是蠻耗電的,官方強烈希望你把間隔拉長一點 alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);一分鐘後啟動的單次鬧鐘
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60 * 1000, alarmIntent);
RTC_WAKEUP:
鬧鐘訂於大約下午兩點,並重複於每日同一時間
Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.HOUR_OF_DAY, 14); // setInexactRepeating() 必須傳入 AlarmManager interval 常數,這裡用的是 AlarmManager.INTERVAL_DAY // 注意時間會是大約值,無法非常精確 alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);喚醒設備於當日 8:30 am,每 20 分鐘重複
private AlarmManager alarmMgr; private PendingIntent alarmIntent; ... alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, AlarmReceiver.class); alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.HOUR_OF_DAY, 8); calendar.set(Calendar.MINUTE, 30); // 使用 setRepeating 可以精確指定鬧鐘響的時間,重複時間就不用 AlarmManager 常數,而是直接給間隔的毫秒值 // 再提醒一次:在 Android 4.4 (API Level 19)之後,所有的 repeating alarms 都是 inexact alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * 20, alarmIntent);
Cancel an Alarm
在 PendingIntent 裡我們可以取出 alarmMgr 再用 alarmMgr.cancel 取消鬧鐘
//如果鬧鐘已經設定了就取消 if (alarmMgr!= null) { alarmMgr.cancel(alarmIntent); }
Start an Alarm When the Device Boots
當關機時,所有鬧鐘都會被取消,所以我們可以在開機時重設鬧鐘
首先當然我們要宣告接收 BOOT_COMPLETED 事件,還有該事件的 receiver
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> ... <receiver android:name=".SampleBootReceiver" android:enabled="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"></action> </intent-filter> </receiver/>然後實作這個 BroadcastReceiver 去接收 BOOT_COMPLETED
public class SampleBootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { // Set the alarm here. } } }由於上面在 manifest 中把 receiver 的 android:enabled 設為 false 以避免不必要的通知
所以我們在需要接收通知時在程式中將它 enable
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class); PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, //或 PackageManager.COMPONENT_ENABLED_STATE_DISABLED PackageManager.DONT_KILL_APP);一旦設為 PackageManager.COMPONENT_ENABLED_STATE_ENABLED 後,因為會覆蓋原本 manifest 的設定,即使重新開機它也會保持在 enable
所以當使用者取消鬧鐘(或我們不再需要接收這事件的情況下)可以再用一樣方法將 enabled 設回 PackageManager.COMPONENT_ENABLED_STATE_DISABLED
相關資料:
Managing Device Awake State
Scheduling Repeating Alarms
沒有留言:
張貼留言