En este documento, se explica cómo migrar apps para usar la biblioteca cliente de WorkManager en lugar de la biblioteca de GCMNetworkManager con el fin de realizar operaciones en segundo plano. Por lo general, la forma preferida para hacer que una app programe trabajos en segundo plano es mediante WorkManager. Al incluir también la biblioteca de WorkManager GCM, puedes habilitar WorkManager para usar GCM a fin de programar las tareas cuando se ejecuta en dispositivos Android con un nivel de API 22 o inferior.
Cómo migrar a WorkManager
Si tu app actualmente usa GCMNetworkManager para realizar operaciones en segundo plano, sigue estos pasos a fin de migrar a WorkManager.
En los siguientes pasos, suponemos que estás comenzando con el siguiente código de GCMNetworkManager, que define y programa tu tarea:
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
// 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);
En este ejemplo, se asume que MyUploadService
define la operación de carga real:
Kotlin
class MyUploadService : GcmTaskService() { fun onRunTask(params: TaskParams): Int { // Do some upload work return GcmNetworkManager.RESULT_SUCCESS } }
Java
class MyUploadService extends GcmTaskService { @Override public int onRunTask(TaskParams params) { // Do some upload work return GcmNetworkManager.RESULT_SUCCESS; } }
Cómo incluir las bibliotecas de WorkManager
Para usar las clases de WorkManager, debes agregar la biblioteca de WorkManager a tus dependencias de compilación. También debes agregar la biblioteca de WorkManager GCM, que permite a WorkManager usar GCM para la programación de trabajos cuando tu app se ejecuta en dispositivos que no admiten JobScheduler (es decir, dispositivos con nivel de API 22 o inferior). Si quieres obtener información detallada para agregar las bibliotecas, consulta Cómo comenzar a usar WorkManager.
Cómo modificar tu manifiesto
Cuando implementaste GCMNetworkmanager, agregaste una instancia de GcmTaskService
al manifiesto de la app, como se describe en la documentación de referencia de GcmNetworkManager
.
GcmTaskService
examina la tarea entrante y la delega al controlador de tareas. WorkManager administra la delegación de tareas a tu trabajador, por lo que ya no necesitas una clase que lo haga; simplemente puedes quitar tu GcmTaskService
del manifiesto.
Cómo definir al trabajador
Tu implementación de GCMNetworkManager define una OneoffTask
o RecurringTask
, que especifica exactamente qué trabajo se debe hacer. Debes volver a escribir eso como Worker
, como se documenta en Cómo definir tus solicitudes de trabajo.
El código GCMNetworkManager de muestra define una tarea myTask
. El equivalente de WorkManager se ve de la siguiente manera:
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
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() } }
Existen las siguientes diferencias entre la tarea de GCM y Worker
:
- GCM usa un objeto
TaskParams
para pasar parámetros a la tarea.WorkManager
usa datos de entrada, que puedes especificar enWorkRequest
, como se describe en la documentación deWorkManager
sobre Cómo definir entradas y salidas para tu tarea. En ambos casos, puedes pasar pares clave-valor que especifiquen los parámetros persistentes necesarios para la tarea. - El
GcmTaskService
indica si la operación se realizó correctamente o no con marcas comoGcmNetworkManager.RESULT_SUCCESS
. UnWorker
de WorkManager indica sus resultados mediante un métodoListenableWorker.Result
, comoListenableWorker.Result.success()
, y mostrando el valor de resultado de ese método. - Como ya se mencionó, cuando defines el elemento
Worker
, no estableces restricciones ni etiquetas. Eso lo haces en el paso siguiente, cuando creas el elementoWorkRequest
.
Cómo programar la solicitud de trabajo
La definición de Worker
especifica qué necesitas hacer. Para especificar cuándo se debe realizar el trabajo, debes definir la WorkRequest
:
- Crea una
OneTimeWorkRequest
oPeriodicWorkRequest
y establece las restricciones que desees para especificar cuándo se debe ejecutar la tarea y las etiquetas que identifican tu trabajo. - Pasa la solicitud a
WorkManager.enqueue()
con el objetivo de que la tarea se ponga en cola para su ejecución.
Por ejemplo, en la sección anterior se mostró cómo convertir un elemento OneoffTask
en un elemento Worker
equivalente. Sin embargo, ese Worker
no incluyó las restricciones y la etiqueta de ejecución del objeto OneoffTask
. En su lugar, estableceremos las restricciones y el ID de la tarea cuando creemos el elemento WorkRequest
. También especificaremos que la tarea no debe ejecutarse a menos que haya una conexión de red. No es necesario que solicites explícitamente una conexión de red con GCMNetworkManager, ya que este requiere la conexión de forma predeterminada. Sin embargo, WorkManager no la requiere a menos que agregues específicamente esa restricción.
Una vez que definimos el elemento WorkRequest
, lo ponemos en cola con WorkManager.
Kotlin
val uploadConstraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .setRequiresCharging(true).build() val uploadTask = OneTimeWorkRequestBuilder<UploadWorker>() .setConstraints(uploadConstraints) .build() WorkManager.getInstance().enqueue(uploadTask)
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);
Mapeados de API
En esta sección, se describe cómo se mapean algunas funciones y restricciones de GCMNetworkManager con sus equivalentes de WorkManager.
Mapeado de restricciones
GCMNetworkManager te permite establecer una serie de restricciones que se aplican en el momento de la ejecución de tu tarea. En la mayoría de los casos, existe una restricción equivalente de WorkManager clara. En esta sección, se enumeran esas equivalencias.
Llama al método adecuado en el objeto Builder de la tarea para establecer restricciones en las tareas de GCMNetworkManager. Por ejemplo, puedes establecer un requisito de red llamando a Task.Builder.setRequiredNetwork()
.
En WorkManager, puedes crear un objeto Constraints.Builder
y llamar a los métodos de ese objeto para establecer restricciones (por ejemplo, Constraints.Builder.setRequiredNetworkType())
). Luego, usa el compilador a fin de crear un objeto Constraints que puedes adjuntar a la solicitud de trabajo. Para obtener más información, consulta Cómo definir tus solicitudes de trabajo.
Restricción de GCMNetworkManager | Equivalente de WorkManager | Notas |
---|---|---|
setPersisted() |
(no se necesita) | Todos los trabajos de WorkManager se conservan después de todos los reinicios del dispositivo. |
setRequiredNetwork() |
setRequiredNetworkType() |
De manera predeterminada, GCMNetworkManager requiere acceso a la red. WorkManager no necesita acceso a la red de manera predeterminada. Si tu trabajo requiere acceso a la red, debes usar setRequiredNetworkType(CONNECTED) o establecer un tipo de red más específico. |
setRequiresCharging() |
Otros mapeos
Además de las restricciones, hay otras opciones de configuración que puedes aplicar a las tareas de GCMNetworkManager. En esta sección, se describe la forma correspondiente de aplicar esas opciones a un trabajo de WorkManager.
Etiquetas
Todas las tareas de GCMNetworkManager deben tener una string de etiqueta, que se establece llamando al método setTag()
de Builder. Los trabajos de WorkManager se identifican de forma exclusiva mediante un ID, que WorkManager genera automáticamente. Puedes obtenerlo llamando a WorkRequest.getId()
. Además, las solicitudes de trabajo pueden tener de forma opcional una o más etiquetas. Para establecer una etiqueta en tu trabajo de WorkManager, llama al método WorkRequest.Builder.addTag()
antes de usar ese objeto Builder para crear el WorkRequest
.
En GCMNetworkManager, puedes llamar a setUpdateCurrent()
para especificar si la tarea debe reemplazar cualquier tarea existente con la misma etiqueta.
El enfoque equivalente de WorkManager es poner en cola la tarea llamando a enqueueUniqueWork()
o enqueueUniquePeriodicWork()
. Si usas estos métodos, le asignas un nombre único al trabajo y también especificas cómo WorkManager debe manejar la solicitud si ya existe un trabajo pendiente con ese nombre. Para obtener más información, consulta Cómo administrar el trabajo único.
Parámetros de la tarea
Para pasar parámetros a un trabajo de GCMNetworkManager, llama a Task.Builder.setExtras()
y pásalos dentro de un objeto Bundle
. WorkManager te permite pasar un objeto Data
que contenga los parámetros como pares clave-valor al trabajo de WorkManager. Para obtener más información, consulta Cómo asignar datos de entrada.