鍍金池/ 教程/ Android/ 在Android Lollipop上使用JobScheduler API
原文鏈接
Issue #185
Issue #181
Issue #161
Issue #192
Issue #174
Issue #190
RecyclerView FastScroll – Part 2
僅作為Android 調(diào)試模式工具的Stetho
Issue #150
Issue #167
Issue #180
Issue #151
Issue #188
Issue #159
Issue #189
Issue #160
Issue #168
Issue #146
Issue #173
Issue #198
Issue #179
延期的共享元素轉(zhuǎn)換(3b)
Yahnac:RxJava Firebase&內(nèi)容提供
Issue #162
游戲性能:規(guī)劃限定條件
分析清單:測(cè)量和尋找哪些方面
Issue #148
Issue #166
Issue #158
Issue #178
Issue #193
Issue #145
Issue #170
Issue #169
Issue #196
Issue #186
Issue #172
Issue #171
附加Android工件和Gradle的檔案
Issue #147
自定義顏色范圍
根據(jù) Material 設(shè)計(jì)導(dǎo)航制圖工具樣式
Issue #187
Issue #184
Issue #175
在Android Lollipop上使用JobScheduler API
Android性能案例追蹤研究
使用安卓Wear API創(chuàng)建watchface—第2部分
在谷歌市場(chǎng)上創(chuàng)造更好的用戶體驗(yàn)
映射與包的神秘關(guān)系
Issue #165
用Robolectric進(jìn)行參數(shù)化測(cè)試
Issue #155
Issue #149
MVC / MVP中的M -模型
歡迎為 Android 和 iOS 嵌入 API
Issue #164
Android UI 自動(dòng)化測(cè)試
Issue #182
Issue #191
Issue #183
Issue #163
Issue #157
響應(yīng)式編程(Reactive Programming)介紹
Issue #197
原文鏈接
Issue #153
Issue #152
Issue #176
原文地址
Android Material 支持庫:Electric Boogaloo的提示與技巧
Issue #156
Issue #154
Android的模糊視圖
Issue #194
Issue #177
Issue #195
針對(duì)Jenkins的谷歌商店安卓出版插件

在Android Lollipop上使用JobScheduler API

在本教程中,您將學(xué)習(xí)如何使用 JobScheduler API適用于 Android Lollipop。當(dāng)滿足一定的條件時(shí),該JobScheduler API允許開發(fā)者創(chuàng)建后臺(tái)執(zhí)行的工作。

介紹

當(dāng)使用Android進(jìn)行工作時(shí),會(huì)遇到這樣的情況——你會(huì)想在將來的某個(gè)時(shí)間或在一定條件下運(yùn)行任務(wù),例如當(dāng)一個(gè)設(shè)備接入電源或連接到Wi-Fi網(wǎng)絡(luò)。值得慶幸的是有API21,因?yàn)锳ndroid Lollipop而被大多數(shù)人所知,谷歌已經(jīng)提供了被稱為JobScheduler API的新組件來處理這樣的情況。

當(dāng)一組預(yù)定義的條件得到滿足時(shí),JobScheduler API的應(yīng)用程序執(zhí)行一項(xiàng)操作。不像 AlarmManager 類,該時(shí)間測(cè)定時(shí)不準(zhǔn)確的。此外,該 JobScheduler API 能夠一同批處理各種工作。這允許應(yīng)用程序執(zhí)行特定的任務(wù),同時(shí)考慮設(shè)備的電池在定時(shí)控制上的成本。

在這篇文章中,通過使用JobScheduler API和 jobservice 類在一個(gè)Android應(yīng)用程序中運(yùn)行一個(gè)簡(jiǎn)單的后臺(tái)任務(wù),您將學(xué)習(xí)更多關(guān)于 JobScheduler API和 jobservice 類方面的知識(shí)。在本教程中的代碼可以在 GitHub上獲得。

1、創(chuàng)建工作服務(wù)

