文章目錄
- 一、JobServiceContext 引入
- 二、JobServiceContext 源碼分析
- 三、使用者在應用層如何使用 JobScheduler
- 四、使用者送出任務
- 五、廣播接收者監聽廣播觸發 JobService 執行任務
推薦代碼檢視網站 :
- https://www.androidos.net.cn/sourcecode ( 推薦 )
- http://androidxref.com/
一、JobServiceContext 引入
上一篇部落格 【Android 電量優化】JobScheduler 相關源碼分析 ( JobSchedulerService 源碼分析 | 任務檢查 | 任務執行 ) 中在 JobSchedulerService 中的 assignJobsToContextsLocked 方法中 , 有如下代碼 :
// /frameworks/base/services/core/java/com/android/server/job/JobSchedulerService.java 中的代碼
mActiveServices.get(i).executeRunnableJob(pendingJob)
mActiveServices 就是 JobServiceContext 集合 , 上述方法調用了 JobServiceContext 的 executeRunnableJob 方法 , 目的是要執行傳入的 pendingJob 任務 ;
二、JobServiceContext 源碼分析
在 JobServiceContext 類的 executeRunnableJob 方法的作用 : 該方法傳遞一個 Job 任務給 JobServiceContext 執行 , 調用者需要先檢查如下兩個條件 :
- 目前是否有運作中的任務 , getRunningJob() 必須為空 ;
- 同時還需要確定該 JobServiceContext 上下文是有效的 ;
在該方法中建立了 Intent , 并使用該意圖綁定了一個服務 , 這個服務就是建立 JobInfo 時 , 開發者自定義的 JobService 服務 , 送出任務時需要送出該服務 ;
綁定服務 , 執行 JobService 服務中的 onStartJob 方法
截止到此處 , 基本 JobScheduler 整個運作的閉環 , 進行了簡單的源碼分析 , 沒有深入分析 , 僅限于簡單了解 ;
public class JobServiceContext extends IJobCallback.Stub implements ServiceConnection {
// ...
/**
* 該方法傳遞一個 Job 任務給 JobServiceContext 執行 .
* 調用者需要先檢查目前是否有運作中的任務 , getRunningJob() 為空 ;
* 并且確定該 JobServiceContext 上下文是有效的 ;
*
* @param 将要運作的任務的狀态 ;
* @return True 如果該任務是有效的 , 并且正在執行 ;
* False 如果該任務不能被執行 ;
*/
boolean executeRunnableJob(JobStatus job) {
synchronized (mLock) {
// ...
// 此處建立了 Intent , 并使用該意圖綁定了一個服務
final Intent intent = new Intent().setComponent(job.getServiceComponent());
// 使用上述意圖 Intent 綁定服務
// 這個服務就是建立 JobInfo 時 , 開發者自定義的 JobService 服務 , 送出任務時需要送出該服務
boolean binding = mContext.bindServiceAsUser(intent, this,
Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND,
new UserHandle(job.getUserId()));
// ...
try {
// 啟動服務 , 會執行 JobService 服務中的 onStartJob 方法
mBatteryStats.noteJobStart(job.getBatteryName(), job.getSourceUid());
} catch (RemoteException e) {
// Whatever.
}
mJobPackageTracker.noteActive(job);
mAvailable = false;
return true;
}
}
}
該代碼路徑為 /frameworks/base/services/core/java/com/android/server/job/JobServiceContext.java , 點選連結可跳轉檢視完整源碼 ;
三、使用者在應用層如何使用 JobScheduler
先講解使用者在應用層如何使用 JobScheduler :
在 【Android 電量優化】電量優化 ( JobScheduler | JobService | AsyncTask ) 部落格中 , 講解了 JobScheduler 如何使用 ;
- 擷取服務 : 首先擷取系統的 JobScheduler 服務 , 就是之前分析的 JobSchedulerService 類 ;
- 建立任務 : 建立 JobInfo 任務資訊 , 使用 JobScheduler 送出該任務 ; mJobScheduler.schedule(jobInfo) ;
- 自定義 JobService : 開發者在應用中自定義 JobService 服務 ;
- 服務執行 : 系統會在合适的時間調用 JobService 服務的 boolean onStartJob(JobParameters params) 方法 ;
其中涉及到兩個入口 , 一個是使用者送出任務 , 另一個是系統在某個時間回調 JobService 服務中的開始執行任務方法 ;
主要針對上述兩個入口進行分析 ;
使用者送出任務的驅動事件是開發者寫的送出任務的代碼 ;
系統回調 JobService 服務的驅動事件 , 是使用者對手機的操作 , 如插拔電源線 , 切換 WIFI 網絡等操作 , 這些操作觸發廣播 , 相應廣播接收者收到這些廣播 , 就會觸發一系列相關的操作 ;
四、使用者送出任務
分析使用者送出任務 :
【Android 電量優化】JobScheduler 相關源碼分析 ( JobSchedulerService 源碼分析 | Android 源碼線上網址推薦 ) 部落格中講解了如下内容 :
- JobScheduler 送出任務的方法 schedule(jobInfo) , 最終調用的是 JobSchedulerService 中的 schedule 方法 ;
- 在 schedule 方法中調用了 scheduleAsPackage 方法 , 傳入任務相關資訊 , 進行了一系列的狀态判定 ;
- 在 scheduleAsPackage 方法中調用 startTrackingJob 方法 , 該方法中周遊所有的狀态控制器 , 確定所有相關的控制器知道該狀态 ;
【Android 電量優化】JobScheduler 相關源碼分析 ( ConnectivityController 底層源碼分析 | 構造函數 | 追蹤任務更新 | 注冊接收者監聽連接配接變化 ) 部落格中接着上面的部落格繼續分析 :
- 在 startTrackingJob() 方法中 , 調用狀态控制器 StateController 的 maybeStartTrackingJobLocked 方法 , 該方法的作用是更新所有對應的狀态控制器監聽的任務 ;
五、廣播接收者監聽廣播觸發 JobService 執行任務
廣播接收者監聽廣播 : 這是觸發系統回調 JobService 服務的入口 ;
- 注冊廣播接收者 : ConnectivityController 中注冊了廣播接收者 , 用于監聽 ConnectivityManager.CONNECTIVITY_ACTION 廣播 , 這是網絡狀态改變後發出的廣播 ;
- 廣播接收者收到網絡狀态改變的廣播後 , 會調用 updateTrackedJobs(-1) 方法 ;
- 該方法會更新所有對網絡狀态敏感的任務 , 例如有的任務要求在 WIFI 條件下執行 , 此時就會觸發該任務的狀态改變 ;
- updateTrackedJobs 方法中又會調用 狀态改變監聽器 mStateChangedListener 的 onControllerStateChanged 方法 ;
- 狀态改變監聽器 mStateChangedListener 就是 JobSchedulerService 類 ;
- 在實作的 StateChangedListener 接口的 onControllerStateChanged() 回調方法中 , 使用 JobHandler mHandler 發送了 MSG_CHECK_JOB 消息 ;
- 在 JobHandler 中接收上述消息 , 并檢查任務 , 最終調用 maybeRunPendingJobsH() 方法 , 執行任務 ;
- 在 maybeRunPendingJobsH 方法中 , 調用 assignJobsToContextsLocked , 執行任務 ;
- 在 assignJobsToContextsLocked 方法中 , 最終調用了 JobServiceContext 執行 executeRunnableJob(pendingJob) 方法 , 用于執行 pendingJob 任務 ;
- 最終在 JobServiceContext 中綁定使用者自定義的 JobService , 開始執行任務 , 會自動回調下面代碼中的 onStartJob 方法 ;
public class BpJobService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
// 啟動 AsyncTask 異步任務處理工作
new JobAsyncTask().execute(params);
return false;
}
// ... 省略部分代碼
}
- /frameworks/base/services/core/java/com/android/server/job/JobSchedulerService.java
- frameworks/base/services/core/java/com/android/server/job/controllers/ConnectivityController.java
- /frameworks/base/services/core/java/com/android/server/job/JobServiceContext.java