【Android P】 JobScheduler服務(wù)源碼解析(一) —— 如何使用Job

最近Jobscheduler的使用不當(dāng)導(dǎo)致不少問題,比如定時任務(wù)不生效或者沖突。歸根結(jié)底是對Jobscheduler的使用不熟悉以及,其工作原理沒有一個系統(tǒng)性的了解。本人也曾踩坑,所以下定決心好好熟悉Jobscheduler。

概述

在android開發(fā)中經(jīng)常會有這樣的需求,開發(fā)者需要在稍后的某個時間點或者滿足某個特定的條件時去執(zhí)行某個任務(wù),例如當(dāng)設(shè)備開始充電,或者網(wǎng)絡(luò)狀態(tài)連接到wifi狀態(tài)時執(zhí)行某些推送通知的任務(wù),jobscheduler就是用來處理這類場景的任務(wù)。

Jobscheduler的android在5.0上針對于降低功耗而提出來的一種策略方案,自 Android 5.0 發(fā)布以來,JobScheduler 已成為執(zhí)行后臺工作的首選方式,其工作方式有利于用戶。應(yīng)用可以在安排作業(yè)的同時允許系統(tǒng)基于設(shè)備狀態(tài)、電源和連接情況等具體條件進(jìn)行優(yōu)化。JobScheduler 可實現(xiàn)控制和簡潔性,谷歌推出該機制是想要所有應(yīng)用在執(zhí)行后臺任務(wù)時使用它。 在之前的版本上,沒有Job 這個服務(wù),客戶端代碼如果需要實現(xiàn)類似的需求,必須要在客戶端代碼用alarm ,network, battery等服務(wù)來多次判斷條件,以實現(xiàn)此類需求,對于App 開發(fā)者來說,其實是一個比較麻煩和復(fù)雜的代碼邏輯。而job 的出現(xiàn),很大程度上把此類條件判斷邏輯放到服務(wù)端去判斷,當(dāng)所有限制條件滿足時候,客戶端觸發(fā)job

如何使用jobscheduler

應(yīng)用如果想使用JobScheduler API的話,首先需要創(chuàng)建自己需要執(zhí)行的任務(wù)信息,創(chuàng)建任務(wù)的方法在谷歌官方文檔上已經(jīng)有詳細(xì)介紹,這里只是放出一個實例:


JobInfo updateJob = new    JobInfo.Builder(UPDATEDB_JOB_ID, new ComponentName(context, TimedUpdateCleanUpDbJobService.class))

                      .setPeriodic(UPDATE_MIN_TIME)// 設(shè)置循環(huán)時間

                      .setPersisted(true)// 是否是持久化的job,如果是,開機后便會設(shè)置到系統(tǒng)中,需要RECEIVE_BOOT_COMPLETED權(quán)限

                      .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) // 需要非計費網(wǎng)絡(luò)

                      .setRequiresDeviceIdle(true)//需要設(shè)備空閑

                      .build();

JobScheduler scheduler = getSystemService(Context.JOB_SERVICE);

scheduler.scheduler(updateJob);

上面的一個任務(wù)是在開機之后執(zhí)行初始化的操作。其實并不需要延時1s,但是這里需要注意的一個點是JobScheduler所創(chuàng)建并執(zhí)行的人物必須是帶有條件限制的,不然是違背其初衷的,當(dāng)你創(chuàng)建一個任務(wù)不做任何限制條件并且直接調(diào)用 scheduler.schedule(builder.build());去執(zhí)行該任務(wù)是不可行的,會報以下的異常


java.lang.IllegalArgumentException: You're trying to build a job with no constraints, this is not allowed.

其次需要新建一個service,來繼承JobService(與DreamService類似),而且必須重寫其中的兩個方法,分別是onStartJob(JobParameters params)和onStopJob(JobParameters params);

客戶端job 的代碼書寫


