Android開發技巧(三)—— 創建定時任務

每種手機都有自己的休眠策略,Android手機在長時間不操作時會自動讓CPU進入睡眠狀態,這就導致JAVA原生Timer的定時任務無法運行。

所以我們需要藉助Alarm喚醒CPU

一、Alarm機制

Alarm藉助了AlermManager類,這個類和NotificationManger類似。通過調用ContextgetSystemService(),來獲取實例,不過這裏要傳入Context..ALARM_SERVICE,因此,獲取AlarmManager實例可以寫成:

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

接下來調用AlertManagerset()方法就能設置一個定時任務,比如10秒後任務執行:

long triggerAtTime = SystemClock.elapsedRealtime() + 10*1000;
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pendingIntent);

SystemClock.elepsedRealtime()可以獲取到系統開機至今的毫秒數
System.cuurrentTimeMillis()可以獲取到1970.1.1至今的毫秒數
set()方法有三個參數:

  • 第一個參數:整型參數,用於指定工作類型,有四種值可選:
    • ELAPSED_REALTIME:定時任務的觸發時間從開機開始算起,但不會喚醒CPU
    • ELAPSED_REALTIME_WAKEUP:定時任務的觸發時間從系統開機開始算起,會喚醒CPU
    • RTC:定時任務的觸發時間從1970.1.1開始算起,但不會喚醒CPU
    • RTC_WAKEUP:定時任務的觸發事件從1970.1.1開始算起,但會喚醒CPU
  • 第二個參數:任務的觸發時間,以毫秒爲單位
  • 第三個參數PendingIntent,一個可以觸發的廣播或服務

再比如要實現一個可以長時間在後臺定時運行的服務:
首先建一個普通的服務,比如起名爲LongRunningService,然後把觸發定時任務的代碼寫在onStartCommand()

public class LongRunningService extends Service{
	@Override
	public IBinder onBind(Intent intent){
		return null;
	}
	
	@Overide
	public int onStartCommand(Intent intent, int flags, int startId){
		new Thread(new Runnable(){
			@Override
			public void run(){
				// 在這裏執行具體的邏輯事件
			}
		}).start();
		AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
		int anHour = 60*60*1000;
		long triggerAtTime = SystemClock.elapsedRealtime()+anHour();
		Intent i = new Intent(this, LongRunningService.class);
		PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
		manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
		return super.onStartCommand(intent, flags, startId);
	}
}

這樣就能保證定時任務每一小時執行依次一次,最後,這樣啓動這個定時任務:

Intent intent = new Intent(context, LongRunningService.class);
context.startService(intent);

Androiod4.4 之後,Alarm任務的觸發時間不再準確,這是系統做出了耗電優化,用setExact()代替set()即可準時運行

二、Doze模式

在安卓6.0之後,谷歌又加入了全新的Doze模式,就是說當屏幕關閉一段時間後,系統會對CPU,網絡、Alarm等活動做出限制,從而延長電池壽命
但是系統會間歇性退出Doze模式一小段時間,讓應用完成他們的同步操作和Alerm任務。

具體限制:

  • 網絡訪問被禁止
  • 忽略喚醒CPU和屏幕操作
  • 不再wifi掃描
  • 不再執行同步任務
  • Alarm任務將會在下次退出Doze模式時執行

這使得我們的Alarm任務不再準時,但如果你非要準時執行,也有特殊方案:
AlarmManager.setAndAllowWhileIdle()AlermManager,setExactAndAllowWhileIdle()使得Doze模式也能正常執行定時任務,使用方法和之前的setExact()set()一樣

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章