Android Doze模式下Alarm定時任務實現(xiàn)流程詳解
定時任務
Timer不太適合那些需要長期在后臺運行的定時任務,因為每個手機都有自己的休眠策略,Android手機長時間不操作就會導致Timer定時任務無法執(zhí)行,而Alarm具有喚醒CPU的功能,能保證大多數(shù)情況下,執(zhí)行定時任務的時候CPU能正常工作。
AlarmManager manager= (AlarmManager) getSystemService(Context.ACTIVITY_SERVICE); PendingIntent pendingIntent; /** * SystemClock.elapsedRealtime():獲取到系統(tǒng)開機至今所經(jīng)歷的毫秒數(shù) * System.currentTimeMillis():1970-1-1 0:00至今所經(jīng)歷的毫秒數(shù) * * ELAPSED_REALTIME:定時任務觸發(fā)從系統(tǒng)開機算起 但不喚醒CPU * ELAPSED_REALTIME_WAKEUP:定時任務觸發(fā)從系統(tǒng)開機算起 喚醒CPU * RTC:從1970-1-1 0:00算起 不喚醒CPU * RTC_WAKEUP:從1970-1-1 0:00算起 喚醒CPU */ /**pendIntent:一般會調(diào)用getSrervice或getBroadCast 來獲取一個能夠執(zhí)行服務或廣播的pendingIntent, 這樣才能保證在任務被觸發(fā)的時候, 服務里的onStartCommand()和onRecive()方法被執(zhí)行 */ long time= SystemClock.elapsedRealtime()+10*1000;//10秒鐘后執(zhí)行任務 manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,time,pendingIntent);
那么要實現(xiàn)一個長時間在后臺定時運行的服務該怎么做?
創(chuàng)建一個MyService類
package com.example.test; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.SystemClock; import androidx.annotation.Nullable; public class MyService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { new Thread(new Runnable() { @Override public void run() { //TODO } }).start(); AlarmManager manager= (AlarmManager) getSystemService(ALARM_SERVICE); int time=60*60*1000;//一小時 long triggerAtTime= SystemClock.elapsedRealtime()+time; Intent intent1=new Intent(this,MyService.class); PendingIntent pendingIntent=PendingIntent.getService(this,0,intent1,0); manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pendingIntent); return super.onStartCommand(intent, flags, startId); } }
可以看到先創(chuàng)建了一個子線程在這里執(zhí)行具體的操作任務,然后就是alarm機制,定義任務觸發(fā)一小時后,再使用PendingIntent指定定時處理任務的MyService,最后調(diào)用set方法設定完成。
這樣就將一個長時間在后臺定時運行的服務設定成功了,一旦啟動了MyService,就會在onStartCommand()方法里設定一個定時任務,這樣一小時后將會再次啟動MyService,每隔一小時就會執(zhí)行一次。
然后去使用,在manifest文件中注冊服務
<service android:name=".MyService"/>
在使用的地方調(diào)用下面代碼就可以。
Intent intent=new Intent(context,MyService.class); context.startService(intent);
但是在Android4.4后,定時任務變得不準確,會延時一段時間才能執(zhí)行,那是因為系統(tǒng)在耗電方面進行的優(yōu)化,系統(tǒng)會檢測有多少Alarm任務存在,將觸發(fā)時間相近的幾個任務放在一起執(zhí)行,這樣可以大幅度的減少CPU被喚醒的次數(shù),演唱電池的使用時長。也可以使用setExact()來代替set()方法,可以保證任務能夠準時執(zhí)行。
Doze模式
如果設備未充電,并處于靜止狀態(tài),且屏幕關閉了一段時間后,就能進入到Doze模式。
在Doze模式下,系統(tǒng)會對CPU、網(wǎng)絡、Alarm等活動進行限制,從而延長電池的使用壽命。當然,系統(tǒng)并不會一直處于Doze模式,而是會間歇性地退出Doze模式一小段時間,在這段時間中,應用就可以去完成它的同步操作、Alarm任務等。
Doze模式下受限制的功能:
- 網(wǎng)絡訪問被禁止。
- 系統(tǒng)忽略喚醒CPU或者屏幕操作。
- 系統(tǒng)不再執(zhí)行WIFI掃描。
- 系統(tǒng)不再執(zhí)行同步服務。
- Alarm任務將會在下次退出Doze模式的時候執(zhí)行。
在Doze模式下, Alarm任務會變得相當不準,當然這種情況下對Alarm的要求也并不高,如果有特殊的要求,調(diào)用AlarmManager的setAndAllowWhileIdle()或者setExactAndAllowWhileIdle()方法就能讓定時任務正常執(zhí)行,和set()與setExact()的區(qū)別是一樣的。
到此這篇關于Android Doze模式下Alarm定時任務實現(xiàn)流程詳解的文章就介紹到這了,更多相關Android Alarm定時任務內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android編程獲取網(wǎng)絡連接方式及判斷手機卡所屬運營商的方法
這篇文章主要介紹了Android編程獲取網(wǎng)絡連接方式及判斷手機卡所屬運營商的方法,涉及Android針對網(wǎng)絡的判斷及本機信息的獲取技巧,需要的朋友可以參考下2016-01-01Android中使用Notification實現(xiàn)狀態(tài)欄的通知
本文主要介紹了android利用Notification實現(xiàn)狀態(tài)欄的通知的示例代碼。具有很好的參考價值。下面跟著小編一起來看下吧2017-04-04Android 不同Activity間數(shù)據(jù)的傳遞 Bundle對象的應用
本篇文章小編為大家介紹,Android 不同Activity間數(shù)據(jù)的傳遞 Bundle對象的應用。需要的朋友參考下2013-04-04Kotlin中常見內(nèi)聯(lián)擴展函數(shù)的使用方法教程
在Kotlin中,使用inline修飾符標記內(nèi)聯(lián)函數(shù),既會影響到函數(shù)本身, 也影響到傳遞給它的Lambda表達式,這兩者都會被內(nèi)聯(lián)到調(diào)用處。下面這篇文章主要給大家介紹了關于Kotlin中常見內(nèi)聯(lián)擴展函數(shù)的使用方法,需要的朋友可以參考下。2017-12-12Android開發(fā)實現(xiàn)圖片平移、縮放、倒影及旋轉(zhuǎn)功能的方法
這篇文章主要介紹了Android開發(fā)實現(xiàn)圖片平移、縮放、倒影及旋轉(zhuǎn)功能的方法,涉及Android針對圖片的讀取、寫入、屬性設置及矩陣運算等相關操作技巧,需要的朋友可以參考下2017-10-10