開始,你會(huì)想使用最小所需的API 21創(chuàng)建一個(gè)新的Android項(xiàng)目,因?yàn)樵贏ndroid的最新版本中已經(jīng)增加了JobScheduler API ,在寫作的時(shí)候, 它沒有通過支持庫向后兼容。

假設(shè)你使用的是Android Studio,在你點(diǎn)擊完新項(xiàng)目按鈕后,你會(huì)看到一個(gè)基本的“Hello World”應(yīng)用。你要進(jìn)行這個(gè)項(xiàng)目的第一步是創(chuàng)建一個(gè)新的Java類。為了讓事情簡(jiǎn)單化,命名它為JobSchedulerService ,并擴(kuò)展jobservice 類,這就需要?jiǎng)?chuàng)建兩個(gè)方法:onStartJob(JobParameters params)onStopJob(JobParameters params)。

    public class JobSchedulerService extends JobService {
    @Override
    public boolean onStartJob(JobParameters params) {

        return false;
    }

    @Override
    public boolean onStopJob(JobParameters params) {

        return false;
    }

    }

當(dāng)你開始你的任務(wù)時(shí),onstartjob(jobparameters params) 是你必須使用的方法,因?yàn)樗窍到y(tǒng)用來觸發(fā)已經(jīng)安排的工作的。正如你可以看到,該方法返回一個(gè)布爾值。如果返回值是false,該系統(tǒng)假定任何任務(wù)運(yùn)行不需要很長(zhǎng)時(shí)間并且到方法返回時(shí)已經(jīng)完成。如果返回值是true,那么系統(tǒng)假設(shè)任務(wù)是需要一些時(shí)間并且負(fù)擔(dān)落到你(開發(fā)者)的身上,當(dāng)給定的任務(wù)完成時(shí)通過調(diào)用jobFinished(JobParameters params, boolean needsRescheduled)告知系統(tǒng)。

當(dāng)收到取消請(qǐng)求時(shí),onStopJob(JobParameters params) 是系統(tǒng)用來取消掛起的任務(wù)的。重要的是要注意到,如果onStartJob(JobParameters params)返回 false,當(dāng)取消請(qǐng)求被接收時(shí),該系統(tǒng)假定沒有目前運(yùn)行的工作。換句話說,它根本就不調(diào)用onStopJob(JobParameters params)

有一點(diǎn)要注意的是,工作服務(wù)在你的應(yīng)用程序的主線程上運(yùn)行。這意味著,你必須使用另一個(gè)線程處理程序,或運(yùn)行時(shí)間更長(zhǎng)的任務(wù)異步任務(wù)以不阻塞主線程。由于多線程技術(shù)超出本教程的范圍,讓我們保持簡(jiǎn)單和實(shí)現(xiàn)處理程序來運(yùn)行在JobSchedulerService類中的任務(wù)。

    private Handler mJobHandler = new Handler( new Handler.Callback() {
    @Override
    public boolean handleMessage( Message msg ) {
        Toast.makeText( getApplicationContext(), 
            "JobService task running", Toast.LENGTH_SHORT )
            .show();
        jobFinished( (JobParameters) msg.obj, false );
        return true;
    }
    } );

在處理程序中,你執(zhí)行handleMessage(Message msg)方法(Handler實(shí)例的一部分),并使用它運(yùn)行你的任務(wù)的邏輯。在此情況下,讓事情簡(jiǎn)單化,從應(yīng)用程序發(fā)送一個(gè)Toast信息,雖然這是在那里你可以像同步數(shù)據(jù)一樣給出你的邏輯。

當(dāng)任務(wù)完成時(shí),你需要調(diào)用jobFinished(JobParameters params, boolean needsRescheduled)讓系統(tǒng)知道你完成了那項(xiàng)任務(wù),它可以開始排隊(duì)接下來的操作。如果你不這樣做,你的工作將只運(yùn)行一次,你的應(yīng)用程序?qū)⒉槐辉试S執(zhí)行額外的工作。

