天天看點

JobScheduler布置背景任務以及實作程序保活?

1.簡介

  在Android 5.0 提供了一套新的 

JobScheduler

 API,它允許您定義要在以後的某個時間或在指定的條件下(例如,當裝置在充電時)異步運作的作業來優化電池壽命。

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

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

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

2.關鍵類

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

  JobScheduler 管理任務:布置、撤銷、更新等.

  JobService 執行任務的服務元件.

2.1  JobScheduler

int schedule (JobInfo job)      

布置一個任務,如果任務的id相同,後者覆寫前者,如果前者正在運作,它會被打斷.

布置失敗傳回 RESULT_FAILURE ,可能job的參數有錯誤

布置成功傳回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、setOverrideDeadline、setPeriodic沖突。

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_NONE

NETWORK_TYPE_ANY

NETWORK_TYPE_UNMETERED

NETWORK_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