android 後臺長時間執行週期性定時任務 解決方案收集
Alarm manager 主要管理硬體時鐘。
一些與時間相關的應用,如日曆,鬧鐘等需要使用Alarm Manager的服務。Alarm manager功能相對比較簡單,相關程式碼位於
frameworks/base/core/jni/server/com_android_server_AlarmManagerService.cpp
frameworks/base/services/java/com/android/server/AlarmManagerService.java
一. frameworks/base/core/jni/server/com_android_server_AlarmManagerService.cpp
這部分程式碼直接管理硬體時鐘,裝置名為/dev/alarm。包括開啟裝置,關閉裝置,設定時區,設定觸發時間(timeout),以及等待時鐘觸發。
二. frameworks/base/services/java/com/android/server/AlarmManagerService.java
這部分封裝目錄一中的程式碼,向上提供java介面,同時與客戶端(如calendar)互動,接收來自客戶端的時鐘設定請求,並在時鐘觸發時通知客戶端。
Alarm是在預定的時間上觸發Intent的一種獨立的方法。
Alarm超出了應用程式的作用域,所以它們可以用於觸發應用程式事件或動作,甚至在應用程式關閉之後。與Broadcast Receiver結合,它們可以變得尤其的強大,可以通過設定Alarm來啟動應用程式或者執行動作,而應用程式不需要開啟或者處於活躍狀態。
舉個例子,你可以使用Alarm來實現一個鬧鐘程式,執行正常的網路查詢,或者在“非高峰”時間安排耗時或有代價的操作。
對於僅在應用程式生命週期內發生的定時操作,Handler類與Timer和Thread類的結合是一個更好的選擇,它允許Android更好地控制系統資源。
Android中的Alarm在裝置處於睡眠模式時仍保持活躍,它可以設定來喚醒裝置;然而,所有的Alarm在裝置重啟時都會被取消。
Alarm的操作通過AlarmManager來處理,通過getSystemService可以獲得其系統服務,如下所示:
AlarmManager alarms = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
為了建立一個新的Alarm,使用set方法並指定一個Alarm型別、觸發時間和在Alarm觸發時要呼叫的Intent。如果你設定的Alarm發生在過去,那麼,它將立即觸發。
這裡有4種Alarm型別。你的選擇將決定你在set方法中傳遞的時間值代表什麼,是特定的時間或者是時間流逝:
❑ RTC_WAKEUP
在指定的時刻(設定Alarm的時候),喚醒裝置來觸發Intent。
❑ RTC
在一個顯式的時間觸發Intent,但不喚醒裝置。
❑ ELAPSED_REALTIME
從裝置啟動後,如果流逝的時間達到總時間,那麼觸發Intent,但不喚醒裝置。流逝的時間包括裝置睡眠的任何時間。注意一點的是,時間流逝的計算點是自從它最後一次啟動算起。
❑ ELAPSED_REALTIME_WAKEUP
從裝置啟動後,達到流逝的總時間後,如果需要將喚醒裝置並觸發Intent。
Alarm的建立過程演示如下片段所示:
int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
long timeOrLengthofWait = 10000;
String ALARM_ACTION = “ALARM_ACTION”;
Intent intentToFire = new Intent(ALARM_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intentToFire, 0);
alarms.set(alarmType, timeOrLengthofWait, pendingIntent);
當Alarm到達時,你指定的PendingIntent將被觸發。設定另外一個Alarm並使用相同的PendingIntent來替代之前存在的Alarm。
取消一個Alarm,呼叫AlarmManager的cancel方法,傳入你不再希望被觸發的PendingIntent,如下面的程式碼所示:
alarms.cancel(pendingIntent);
接下來的程式碼片段中,設定了兩個Alarm,隨後馬上取消了第一個Alarm。第一個Alarm顯式地設定了在特定的時間喚醒裝置併發送Intent。第二個設定為從裝置啟動後,流逝時間為30分鐘,到達時間後如果裝置在睡眠狀態也不會喚醒它。
AlarmManager alarms = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
String MY_RTC_ALARM = “MY_RTC_ALARM”;
String ALARM_ACTION = “MY_ELAPSED_ALARM”;
PendingIntent rtcIntent = PendingIntent.getBroadcast(this, 0, new Intent(MY_RTC_ALARM), 1);
PendingIntent elapsedIntent = PendingIntent.getBroadcast(this, 0, new Intent(ALARM_ACTION), 1);
// Wakeup and fire intent in 5 hours.(註釋可能有錯)
Date t = new Date();
t.setTime(java.lang.System.currentTimeMillis() + 60*1000*5);
alarms.set(AlarmManager.RTC_WAKEUP, t.getTime(), rtcIntent);
// Fire intent in 30 mins if already awake.
alarms.set(AlarmManager.ELAPSED_REALTIME, 30*60*1000, elapsedIntent);
// Cancel the first alarm.
alarms.cancel(rtcIntent);
1.新增許可權
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
2.建一個Service,在裡面寫:
WakeLock mWakeLock;// 電源鎖
/**
* onCreate時,申請裝置電源鎖
*/
private void acquireWakeLock() {
if (null == mWakeLock) {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
| PowerManager.ON_AFTER_RELEASE, "myService");
if (null != mWakeLock) {
mWakeLock.acquire();
}
}
}
/**
* onDestroy時,釋放裝置電源鎖
*/
private void releaseWakeLock() {
if (null != mWakeLock) {
mWakeLock.release();
mWakeLock = null;
}
}
這樣就可以保證你的Service在鎖屏時不被幹掉。但是這樣又有一個問題,就是耗電特別快,我想借問下高手有人知道要怎樣解決耗電的問題嗎?