Android Doze模式下Alarm定時(shí)任務(wù)實(shí)現(xiàn)流程詳解
定時(shí)任務(wù)
Timer不太適合那些需要長(zhǎng)期在后臺(tái)運(yùn)行的定時(shí)任務(wù),因?yàn)槊總€(gè)手機(jī)都有自己的休眠策略,Android手機(jī)長(zhǎng)時(shí)間不操作就會(huì)導(dǎo)致Timer定時(shí)任務(wù)無(wú)法執(zhí)行,而Alarm具有喚醒CPU的功能,能保證大多數(shù)情況下,執(zhí)行定時(shí)任務(wù)的時(shí)候CPU能正常工作。
AlarmManager manager= (AlarmManager) getSystemService(Context.ACTIVITY_SERVICE);
PendingIntent pendingIntent;
/**
* SystemClock.elapsedRealtime():獲取到系統(tǒng)開機(jī)至今所經(jīng)歷的毫秒數(shù)
* System.currentTimeMillis():1970-1-1 0:00至今所經(jīng)歷的毫秒數(shù)
*
* ELAPSED_REALTIME:定時(shí)任務(wù)觸發(fā)從系統(tǒng)開機(jī)算起 但不喚醒CPU
* ELAPSED_REALTIME_WAKEUP:定時(shí)任務(wù)觸發(fā)從系統(tǒng)開機(jī)算起 喚醒CPU
* RTC:從1970-1-1 0:00算起 不喚醒CPU
* RTC_WAKEUP:從1970-1-1 0:00算起 喚醒CPU
*/
/**pendIntent:一般會(huì)調(diào)用getSrervice或getBroadCast
來(lái)獲取一個(gè)能夠執(zhí)行服務(wù)或廣播的pendingIntent,
這樣才能保證在任務(wù)被觸發(fā)的時(shí)候,
服務(wù)里的onStartCommand()和onRecive()方法被執(zhí)行
*/
long time= SystemClock.elapsedRealtime()+10*1000;//10秒鐘后執(zhí)行任務(wù)
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,time,pendingIntent);那么要實(shí)現(xiàn)一個(gè)長(zhǎng)時(shí)間在后臺(tái)定時(shí)運(yùn)行的服務(wù)該怎么做?
創(chuàng)建一個(gè)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;//一小時(shí)
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)建了一個(gè)子線程在這里執(zhí)行具體的操作任務(wù),然后就是alarm機(jī)制,定義任務(wù)觸發(fā)一小時(shí)后,再使用PendingIntent指定定時(shí)處理任務(wù)的MyService,最后調(diào)用set方法設(shè)定完成。
這樣就將一個(gè)長(zhǎng)時(shí)間在后臺(tái)定時(shí)運(yùn)行的服務(wù)設(shè)定成功了,一旦啟動(dòng)了MyService,就會(huì)在onStartCommand()方法里設(shè)定一個(gè)定時(shí)任務(wù),這樣一小時(shí)后將會(huì)再次啟動(dòng)MyService,每隔一小時(shí)就會(huì)執(zhí)行一次。
然后去使用,在manifest文件中注冊(cè)服務(wù)
<service android:name=".MyService"/>
在使用的地方調(diào)用下面代碼就可以。
Intent intent=new Intent(context,MyService.class);
context.startService(intent);但是在Android4.4后,定時(shí)任務(wù)變得不準(zhǔn)確,會(huì)延時(shí)一段時(shí)間才能執(zhí)行,那是因?yàn)橄到y(tǒng)在耗電方面進(jìn)行的優(yōu)化,系統(tǒng)會(huì)檢測(cè)有多少Alarm任務(wù)存在,將觸發(fā)時(shí)間相近的幾個(gè)任務(wù)放在一起執(zhí)行,這樣可以大幅度的減少CPU被喚醒的次數(shù),演唱電池的使用時(shí)長(zhǎng)。也可以使用setExact()來(lái)代替set()方法,可以保證任務(wù)能夠準(zhǔn)時(shí)執(zhí)行。
Doze模式
如果設(shè)備未充電,并處于靜止?fàn)顟B(tài),且屏幕關(guān)閉了一段時(shí)間后,就能進(jìn)入到Doze模式。
在Doze模式下,系統(tǒng)會(huì)對(duì)CPU、網(wǎng)絡(luò)、Alarm等活動(dòng)進(jìn)行限制,從而延長(zhǎng)電池的使用壽命。當(dāng)然,系統(tǒng)并不會(huì)一直處于Doze模式,而是會(huì)間歇性地退出Doze模式一小段時(shí)間,在這段時(shí)間中,應(yīng)用就可以去完成它的同步操作、Alarm任務(wù)等。

Doze模式下受限制的功能:
- 網(wǎng)絡(luò)訪問被禁止。
- 系統(tǒng)忽略喚醒CPU或者屏幕操作。
- 系統(tǒng)不再執(zhí)行WIFI掃描。
- 系統(tǒng)不再執(zhí)行同步服務(wù)。
- Alarm任務(wù)將會(huì)在下次退出Doze模式的時(shí)候執(zhí)行。
在Doze模式下, Alarm任務(wù)會(huì)變得相當(dāng)不準(zhǔn),當(dāng)然這種情況下對(duì)Alarm的要求也并不高,如果有特殊的要求,調(diào)用AlarmManager的setAndAllowWhileIdle()或者setExactAndAllowWhileIdle()方法就能讓定時(shí)任務(wù)正常執(zhí)行,和set()與setExact()的區(qū)別是一樣的。
到此這篇關(guān)于Android Doze模式下Alarm定時(shí)任務(wù)實(shí)現(xiàn)流程詳解的文章就介紹到這了,更多相關(guān)Android Alarm定時(shí)任務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)關(guān)機(jī)重啟的方法分享
這篇文章主要介紹了Android實(shí)現(xiàn)關(guān)機(jī)重啟的方法,需要的朋友可以參考下2014-02-02
android中設(shè)置TextView/Button 走馬燈(Marquee)效果示例
定義走馬燈(Marquee),主要在Project/res/layout/main.xml即可,下面與大家分享下具體的實(shí)現(xiàn),感興趣的朋友可以參考下哈2013-06-06
Android中利用viewflipper動(dòng)畫切換屏幕效果
這篇文章主要介紹了Android中利用viewflipper動(dòng)畫切換屏幕效果的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
Android開發(fā)VR實(shí)戰(zhàn)之播放360度全景視頻
這篇文章主要為大家詳細(xì)介紹了Android開發(fā)VR實(shí)戰(zhàn)之播放360度全景視頻,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
解析:繼承ViewGroup后的子類如何重寫onMeasure方法
本篇文章是對(duì)繼承ViewGroup后的子類如何重寫onMeasure方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
Android代碼實(shí)現(xiàn)新年賀卡動(dòng)畫示例詳解
這篇文章主要為大家介紹了Android代碼實(shí)現(xiàn)新年賀卡動(dòng)畫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Android中使用GridView實(shí)現(xiàn)仿微信圖片上傳功能(附源代碼)
由于工作要求最近在使用GridView完成圖片的批量上傳功能,我的例子當(dāng)中包含仿微信圖片上傳、拍照、本地選擇、相片裁剪等功能,如果有需要的朋友可以看一下2017-08-08
Android自定義控件實(shí)現(xiàn)時(shí)間軸
這篇文章主要為大家詳細(xì)介紹了Android自定義控件實(shí)現(xiàn)時(shí)間軸,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04

