Slide 1

Slide 1 text

WorkManager
 學習⼼心得 Elvis Lin @Android Taipei
 2018-12-27

Slide 2

Slide 2 text

關於我 • Elvis Lin • Android 與 iOS 永遠的初學者 • Twitter: @elvismetaphor • Blog: https://blog.elvismetaphor.me

Slide 3

Slide 3 text

Agenda • ⽬目前 Android 對背景執⾏行行的限制 • 處理理背景任務的⼀一般⽅方式(ex: JobScheduler) • WorkManager

Slide 4

Slide 4 text

背景任務的限制 • 在 Android Oreo 之後,程式在背景的執⾏行行有了了許多限制 • 所有在 Oreo 與 Pie 執⾏行行的 apps 都會被影響 • 無法在 background 開始⼀一個 service • NO startService() • 當程式到背景時,service 會被終⽌止 • ⼤大部分 implicit broadcasts 無法在 manifest 中直接註冊監聽

Slide 5

Slide 5 text

Service 的限制 • 在背景呼叫 startService() • IllegalStateException • 當程式從 Foreground 移到 Background 時 • 所有的 services 只會執⾏行行⼀一⼩小段時間,然後就會結束

Slide 6

Slide 6 text

Broadcast 的限制 • Implicit Broadcasts — 沒有特定⽬目標的 broadcasts • Static Receivers — 定義在 AndroidManifest.xml 中的 receivers • 在 Oreo 以後,static receivers 收不到 implicit broadcasts

Slide 7

Slide 7 text

解決⽅方法 • 使⽤用 JobScheduler • 使⽤用 Firebase Cloud Message,獲得短暫的背景執⾏行行時間 • startForegroundService() • 將任務留留到程式在前景的時候再做

Slide 8

Slide 8 text

使⽤用 Job • JobScheduler • Firebase JobDispatcher (當 < API Level 21) • AlarmManager (當 < API Level 21 ⽽而且沒有 Google Play Service)

Slide 9

Slide 9 text

JobScheduler // Create a JobService to execute the work public class DownloadArtworkJobService extends JobService {
 @Override
 public boolean onStartJob(JobParameters params) {
 // Do something
 } }
 // Schedule a Job 
 JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); jobScheduler.schedule(new JobInfo.Builder(LOAD_ARTWORK_JOB_ID, new ComponentName(this, DownloadArtworkJobService.class)) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) .build());

Slide 10

Slide 10 text

Firebase JobDispatcher // Create a new dispatcher using the Google Play driver. FirebaseJobDispatcher dispatcher = 
 new FirebaseJobDispatcher(new GooglePlayDriver(context)); Job myJob = dispatcher.newJobBuilder() .setService(MyJobService.class) // the JobService that will be called .setTag("my-unique-tag") // uniquely identifies the job .build(); dispatcher.mustSchedule(myJob);

Slide 11

Slide 11 text

使⽤用 FCM • 送 High Priority Message • 當收到 message 時,app 可以有⼀一點短暫的時間在 Foreground 的狀狀態 • App 可以利利⽤用這段時間呼叫 startService() 完成⼯工作

Slide 12

Slide 12 text

使⽤用 startForegroundService • startForegroundService(Intent service) • 在 service 中 • 產⽣生⼀一個 (visible) notification • 執⾏行行 startForeground(id, notification)

Slide 13

Slide 13 text

WorkManager

Slide 14

Slide 14 text

WorkManager • 屬於 architecture components 的⼀一部分,⽤用來來處理理 background ⼯工作 • ⽀支援條件限制與條件觸發 (ex: 有網路路連線、充電中) • ⽀支援單次或週期性的任務 • 可以將多個 worker 串串接起來來 • 向下相容到 API 14

Slide 15

Slide 15 text

WorkManager (續) • 沒有 Google Play Services 也可以使⽤用 • 整合多組 API,提供⼀一致的介⾯面 • …… • BUT, ⽬目前還在 beta 階段

Slide 16

Slide 16 text

整合多個 APIs

Slide 17

Slide 17 text

基本元件 • Worker: 包含所有要在背景執⾏行行的⼯工作,開發者在 doWork() 這個 method 實作 • WorkRequest: 內部包含 Worker 與其他必要的資訊,例例如觸 發的條件或輸入的資料 • OneTimeWorkRequest • PeriodicWorkRequest • WorkManager: 排程與控制 WorkRequest 的執⾏行行