public class MyJobService extends JobService {

public abstract boolean onStartJob(JobParameters params) { // 在任務(wù)開始執(zhí)行時觸發(fā)。返回false表示執(zhí)行完畢,返回true表示需要開發(fā)者自己調(diào)用jobFinished方法通知系統(tǒng)已執(zhí)行完成。

...

jobFinished();

}

public abstract boolean onStopJob(JobParameters params){  //在任務(wù)停止執(zhí)行時觸發(fā)。返回true 為重新調(diào)度,返回false 表示不會重新調(diào)度,job完全被停止了

...

}

}

當(dāng)上面創(chuàng)建任務(wù)時執(zhí)行到scheduler.schedule(builder.build()); 則開始準(zhǔn)備執(zhí)行任務(wù),一旦設(shè)置滿足條件,便會執(zhí)行到onStartJob()方法,也就是在我們的任務(wù)應(yīng)該具體事宜應(yīng)該是放在onStartJob中去做的。

當(dāng)任務(wù)執(zhí)行完畢后要調(diào)用jobFinished()來通知系統(tǒng)。當(dāng)系統(tǒng)受到一個cancel請求時會取消該任務(wù)(當(dāng)該任務(wù)未執(zhí)行將其在pending list刪除,如果該任務(wù)正在執(zhí)行則停止其任務(wù))。

使用Jobscheduler還需要到AndroidManifest.xml中添加一個service節(jié)點讓你的應(yīng)用擁有綁定和使用這個JobService的權(quán)限。


<service android:name="com.example.apuser.jobtest.JobTestService"

    android:permission="android.permission.BIND_JOB_SERVICE" />

這里需要重點注意的是:這個job service運行在你的主線程,這意味著你需要使用子線程,handler, 或者一個異步任務(wù)來運行耗時的操作以防止阻塞主線程。

常見接口解釋:


setRequiresBatteryNotLow(boolean) //是否需要電量充足

setRequiresCharging(boolean) //是否需要充電默認(rèn)false

setRequiresDeviceIdle(boolean) //是否需要設(shè)備空閑,設(shè)備空閑是指設(shè)備沒有在使用并且已經(jīng)有一段時間沒使用了

addTriggerContentUri(TriggerContentUri) //監(jiān)聽指定ContentUri,改變時才會觸發(fā)任務(wù),和周期性和持續(xù)性任務(wù)不兼容

setPeriodic(long) //是否是周期性任務(wù),intervalMillis是執(zhí)行的周期,每個周期最多執(zhí)行一次,和setMinimumLatency和setOverrideDeadline不兼容,flextime = intervaltime

setPeriodic(long intervalMillis, long flexMillis) // flex 時間為窗口時間。最小窗口時間為5分鐘()

setMinimumLatency(long) // 設(shè)置任務(wù)至少延遲多少時間才執(zhí)行

setOverrideDeadline(long) // 任務(wù)執(zhí)行的截止時間,如果到了該截止時間,其他條件不滿足也會被執(zhí)行

setRequiresStorageNotLow(boolean) //設(shè)置任務(wù)需要存儲空間充裕條件

setPriority(int) // 設(shè)置優(yōu)先級。越大優(yōu)先級越高

setPersisted(boolean) // 是否是持續(xù)性任務(wù),如果是,開機后會繼續(xù)執(zhí)行,但需要RECEIVE_BOOT_COMPLETED權(quán)限

總結(jié)

JobScheduler 雖然是在5.0上新增加的一個新服務(wù),但是從L到M,N以及最新的O 上,谷歌Android也是在重點推薦使用該功能,并且在Android O 上谷歌還推出了一套Android vitals 計劃,旨在提高Android 系統(tǒng)的功耗,性能,以及穩(wěn)定性等相關(guān)指標(biāo),在對功耗上提出來的建議便是,非精確性的定時任務(wù)建議使用Job來代替Alarm,能更加準(zhǔn)確的滿足條件的執(zhí)行你想要執(zhí)行的任務(wù)。在Android O上JobScheduler更加完善了其條件控制,加上了低存儲,低電量策略下的job運行限制,這里將在后面job服務(wù)解析中繼續(xù)提到

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容