JobScheduler佈置後臺任務以及實現進程保活?

1.簡介

  在Android 5.0 提供了一套新的 JobScheduler API,它容許您定義要在之後的某個時間或在指定的條件下(例如,當設備在充電時)異步運行的做業來優化電池壽命。android

  https://developer.android.com/reference/android/app/job/package-summarygit

  https://developer.android.com/reference/android/app/job/JobSchedulerapi

  https://developer.android.com/reference/android/app/job/JobService網絡

2.關鍵類

  JobInfo 描述任務,包含各個參數.app

  JobScheduler 管理任務:佈置、撤銷、更新等.異步

  JobService 執行任務的服務組件.ide

2.1  JobScheduler

int schedule (JobInfo job)

佈置一個任務,若是任務的id相同,後者覆蓋前者,若是前者正在運行,它會被打斷.fetch

佈置失敗返回 RESULT_FAILURE ,可能job的參數有錯誤flex

佈置成功返回RESULT_SUCCESS優化

void cancel (int jobId)

撤銷指定id的任務,若是任務正在運行,它馬上中止.因爲是用戶手動撤銷,因此任務的 onStopJob 的返回值沒

有意義,被忽略.

void cancelAll ()
撤銷全部任務. 
int enqueue (JobInfo job,JobWorkItem work)

    佈置任務和工做內容,若是該任務不存在,則添加一個新的任務.若是該任務正在運行,會被中斷並以新的內容

添加到隊列中.

    若是jobInfo使用JobInfo.Builder.setExtras(PersistableBundle)等添加了附加數據,要保持它們一致,

使用JobInfo.Builder.setClipData(ClipData, int)添加數據後的任務永遠被視爲新任務,即便ClipData相同.

JobInfo getPendingJob (int jobId)
 根據id查找任務.
List<JobInfo> getAllPendingJobs ()
 返回當前應用佈置的全部任務.(包括已經啓動的和等待中的)

2.2 JobInfo及JobInfo.Builder

  JobInfo.Builder 構造jobinfo,設置任務的各項參數.如網絡類型,運行週期等.

JobInfo build () 生成一個JobInfo對象
setBackoffCriteria (long initialBackoffMillis,int backoffPolicy)

設置回退策略,與setRequiresDeviceIdle(boolean)衝突.

initialBackoffMillis 是失敗後的等待時間,

backoffPolicy 是回退方式,有BACKOFF_POLICY_LINEAR BACKOFF_POLICY_EXPONENTIAL 兩種.

setEstimatedNetworkBytes (long downloadBytes, long uploadBytes)

預算任務網絡鏈接時使用的字節數,若是知道具體字節最好,若是不是固定的可用JobInfo.NETWORK_BYTES_UNKNOWN

setExtras (PersistableBundle extras) 設置額外數據, PersistableBundle 裏要放基本類型的數據.
setImportantWhileForeground (boolean importantWhileForeground) 是否臨時加入白名單,在變成前臺重要任務.默認false.
setMinimumLatency (long minLatencyMillis) 設置最小延遲時間,與 setPeriodic 衝突.
setOverrideDeadline (long maxExecutionDelayMillis) 最後執行期限,條件不知足也執行.與 setPeriodic 衝突.
setPeriodic (long intervalMillis) 設置任務執行週期,單位毫秒.
setPeriodic (long intervalMillis, long flexMillis)
setPersisted (boolean isPersisted) 設置是持久任務,開機後仍然有效.
setPrefetch (boolean prefetch) 設置任務是否預讀本地內容,若是是,則系統會放寬網絡類型約束.
setRequiredNetwork (NetworkRequest networkRequest)

設置任務使用的網絡類型,若是無聯網,不要調用這個方法,默認是null,這是一個很是嚴厲的約束,若是網絡類型不知足,

任務不會被執行.這個方法有重載,只調用其中一個就可,重複調用後面的會覆蓋前面的.

經常使用的類型:

NETWORK_TYPE_NONENETWORK_TYPE_ANYNETWORK_TYPE_UNMETEREDNETWORK_TYPE_NOT_ROAMING or NETWORK_TYPE_METERED

setRequiredNetworkType (int networkType)
setRequiresBatteryNotLow (boolean batteryNotLow)  是否只在非低電量狀況下運行,true表示在非低電量運行,默認false.
setRequiresCharging (boolean requiresCharging) 設置是否只在充電時運行.默認fase.注意系統在特別繁忙時,可能忽略usb充電,這時任務不會被執行.
setRequiresDeviceIdle (boolean requiresDeviceIdle) 在空閒時運行,默認fase,這裏的空閒狀態是個寬泛的系統定義,一般指在沒有應用與用戶交互時.
setRequiresStorageNotLow (boolean storageNotLow) 非低存儲空間時運行.默認false.
setTransientExtras (Bundle extras) 給任務添加臨時數據,與setPersisted衝突.
addTriggerContentUri (JobInfo.TriggerContentUri uri)

