Workers: They Do Work

The work that you want to have done in the background needs to be wrapped in a Worker subclass. This is an abstract class with one abstract method: doWork(). In that method, you put your work to be done in the background.

Note that:

As noted above, doWork() returns a ListenableWorker.Result object. There are static factory methods on ListenableWorker.Result that you use to create instances. Those factory methods represent three main result scenarios:

Beyond the return value and the aforementioned limitations on what you can do in doWork(), the actual business logic is up to you.

The DownloadWork sample module in the Sampler and SamplerJ projects contains a DownloadWorker class that downloads a file using OkHttp and a companion library named Okio:

package com.commonsware.jetpack.work.download;

import android.content.Context;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import androidx.annotation.NonNull;
import androidx.work.ListenableWorker;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okio.BufferedSink;
import okio.Okio;

public class DownloadWorker extends Worker {
  public static final String KEY_URL="url";
  public static final String KEY_FILENAME="filename";

  public DownloadWorker(@NonNull Context context,
                        @NonNull WorkerParameters workerParams) {
    super(context, workerParams);
  }

  @NonNull
  @Override
  public Result doWork() {
    OkHttpClient client=new OkHttpClient();
    Request request=new Request.Builder()
      .url(getInputData().getString(KEY_URL))
      .build();

    try (Response response=client.newCall(request).execute()) {
      File dir=getApplicationContext().getCacheDir();
      File downloadedFile=
        new File(dir, getInputData().getString(KEY_FILENAME));
      BufferedSink sink=Okio.buffer(Okio.sink(downloadedFile));

      sink.writeAll(response.body().source());
      sink.close();
    }
    catch (IOException e) {
      Log.e(getClass().getSimpleName(), "Exception downloading file", e);

      return ListenableWorker.Result.failure();
    }

    return ListenableWorker.Result.success();
  }
}
package com.commonsware.jetpack.work.download

import android.content.Context
import android.util.Log
import androidx.work.Worker
import androidx.work.WorkerParameters
import okhttp3.OkHttpClient
import okhttp3.Request
import okio.buffer
import okio.sink
import java.io.File
import java.io.IOException

class DownloadWorker(context: Context, workerParams: WorkerParameters) :
  Worker(context, workerParams) {

  override fun doWork(): Result {
    val client = OkHttpClient()
    val request = Request.Builder()
      .url(inputData.getString(KEY_URL)!!)
      .build()

    try {
      client.newCall(request).execute().use { response ->
        val dir = applicationContext.cacheDir
        val downloadedFile = File(dir, inputData.getString(KEY_FILENAME)!!)
        val sink = downloadedFile.sink().buffer()

        response.body?.let { sink.writeAll(it.source()) }
        sink.close()
      }
    } catch (e: IOException) {
      Log.e(javaClass.simpleName, "Exception downloading file", e)

      return Result.failure()
    }

    return Result.success()
  }

  companion object {
    const val KEY_URL = "url"
    const val KEY_FILENAME = "filename"
  }
}

Worker — from which DownloadWorker inherits — has a two-parameter constructor, taking a Context and a WorkerParameters object. In many cases, you can just chain to the superclass constructor, as DownloadWorker does.

Pretty much everything inside of doWork() is just application code that does the download and returns success() if the download succeeded or failure() if there was some exception during the download.

This doWork() method is using two methods that we get from Worker:


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.