onStartJob(JobParameters params)方法中,jobFinished(JobParameters params, boolean needsRescheduled) 的兩個(gè)參數(shù)值是JobParameters傳遞到JobService類,一個(gè)布爾值讓系統(tǒng)知道是否需要根據(jù)工作的最初要求重新編排工作。這個(gè)布爾值對(duì)于理解是非常有用的,因?yàn)樗鼛椭懔私馊绾翁幚碛捎谄渌麊栴}(如一個(gè)失敗的網(wǎng)絡(luò)電話)而導(dǎo)致你的任務(wù)無法完成的情況。

隨著Handler程序?qū)嵗膭?chuàng)建,你可以繼續(xù)并開始執(zhí)行onStartJob(JobParameters params)onStopJob(JobParameters params)方法來控制你的任務(wù)。你會(huì)發(fā)現(xiàn),在下面的代碼片段中,onStartJob(JobParameters params)方法的返回值為true。這是因?yàn)?,你要使用一個(gè)Handler 程序?qū)嵗齺砜刂颇愕牟僮?,這意味著相比onStartJob(JobParameters params)方法它可能需要更長(zhǎng)的時(shí)間來完成。通過返回true,你讓應(yīng)用程序知道,你將手動(dòng)調(diào)用jobFinished(JobParameters params, boolean needsRescheduled)方法。你也會(huì)注意到,數(shù)字1被傳遞到Handler示例。這是相關(guān)引用工作中你將用到的標(biāo)識(shí)符。

    @Override
    public boolean onStartJob(JobParameters params) {
    mJobHandler.sendMessage( Message.obtain( mJobHandler, 1, params ) );
    return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
    mJobHandler.removeMessages( 1 );
    return false;
    }

一旦你使用Java部分的JobSchedulerService類完成,你需要研究AndroidManifest.xml,并增加服務(wù)節(jié)點(diǎn),因此,你的應(yīng)用程序有權(quán)限綁定和使用JobService類。

<service android:name=".JobSchedulerService"
    android:permission="android.permission.BIND_JOB_SERVICE" />

2、創(chuàng)建工作計(jì)劃

隨著JobSchedulerService 類完成,我們可以開始考慮你的應(yīng)用程序?qū)⑷绾闻cJobScheduler API相互作用。你需要做的第一件事就是創(chuàng)建一個(gè)JobScheduler對(duì)象,在示例代碼中調(diào)用mJobScheduler ,通過獲得一個(gè)系統(tǒng)服務(wù)的實(shí)例JOB_SCHEDULER_SERVICE來初始化它。在示例應(yīng)用程序中,這是在MainActivity 類中完成的。

mJobScheduler = (JobScheduler) 
    getSystemService( Context.JOB_SCHEDULER_SERVICE );

當(dāng)你想創(chuàng)建你的計(jì)劃任務(wù)時(shí),你可以使用來JobInfo.Builder創(chuàng)建一個(gè)JobInfo對(duì)象,字符指針傳遞到你的服務(wù)中。為了創(chuàng)建一個(gè)JobInfo對(duì)象,JobInfo.Builder 接受兩個(gè)參數(shù)。第一個(gè)參數(shù)是你將運(yùn)行工作的標(biāo)識(shí)符,第二個(gè)參數(shù)是你將與JobScheduler API.一同使用的服務(wù)的組件名稱。

JobInfo.Builder builder = new JobInfo.Builder( 1,
        new ComponentName( getPackageName(), 
            JobSchedulerService.class.getName() ) );

當(dāng)你的工作將執(zhí)行時(shí),這個(gè)編輯器可以讓你設(shè)置許多不同的控制選項(xiàng)。下面的代碼片段顯示了你如何設(shè)置你的任務(wù)每三秒定期運(yùn)行一次。

builder.setPeriodic( 3000 );