添加內容觸發器,監聽某個內容,它變化後才執行這個任務,uri指定要被ContentObserver監聽的內容,與setPeriodic(long) or setPersisted(boolean)衝突.如:

1       JobInfo.Builder builder = new JobInfo.Builder(JobIds.PHOTOS_CONTENT_JOB,
2                 new ComponentName("com.example.android.apis", PhotosContentJob.class.getName()));
3         // Look for specific changes to images in the provider.
4         builder.addTriggerContentUri(new JobInfo.TriggerContentUri(
5                 MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
6                 JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
7         // Also look for general reports of changes in the overall provider.
8         builder.addTriggerContentUri(new JobInfo.TriggerContentUri(MEDIA_URI, 0));
9         JOB_INFO = builder.build();
setTriggerContentMaxDelay (long durationMs)

設置內容變化到任務被佈置間的最大延遲(毫秒).

setTriggerContentUpdateDelay (long durationMs)

設置內容變化到任務被佈置間的延遲(毫秒). 

If there are more changes during that time,the delay will be reset to start at the time of the most recent change.

 
  JobInfo經常使用的方法是一些get方法,如getRequiredNetwork () , getBackoffPolicy () , isPeriodic () 等.

 

2.3 JobService

  以startService方式啓動服務,其中幾個重要方法:

boolean onStartJob (JobParameters params)

    當scheduler添加調度任務後,任務開始執行時產生這個回調,默認在主線程.

    注意這個參數,它裏面保存了傳來的數據.一般要保存它,當任務完成時,手動調用jobFinished

時使用.

    返回true表示任務在手動調用jobFinished結束或系統條件不知足而中止前一直在活躍狀態,

服務斷續運行,這時系統爲這個任務保留wakelock鎖.直到jobFinished或onStopJob調用.

    返回false表示任務正常結束,這時系統會釋放與這個任務關聯的wakelock鎖.

    若是任務簡短而且同步的那麼應該返回false,若是異步的應用在任務完成後手動調用jobFinished

boolean onStopJob (JobParameters params)

    來自系統的結束任務通知.一般在任務執行條件不能被知足時產生這個回調,如:當你在構造任務時

指定了網絡條件是wifi,在任務執行期間你關掉了wifi.

    注意:必定要處理這條信息,如釋放不用的資源,不然應用會產生異常行爲.

    返回true表示你還但願在按照構造裏指定的重試策略重試,當這個任務裏有多條工做內容時,

要返回true,表示這個任務須要從新佈置執行未完成的工做..

    返回false表示結束不重試,可是無論返回什麼,當前這個任務必需中止.

void jobFinished (JobParameters params,
boolean wantsReschedule)

    當任務完成後,手動調用這個方法通知系統任務完成,而後系統釋放相應的wakelock鎖,

第1個參數是 onStartJob 傳來的參數.

    第2個參數表示是否嘗試回滾策略,若是是不得以要執行的這個方法,true表示按構造時指定的回滾

策略從新安排.

    默認的回滾策略不會讓任務在系統睡眠期間執行,而只是把它從新添加到任務隊列中,在系統修整維護期間

才執行這個任務.

3.實現進程保活?不可靠!

  若是想用JobService實現進程保活,那麼就得設置任務爲週期任務,有幾個問題,證實用它實現進程保活不可靠.

  • 在最近應用列表點所有清除後,進程會被殺死,週期任務被中止.
  • 在api小於24時,不支持週期任務,只能本身用timer實現,同時要求JobService這個服務組件開啓重啓功能,可是這個功能不在在全部系統上都能順利進行,如在emui,和miui上都被拒絕.emui:
    6-11 15:47:42.292 1494-13224/? I/HwPFWLogger: AppAutoStartupPolicy:prevent scheduleRestart service of package com.example.android.jobscheduler, serviceInfo com.example.android.jobscheduler.service.MyJobService
    06-11 15:48:12.311 1494-1494/? I/HwPFWLogger: AppAutoStartupPolicy:prevent start package com.example.android.jobscheduler, serviceInfo com.example.android.jobscheduler.service.MyJobService by callerPid 1494, callerUid 1000, scene:jobService

    miui:

    06-11 16:45:05.849 1432-1443/system_process I/ActivityManager:   Force stopping service ServiceRecord{bf9fd5e u0 com.example.android.jobscheduler/.service.MyJobService}
    06-11 16:45:06.147 1432-1447/system_process I/AutoStartManagerService: MIUILOG- Reject service :Intent { cmp=com.example.android.jobscheduler/.service.MyJobService } userId : 0 uid : 10127
  • 而api大於23時,最小週期是15分鐘,這對於實時任務來講又有點長.

4.示例

4.1 相關權限

經常使用權限:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 

必用權限:

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

4.2 下載代碼

  https://gitee.com/xi/JobService.git

相關文章
相關標籤/搜索