This document explains how to migrate apps to use the WorkManager client library to perform background operations instead of the GCMNetworkManager library. The preferred way for an app to schedule background jobs is to use WorkManager. By also including the WorkManager GCM library, you can enable WorkManager to use GCM to schedule the tasks when running on Android devices running API level 22 or lower.

## Migrate to WorkManager

If your app currently uses GCMNetworkManager to perform background operations, follow these steps to migrate to WorkManager.

For the following steps, we assume you're starting with the following GCMNetworkManager code, which defines and schedules your task:  

### Kotlin

```kotlin
val myTask = OneoffTask.Builder()
    // setService() says what class does the work
    .setService(MyUploadService::class.java)
    // Don't run the task unless device is charging
    .setRequiresCharging(true)
    // Run the task between 5 & 15 minutes from now
    .setExecutionWindow(5 * DateUtil.MINUTE_IN_SECONDS,
            15 * DateUtil.MINUTE_IN_SECONDS)
    // Define a unique tag for the task
    .setTag("test-upload")
    // ...finally, build the task and assign its value to myTask
    .build()
GcmNetworkManager.getInstance(this).schedule(myTask)
```

### Java

```java
// In GcmNetworkManager, this call defines the task and its
// runtime constraints:
OneoffTask myTask = new OneoffTask.Builder()
    // setService() says what class does the work
    .setService(MyUploadService.class)
    // Don't run the task unless device is charging
    .setRequiresCharging(true)
    // Run the task between 5 & 15 minutes from now
    .setExecutionWindow(
        5 * DateUtil.MINUTE_IN_SECONDS,
        15 * DateUtil.MINUTE_IN_SECONDS)
    // Define a unique tag for the task
    .setTag("test-upload")
    // ...finally, build the task and assign its value to myTask
    .build();
GcmNetworkManager.getInstance(this).schedule(myTask);
```

In this example, we assume`MyUploadService`defines the actual upload operation:  

### Kotlin

```kotlin
class MyUploadService : GcmTaskService() {
    fun onRunTask(params: TaskParams): Int {
        // Do some upload work
        return GcmNetworkManager.RESULT_SUCCESS
    }
}
```

### Java

```java
class MyUploadService extends GcmTaskService {
    @Override
    public int onRunTask(TaskParams params) {
        // Do some upload work
        return GcmNetworkManager.RESULT_SUCCESS;
    }
}
```

### Include the WorkManager libraries

To use the WorkManager classes, you need to add the WorkManager library to your build dependencies. You also need to add the WorkManager GCM library, which enables WorkManager to use GCM for job scheduling when your app is running on devices that don't support JobScheduler (that is, devices running API level 22 or lower). For full details on adding the libraries, see[Getting started with WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager/basics).

### Modify your manifest