其他方法包括:

  • setMinimumLatency(long minLatencyMillis):這會(huì)使你的工作不啟動(dòng)直到規(guī)定的毫秒數(shù)已經(jīng)過去了。這是與setPeriodic(long time)不兼容的,并且如果同時(shí)使用這兩個(gè)函數(shù)將會(huì)導(dǎo)致拋出異常。

  • setOverrideDeadline(long maxExecutionDelayMillis):這將設(shè)置你的工作期限。即使是無法滿足其他要求,你的任務(wù)將約在規(guī)定的時(shí)間已經(jīng)過去時(shí)開始執(zhí)行。類似于setMinimumLatency(long time),這個(gè)函數(shù)是與 setPeriodic(long time) 互相排斥的,并且如果同時(shí)使用這兩個(gè)函數(shù),將會(huì)導(dǎo)致拋出異常。

setPersisted(boolean isPersisted):這個(gè)函數(shù)告訴系統(tǒng),在設(shè)備重新啟動(dòng)后,你的任務(wù)是否應(yīng)該繼續(xù)存在。

  • setRequiredNetworkType(int networkType):這個(gè)函數(shù)會(huì)告訴你工作,只有在設(shè)備處于一種特定的網(wǎng)絡(luò)中時(shí),它才啟動(dòng)。它的默認(rèn)值是JobInfo.NETWORK_TYPE_NONE,這就意味著,無論是否有網(wǎng)絡(luò)連接,該任務(wù)均可以運(yùn)行。另外兩個(gè)可用的類型是JobInfo.NETWORK_TYPE_ANY,這需要某種類型的網(wǎng)絡(luò)連接可用,工作才可以運(yùn)行;以及JobInfo.NETWORK_TYPE_UNMETERED,這就要求設(shè)備在非蜂窩網(wǎng)絡(luò)中。

  • setRequiresCharging(boolean requiresCharging):使用這個(gè)函數(shù)會(huì)告訴你的應(yīng)用程序,除非設(shè)備開始充電,否則工作不會(huì)啟動(dòng)。

  • setRequiresDeviceIdle(boolean requiresDeviceIdle):這會(huì)告知你的工作不會(huì)啟動(dòng),除非用戶不使用他們的設(shè)備,并且他們已經(jīng)有一段時(shí)間沒有使用它。

重要的是要注意到,setRequiredNetworkType(int networkType)、setRequiresCharging(boolean requireCharging)setRequiresDeviceIdle(boolean requireIdle)可能會(huì)導(dǎo)致你的工作永遠(yuǎn)不啟動(dòng),除非setOverrideDeadline(long time)還設(shè)置允許即使不符合條件的情況下,你的工作也可以運(yùn)行。一旦規(guī)定優(yōu)先條件,你可以創(chuàng)建JobInfo對(duì)象,并發(fā)送它到你的JobScheduler對(duì)象,如下所示。

if( mJobScheduler.schedule( builder.build() ) <= 0 ) {
    //If something goes wrong
}

你會(huì)注意到,schedule操作返回一個(gè)整數(shù)。如果schedule 失敗,它將返回一個(gè)為零或更少的值,對(duì)應(yīng)于一個(gè)錯(cuò)誤代碼。否則,它將返回在JobInfo.Builder中定義的作業(yè)標(biāo)識(shí)符。

如果你的應(yīng)用程序需要你停止特定或所有工作,你可以通過對(duì)JobScheduler 對(duì)象調(diào)用cancel(int jobId)cancelAll()實(shí)現(xiàn)。

mJobScheduler.cancelAll();

你現(xiàn)在應(yīng)該能夠使用JobScheduler API以及你自己的應(yīng)用程序進(jìn)行批處理工作和運(yùn)行后臺(tái)操作。

結(jié)論

在這篇文章中,你已經(jīng)學(xué)會(huì)了如何實(shí)現(xiàn)一個(gè)子類,使用一個(gè)Handler對(duì)象來運(yùn)行你的應(yīng)用程序的后臺(tái)任務(wù)。你也學(xué)會(huì)了如何使用JobInfo.Builder來設(shè)置你的服務(wù)應(yīng)該運(yùn)行時(shí)的要求。通過這些,你應(yīng)該能夠在留意功率消耗的同時(shí),提高你自己的應(yīng)用程序操作。

上一篇:Issue #181下一篇:Issue #173