最近有個需求,需要在android手機後臺一直執行一個任務,有一定的時間間隔。
目前方案有以下幾種
方式一:採用Handler的postDelayed(Runnable, long)方法
handler = new Handler();
runnable = new Runnable() {
@Override
public void run() {
// handler自帶方法實現定時器
System.out.println("33331");
handler.postDelayed(this, 1000*3);//每隔3s執行
}
};
handler.postDelayed(runnable, 1000*60);//延時多長時間啓動定時器
方式二:採用timer及TimerTask結合的方法
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println("99999998");
}
};
timer.schedu,
1000,//延遲1秒執行
Time);//週期時間
}
方式三:採用AlarmManager機制
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
// EventBus.getDefault().post(new EventCategory(7));
System.out.println("99999988");//這是定時所執行的任務
}
}).start();
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
int anhour=6*1000;
long triggerAtMillis = SystemClock.elapsedRealtime()+anhour;
Intent alarmIntent = new Intent(this,MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(pendingIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {// 6.0
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtMillis, pendingIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {// 4.4
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtMillis, pendingIntent);
} else {
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtMillis, pendingIntent);
}
return super.onStartCommand(intent, flags, startId);
}
這裏一定要注意的是AlarmManager.ELAPSED_REALTIME_WAKEUP 後面這個類型
記住不要再用setRepeating了,這個方法過時了,設置了一點都不去精確
還有很多人容易寫成RTC_WAKEUP ,但是取時間的時候卻用的是SystemClock.elapsedRealtime()
SystemClock.elapsedRealtime()獲取從設備boot後經歷的時間值。
SystemClock.elapsedRealtime()計算某個時間經歷了多長時間有意義,例如通話經歷了多長時間,這個值是系統設置無關,這是會導致一個不管怎麼設置時間,結果都是5S執行一次的問題,請大家注意,一定要根據上面表格來。
記得註冊服務
調用方式
這裏推薦使用第三種方式
Timer並不太適用於那些需要長期在後臺運行的定時任務。爲了能讓電池更加耐用,每種手機都會有自己的休眠策略,Android 手機就會在長時間不操作的情況下自動讓 CPU 進入到睡眠狀態,這就有可能導致 Timer 中的定時任務無法正常運行。
Alarm具有喚醒 CPU 的功能,即可以保證每次需要執行定時任務的時候 CPU 都能正常工作。
1,Alarm定時不需要程序自身去維護,而又系統來維護,使得程序更好避免了容易出錯問題,更是佔用系統資源,cpu佔有率。
2,即使程序退出後,程序自身不會有任何煩惱的問題,系統到時間自動調用對應組件執行定義好的邏輯
3,定時的多樣性,包括一次定時,循環定時(在xx年x月x日執行,週一至週五執行,每天幾點幾分執行。。。)
如果你的應用是TO C的話,保活請看這一篇,全網搜過寫的最好的
https://www.jianshu.com/p/63aafe3c12af
如果你是TO B的,也就是面向企業的或者工具類的,可以這樣子
比如我的測試手機小米5s,打開應用管理
**
找到我們的應用Testkill,設置自啓動,設置之後,你的APK將做到即便是手動清理APP進程,也能在系統下自行重啓,會重新調用我們上述的MyService,從而達到無敵保活狀態,當然華爲,以及別的手機都會有自己的這個東西,類似白名單,把你的APK加進去即可。
**
比如我們看微信的,爲何能做到無敵保活狀態呢,即便是殺掉的狀態依然能接受新的微信消息,彈出消息提示
!
如果你把自啓動給它關掉,經過驗證,微信被殺也是無法接受新消息提醒的,over。
下面我們來說說使用AlarmManager的一些坑
測試手機系統Android 5.1.1
時間設置爲2S,看看執行結果
小米5 Android8.0
設置成4S的話兩個手機依然執行5s
驗證成功 !!!
由於google對電量做了優化,5S是最小輪詢單位
5S以內不管怎麼設置時間,都是5S執行一次,
凡是>5S的,都是可以在5S以上時間執行的,ojbk.
Android JetPack有個組件WorkManager,也可以實現一些後臺定時任務,https://www.jianshu.com/p/f07e4141d432
WorkManager用於那些需要保證即使APP退出了系統依然可以運行的任務,比如將應用數據上傳到服務器。不要用於如果APP被殺進程,可以安全終止的後臺任務
參考
定時任務,AlarmManager使用
https://www.cnblogs.com/ProtectedDream/p/6351447.html#4079768