When you implemented GCMNetworkManager, you added an instance of`GcmTaskService`to your app manifest, as described in the`GcmNetworkManager`[reference documentation](https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager).`GcmTaskService`looks at the incoming task and delegates it to the task handler. WorkManager manages task delegation to your Worker, so you no longer need a class that does this; simply remove your`GcmTaskService`from the manifest.
| **Note:** You might have added logic to your`GcmTaskService`to do some work before dispatching the task to the handler. In that case, you need to refactor and move that logic into the[`Worker`](https://developer.android.com/reference/androidx/work/Worker)class you define in the next section.

### Define the Worker

Your GCMNetworkManager implementation defines a`OneoffTask`or`RecurringTask`, which specifies just what work needs to be done. You need to rewrite that as a`Worker`, as documented in[Defining your work requests](https://developer.android.com/topic/libraries/architecture/workmanager/how-to/define-work).
| **Note:** In GCMNetworkManager, the task defines both what work you want to do, and when the task should run. With the`WorkManager`library, you use two different classes to define these elements. The[`Worker`](https://developer.android.com/reference/androidx/work/Worker)defines the task you want to perform; when you create the[`WorkRequest`](https://developer.android.com/reference/androidx/work/WorkRequest), you specify any constraints on when the job should run.

The[sample GCMNetworkManager code](https://developer.android.com/develop/background-work/background-tasks/persistent/migrate-from-legacy/gcm#gcm-before)defines a`myTask`task. The WorkManager equivalent looks like this:  

### Kotlin

```kotlin
class UploadWorker(context: Context, params: WorkerParameters)
                        : Worker(context, params) {
    override fun doWork() : Result {
        // Do the upload operation ...
        myUploadOperation()

        // Indicate whether the task finished successfully with the Result
        return Result.success()
    }
}
```

### Java

```java
public class UploadWorker extends Worker {

    public UploadWorker(
        @NonNull Context context,
        @NonNull WorkerParameters params) {
        super(context, params);
    }

    @Override
    public Result doWork() {
      // Do the upload operation ...

      myUploadOperation()

      // Indicate whether the task finished successfully with the Result
      return Result.success()
    }
}
```

There are a few differences between the GCM task and the`Worker`:

- GCM uses a`TaskParams`object to pass parameters to the task. The`WorkManager`uses input data, which you can specify on the`WorkRequest`, as described in the`WorkManager`documentation for[Defining input/output for your task](https://developer.android.com/topic/libraries/architecture/workmanager/how-to/define-work#input_output). In both cases, you can pass key/value pairs specifying any persistable parameters needed by the task.
- The`GcmTaskService`signals success or failure by returning flags like`GcmNetworkManager.RESULT_SUCCESS`. A WorkManager`Worker`signals its results by using a[`ListenableWorker.Result`](https://developer.android.com/reference/androidx/work/ListenableWorker.Result)method, like[`ListenableWorker.Result.success()`](https://developer.android.com/reference/androidx/work/ListenableWorker.Result#success()), and returning that method's return value.
- As we mentioned, you do not set the constraints or tags when you define the`Worker`; instead, you do this in the next step, when you create the`WorkRequest`.

### Schedule the work request

Defining a`Worker`specifies*what* you need done. To specify when the work should be done, you need to define the[`WorkRequest`](https://developer.android.com/reference/androidx/work/WorkRequest):

1. Create a[`OneTimeWorkRequest`](https://developer.android.com/reference/androidx/work/OneTimeWorkRequest)or[`PeriodicWorkRequest`](https://developer.android.com/reference/androidx/work/PeriodicWorkRequest), and set any desired constraints specifying when the task should run, as well as any tags to identify your work.
2. Pass the request to[`WorkManager.enqueue()`](https://developer.android.com/reference/androidx/work/WorkManager#enqueue(androidx.work.WorkRequest))to have the task queued for execution.

For example, the[previous section](https://developer.android.com/develop/background-work/background-tasks/persistent/migrate-from-legacy/gcm#define-worker)showed how to convert a`OneoffTask`to an equivalent`Worker`. However, that`Worker`did not include the`OneoffTask`object's execution constraints and tag. Instead, we set the constraints and task ID when we create the`WorkRequest`. We'll also specify that the task must not run unless there's a network connection. You don't need to explicitly request a network connection with GCMNetworkManager, since GCMNetworkManager requires a network connection by default, but WorkManager does not require a network connection unless you specifically add that constraint. Once we've defined the`WorkRequest`, we enqueue it with WorkManager.  

### Kotlin

```kotlin
val uploadConstraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresCharging(true).build()

val uploadTask = OneTimeWorkRequestBuilder&lt;UploadWorker>()
    .setConstraints(uploadConstraints)
    .build()
WorkManager.getInstance().enqueue(uploadTask)
```

### Java

```java
Constraints uploadConstraints = new Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresCharging(true)
    .build();

OneTimeWorkRequest uploadTask =
        new OneTimeWorkRequest.Builder(UploadWorker.class)
  .setConstraints(uploadConstraints)
  .build();
WorkManager.getInstance().enqueue(uploadTask);
```
| **Note:** With GCMNetworkManager, every task must have a unique tag. The analogous WorkManager construct is the`WorkRequest`ID. This ID is automatically set by WorkManager when the request is created; you get the ID by calling[`WorkRequest.getId()`](https://developer.android.com/reference/androidx/work/WorkRequest#getId). WorkManager also allows you to define tags for your jobs, but these are different from GCMNetworkManager tags because they need not be unique; you might have several similar WorkManager tasks all enqueued at once, and all using the same tag.
| **Note:** GCMNetworkManager requires you to define an execution window, but WorkManager does not require this. Instead, WorkManager runs the job as soon as possible after the constraints are met. In this example, we assume you don't actually need to set a specific time for the job to run.

## API mappings

This section describes how some GCMNetworkManager features and constraints map onto WorkManager equivalents.

### Constraint mappings

GCMNetworkManager lets you set a number of constraints on when your task should run. In most cases, there's a clear equivalent WorkManager constraint. This section lists those equivalents.

Set constraints on GCMNetworkManager tasks by calling the appropriate method in the task's Builder object; for example, you can set a network requirement by calling[`Task.Builder.setRequiredNetwork()`](https://developer.google.com/android/reference/com/google/android/gms/gcm/Task.Builder.html#setRequiredNetwork(int)).

In WorkManager, you create a[`Constraints.Builder`](https://developer.android.com/reference/androidx/work/Constraints.Builder)object and call that object's methods to set constraints (for example,[`Constraints.Builder.setRequiredNetworkType())`](https://developer.android.com/reference/androidx/work/Constraints.Builder#setRequiredNetworkType(androidx.work.NetworkType)), then use the Builder to create a Constraints object which you can attach to the work request. For more information, see[Defining your work requests](https://developer.android.com/topic/libraries/architecture/workmanager/how-to/define-work#constraints).
| **Note:** GCMNetworkManager allows you to specify a specific execution window for your task. There is no equivalent functionality in WorkManager. If you need to do work at a precise time, we recommend using other options, like[`AlarmManager`](https://developer.android.com/reference/android/app/AlarmManager).

|                                                                                 GCMNetworkManager constraint                                                                                 |                                                                  WorkManager equivalent                                                                   |                                                                                                                    Notes                                                                                                                    |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`setPersisted()`](https://developers.google.com/android/reference/com/google/android/gms/gcm/Task.Builder#setPersisted(boolean))                                                            | *(not required)*                                                                                                                                          | All WorkManager jobs are persisted across device reboots                                                                                                                                                                                    |
| [`setRequiredNetwork()`](https://developers.google.com/android/reference/com/google/android/gms/gcm/Task.Builder#public-abstract-task.builder-setrequirednetwork-int-requirednetworkstate)   | [`setRequiredNetworkType()`](https://developer.android.com/reference/androidx/work/Constraints.Builder#setRequiredNetworkType(androidx.work.NetworkType)) | By default GCMNetworkManager requires network access. WorkManager does not require network access by default. If your job requires network access, you must use`setRequiredNetworkType(CONNECTED)`, or set some more specific network type. |
| [`setRequiresCharging()`](https://developers.google.com/android/reference/com/google/android/gms/gcm/Task.Builder#public-abstract-task.builder-setrequirescharging-boolean-requirescharging) |                                                                                                                                                           |                                                                                                                                                                                                                                             |

### Other mappings

Besides constraints, there are other settings you can apply to GCMNetworkManager tasks. This section lists the corresponding way to apply those settings to a WorkManager job.

#### Tags

All GCMNetworkManager tasks must have a tag string, which you set by calling the Builder's[`setTag()`](https://developers.google.com/android/reference/com/google/android/gms/gcm/Task.Builder#setTag(java.lang.String))method. WorkManager jobs are uniquely identified by an ID, which is automatically generated by WorkManager; you can get that ID by calling[`WorkRequest.getId()`](https://developer.android.com/reference/androidx/work/WorkRequest#getId()). In addition, work requests can*optionally* have one or more tags. To set a tag for your WorkManager job, call the[`WorkRequest.Builder.addTag()`](https://developer.android.com/reference/androidx/work/WorkRequest.Builder#addTag(java.lang.String))method, before you use that Builder to create the`WorkRequest`.

In GCMNetworkManager, you can call[`setUpdateCurrent()`](https://developers.google.com/android/reference/com/google/android/gms/gcm/Task.Builder.html#setUpdateCurrent(boolean))to specify whether the task should replace any existing task with the same tag. The equivalent WorkManager approach is to enqueue the task by calling[`enqueueUniqueWork()`](https://developer.android.com/reference/androidx/work/WorkManager#enqueueUniqueWork(java.lang.String,%2520androidx.work.ExistingWorkPolicy,%2520java.util.List%3Candroidx.work.OneTimeWorkRequest%3E))or[`enqueueUniquePeriodicWork()`](https://developer.android.com/reference/androidx/work/WorkManager#enqueueUniquePeriodicWork(java.lang.String,%2520androidx.work.ExistingPeriodicWorkPolicy,%2520androidx.work.PeriodicWorkRequest)); if you use these methods, you give the job a unique name, and also specify how WorkManager should handle the request if there's already a pending job with that name. For more information, see[Handling unique work](https://developer.android.com/topic/libraries/architecture/workmanager/how-to/managing-work#unique-work).

#### Task parameters

You can pass parameters to a GCMNetworkManager job by calling[`Task.Builder.setExtras()`](https://developers.google.com/android/reference/com/google/android/gms/gcm/Task.Builder#setExtras(android.os.Bundle))and passing a`Bundle`containing the parameters. WorkManager allows you to pass a`Data`object to the WorkManager job, containing the parameters as key/value pairs. For details, see[Assign input data](https://developer.android.com/topic/libraries/architecture/workmanager/how-to/define-work#assign_input_data).