1. 程式人生 > >android 後臺長時間執行週期性定時任務 解決方案收集

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在鎖屏時不被幹掉。但是這樣又有一個問題,就是耗電特別快,我想借問下高手有人知道要怎樣解決耗電的問題嗎?