Slide 18

Slide 18 text

專案的設定 • dependencies {
 // Other dependencies
 implementation “android.arch.work:work-runtime: 1.0.0-beta01”
 }

Slide 19

Slide 19 text

實作⼀一個 Worker Public class UploadWorker extends Worker {
 
 @NonNull
 @Override
 public Worker.Result doWork() {
 
 // do something
 return Worker.Result.success()
 }
 }

Slide 20

Slide 20 text

Worker 回傳的狀狀態 • Worker.Result • success() • failure() • retry()

Slide 21

Slide 21 text

將⼯工作放入 WorkManager // Create a request
 OneTimeWorkRequest uploadRequest = 
 new OneTimeWorkRequest.Builder(UploadWorker.class)
 .build();
 
 // Schedule the request
 WorkManager workManager = WorkManager.getInstance(); workManager.enqueue(uploadRequest)

Slide 22

Slide 22 text

加上條件的限制 // Create a request
 OneTimeWorkRequest uploadRequest = 
 new OneTimeWorkRequest.Builder(UploadWorker.class)
 .setRequiresCharging(true)
 .build();
 
 // Schedule the request
 WorkManager workManager = WorkManager.getInstance(); workManager.enqueue(uploadRequest)

Slide 23

Slide 23 text

條件的種類 • NetworkType • Battery • Charging • DeviceIdle • Storage • ContentUpdate • ….

Slide 24

Slide 24 text

傳遞資料給 worker // Create a data
 Data.Builder builder = new Data.Builder();
 Data data = builder.putString(“path”, “file://some_path”);
 
 
 OneTimeWorkRequest uploadRequest = 
 new OneTimeWorkRequest.Builder(UploadWorker.class)
 .setInputData(data)
 .build();


Slide 25

Slide 25 text

取出資料 public Worker.Result doWork() {
 
 String path = getInputData().getString(“path”)
 
 // Do something
 }

Slide 26

Slide 26 text

傳遞資料給後續的 Worker public Worker.Result doWork() {
 
 // Do something
 
 Data.Builder builder = new Data.Builder();
 Data data = 
 builder.putString(“path”, “file://some_path”);
 return Worker.Result.success(data)
 }

Slide 27

Slide 27 text

將多個 Workers 串串連 workManager.beginWork(compressRequest) .then(uploadRequdst) .then(cleanupRequest) .enqueue();

Slide 28

Slide 28 text

保持⼀一次只有⼀一個特定任務在執⾏行行 workManager.beginUniqueWork( IMAGE_UPLOAD_WORK_NAME,
 ExistingWorkPolicy.REPLACE,
 compressRequest) .then(uploadRequest) .then(cleanupRequest) .enqueue();

Slide 29

Slide 29 text

詢問 Worker 的狀狀態 • 取得 WorkInfo
 uploadWorkInfo = workManager
 .getWorkInfosByTagLiveData(TARGET_TAG); • 詢問狀狀態
 uploadWorkInfo.getState() • 詢問是否已經結束
 upLoadWorkInfo.getState().isFinished();

Slide 30

Slide 30 text

取消 Worker 的⼯工作 • workerManbager.cancelAllWorkByTag(TARGET_TAG)

Slide 31

Slide 31 text

總結 • 在 Android Oreo 之後,背景執⾏行行的⼯工作有了了許多限制 • 在不同的情境下,你可以使⽤用 JobScheduler、Firebase JobDispatcher、FCM、AlarmManager 來來完成背景的⼯工作 • WorkManager 將上述的⼤大部分功能打包,提供⼀一致的操作 介⾯面 • WorkManager ⽀支援條件執⾏行行、週期執⾏行行與多個⼯工作的串串接 等需求

Slide 32

Slide 32 text

補充資料 • Background Work with WorkManager
 https://codelabs.developers.google.com/codelabs/android- workmanager/

Slide 33

Slide 33 text

參參考資料 • Background Execution Limits
 https://developer.android.com/about/versions/oreo/background • Schedule jobs intelligently
 https://developer.android.com/topic/performance/scheduling • Guide to Background Processing
 https://developer.android.com/guide/background/ • Schedule tasks with WorkManager
 https://developer.android.com/topic/libraries/architecture/ workmanager/

Slide 34

Slide 34 text

No content