在這篇文章中,你會學習到在Android 5.0中怎樣使用JobScheduler API。
JobScheduler API同意開發人員在符合某些條件時創建運行在后台的任務。
介紹
在Android開發中,會存在這么些場景 : 你須要在稍后的某個時間點或者當滿足某個特定的條件時運行一個任務,比如當設備接通電源適配器或者連接到WIFI。幸運的是在API 21 ( Android 5.0。即Lollipop )中,google提供了一個新叫做JobScheduler API的組件來處理這種場景。
當一系列預置的條件被滿足時,JobScheduler API為你的應用運行一個操作。與AlarmManager不同的是這個運行時間是不確定的。除此之外。JobScheduler API同意同一時候運行多個任務。
這同意你的應用運行某些指定的任務時不須要考慮時機控制引起的電池消耗。
這篇文章中,你會學到關於JobScheduler API很多其它的東西以及在你的應用中用於運行一個簡單的后台任務的JobService,這篇文章中所展示的代碼你都能夠在github中找到。
1. 創建Job Service
首先,你須要創建一個API最低為21的Android項目,因此JobScheduler是近期的版本號才加入Android的,在寫這篇文章的時候,它還沒有兼容庫支持。
假定你使用的是Android Studio,當你點擊了創建項目的完成button之后,你會得到一個”hello world”的應用骨架。你要做的第一步就是創建一個新的java類。
為了簡單起見。讓我們創建一個繼承自JobService且名字為JobSchedulerService的類,這個類必須實現兩個方法。各自是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; } }
當任務開始時會運行onStartJob(JobParameters params)
方法,由於這是系統用來觸發已經被運行的任務。
正如你所示,這種方法返回一個boolean值。假設返回值是false,系統假設這種方法返回時任務已經運行完成。假設返回值是true,那么系統假定這個任務正要被運行,運行任務的重擔就落在了你的肩上。
當任務運行完成時你須要調用jobFinished(JobParameters params, boolean needsRescheduled)
來通知系統。
當系統接收到一個取消請求時,系統會調用onStopJob(JobParameters params)
方法取消正在等待運行的任務。非常重要的一點是假設onStartJob(JobParameters params)
返回false,那么系統假定在接收到一個取消請求時已經沒有正在運行的任務。換句話說,onStopJob(JobParameters params)
在這種情況下不會被調用。
須要注意的是這個job service運行在你的主線程,這意味着你須要使用子線程,handler, 或者一個異步任務來運行耗時的操作以防止堵塞主線程。
由於多線程技術已經超出了我們這篇文章的范圍。讓我們簡單實現一個Handlder來運行我們在JobSchedulerService定義的任務吧。
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; } } );
在Handler中,你須要實現handleMessage(Message msg)
方法來處理你的任務邏輯。在這個樣例中。我們盡量保證樣例簡單,因此我們僅僅在handleMessage(Message msg)
中顯示了一個Toast。這里就是你要寫你的任務邏輯( 耗時操作 )的地方,比方同步數據等。
當任務運行完成之后,你須要調用jobFinished(JobParameters params, boolean needsRescheduled)
來讓系統知道這個任務已經結束,系統能夠將下一個任務加入到隊列中。假設你沒有調用jobFinished(JobParameters params, boolean needsRescheduled)
,你的任務僅僅會運行一次,而應用中的其它任務就不會被運行。
jobFinished(JobParameters params, boolean needsRescheduled)
的兩個參數中的params參數是從JobService的onStartJob(JobParameters params)
的params傳遞過來的。needsRescheduled參數是讓系統知道這個任務是否應該在最處的條件下被反復運行。這個boolean值非常實用,由於它指明了你怎樣處理由於其它原因導致任務運行失敗的情況,比如一個失敗的網絡請求調用。
創建了Handler實例之后。你就能夠實現onStartJob(JobParameters params)
和onStopJob(JobParameters params)
方法來控制你的任務了。
你可能已經注意到在以下的代碼片段中onStartJob(JobParameters params)
返回了true。這是由於你要通過Handler實例來控制你的操作,
這意味着Handler的handleMessage方法的運行時間可能比
onStartJob(JobParameters params)更長。
返回true,你會讓系統知道你會手動地調用jobFinished(JobParameters params, boolean needsRescheduled)
方法。
@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部分做了上述工作之后,你須要到AndroidManifest.xml中加入一個service節點讓你的應用擁有綁定和使用這個JobService的權限。
<service android:name=".JobSchedulerService" android:permission="android.permission.BIND_JOB_SERVICE" />
2. 創建一個JobScheduler對象
隨着JobSchedulerService構建完成,我們能夠開始研究你的應用怎樣與JobScheduler API進行交互了。第一件要做的事就是你須要創建一個JobScheduler對象,在實例代碼的MainActivity中我們通過getSystemService( Context.JOB_SCHEDULER_SERVICE )
初始化了一個叫做mJobScheduler的JobScheduler對象。
mJobScheduler = (JobScheduler)
getSystemService( Context.JOB_SCHEDULER_SERVICE );
當你想創建定時任務時。你能夠使用JobInfo.Builder
來構建一個JobInfo對象,然后傳遞給你的Service。JobInfo.Builder接收兩個參數。第一個參數是你要運行的任務的標識符。第二個是這個Service組件的類名。
JobInfo.Builder builder = new JobInfo.Builder( 1, new ComponentName( getPackageName(), JobSchedulerService.class.getName() ) );
這個builder同意你設置非常多不同的選項來控制任務的運行。
以下的代碼片段就是展示了怎樣設置以使得你的任務能夠每隔三秒運行一次。
builder.setPeriodic( 3000 );
其它設置方法 :
- setMinimumLatency(long minLatencyMillis): 這個函數能讓你設置任務的延遲運行時間(單位是毫秒),這個函數與
setPeriodic(long time)
方法不兼容,假設這兩個方法同一時候調用了就會引起異常; - setOverrideDeadline(long maxExecutionDelayMillis):
這種方法讓你能夠設置任務最晚的延遲時間。假設到了規定的時間時其它條件還未滿足。你的任務也會被啟動。與setMinimumLatency(long time)
一樣,這種方法也會與setPeriodic(long time)
,同一時候調用這兩個方法會引發異常。 - setPersisted(boolean isPersisted):
這種方法告訴系統當你的設備重新啟動之后你的任務是否還要繼續運行。 - setRequiredNetworkType(int networkType):
這種方法讓你這個任務僅僅有在滿足指定的網絡條件時才會被運行。默認條件是JobInfo.NETWORK_TYPE_NONE。這意味着無論是否有網絡這個任務都會被運行。另外兩個可選類型。一種是JobInfo.NETWORK_TYPE_ANY,它表明須要隨意一種網絡才使得任務能夠運行。
還有一種是JobInfo.NETWORK_TYPE_UNMETERED,它表示設備不是蜂窩網絡( 比方在WIFI連接時 )時任務才會被運行。
- setRequiresCharging(boolean requiresCharging):
這種方法告訴你的應用,僅僅有當設備在充電時這個任務才會被運行。 - setRequiresDeviceIdle(boolean requiresDeviceIdle):
這種方法告訴你的任務僅僅有當用戶沒有在使用該設備且有一段時間沒有使用時才會啟動該任務。
須要注意的是setRequiredNetworkType(int networkType)
, setRequiresCharging(boolean requireCharging)
and setRequiresDeviceIdle(boolean requireIdle)
者幾個方法可能會使得你的任務無法運行,除非調用setOverrideDeadline(long time)
設置了最大延遲時間,使得你的任務在為滿足條件的情況下也會被運行。
一旦你預置的條件被設置,你就能夠構建一個JobInfo對象。然后通過例如以下所示的代碼將它發送到你的JobScheduler中。
if( mJobScheduler.schedule( builder.build() ) <= 0 ) { //If something goes wrong }
你可能注意到了。這個schedule方法會返回一個整型。假設schedule方法失敗了。它會返回一個小於0的錯誤碼。否則它會我們在JobInfo.Builder中定義的標識id。
假設你的應用想停止某個任務。你能夠調用JobScheduler對象的cancel(int jobId)
來實現;假設你想取消全部的任務。你能夠調用JobScheduler對象的cancelAll()
來實現。
mJobScheduler.cancelAll();
到了這里,你如今應該已經知道怎樣在你的應用中使用JobScheduler API來運行批量任務和后台操作了。
結論
這篇文章中,你學會了怎么實現一個使用Handler對象來運行后台任務的JobService子類,你也學會了怎樣使用JobInfo.Builder來設置JobService。
掌握了這些之后,你能夠在降低資源消耗的同一時候提升應用的效率。