Migrazione da GCMNetworkManager a WorkManager

Questo documento spiega come eseguire la migrazione delle app per utilizzare la libreria client di WorkManager per eseguire operazioni in background anziché la libreria GCMNetworkManager. Il modo preferito per un'app di pianificare i job in background è utilizzare WorkManager. Includendo anche la libreria GCM di WorkManager, puoi consentire a WorkManager di utilizzare GCM per pianificare le attività durante l'esecuzione sui dispositivi Android con livello API 22 o precedente.

Esegui la migrazione a WorkManager

Se al momento la tua app utilizza GCMNetworkManager per eseguire operazioni in background, segui questi passaggi per eseguire la migrazione a WorkManager.

Per i passaggi seguenti, supponiamo che tu stia iniziando con il seguente codice GCMNetworkManager, che definisce e pianifica l'attività:

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);

In questo esempio, supponiamo che MyUploadService definisca l'operazione di caricamento effettiva:

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;
    }
}

Includi le librerie di WorkManager

Per utilizzare le classi WorkManager, devi aggiungere la libreria WorkManager alle dipendenze della build. Devi inoltre aggiungere la libreria GCM di WorkManager, che consente a WorkManager di utilizzare GCM per la pianificazione dei job quando la tua app è in esecuzione su dispositivi che non supportano JobScheduler (ossia dispositivi con livello API 22 o precedente). Per informazioni dettagliate sull'aggiunta delle librerie, consulta la guida introduttiva a WorkManager.

Modificare il manifest

Quando hai implementato GCMNetworkManager, hai aggiunto un'istanza di GcmTaskService al file manifest dell'app, come descritto nella documentazione di riferimento di GcmNetworkManager. GcmTaskService esamina l'attività in arrivo e la delega al gestore delle attività. WorkManager gestisce la delega delle attività per il tuo worker, quindi non è più necessaria una classe che lo faccia; è sufficiente rimuovere GcmTaskService dal file manifest.

Definisci il worker

L'implementazione di GCMNetworkManager definisce OneoffTask o RecurringTask, che indica quale operazione deve essere eseguita. Devi riscriverlo come Worker, come documentato in Definizione delle richieste di lavoro.

Il codice GCMNetworkManager di esempio definisce un'attività myTask. L'equivalente di WorkManager si presenta così:

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()
    }
}

Esistono alcune differenze tra l'attività GCM e Worker:

  • GCM utilizza un oggetto TaskParams per trasmettere i parametri all'attività. L'WorkManager utilizza i dati di input che puoi specificare nella WorkRequest, come descritto nella documentazione relativa all'WorkManager per la definizione di input/output per l'attività. In entrambi i casi, puoi trasmettere coppie chiave/valore specificando eventuali parametri permanenti richiesti dall'attività.
  • GcmTaskService segnala l'esito positivo o negativo restituendo flag come GcmNetworkManager.RESULT_SUCCESS. Un Worker di WorkManager segnala i suoi risultati utilizzando un metodo ListenableWorker.Result come ListenableWorker.Result.success(), restituendo il valore restituito da quel metodo.
  • Come abbiamo detto in precedenza, non devi impostare i vincoli o i tag quando definisci Worker, ma devi farlo nel passaggio successivo, quando crei la WorkRequest.

Programma la richiesta di lavoro

La definizione di un Worker specifica cosa devi fare. Per specificare quando deve essere completato il lavoro, devi definire WorkRequest:

  1. Crea un elemento OneTimeWorkRequest o PeriodicWorkRequest e imposta i vincoli desiderati per specificare quando eseguire l'attività, nonché i tag per identificare il lavoro.
  2. Passa la richiesta a WorkManager.enqueue() per mettere l'attività in coda per l'esecuzione.

Ad esempio, la sezione precedente mostrava come convertire un OneoffTask in un Worker equivalente. Tuttavia, l'elemento Worker non includeva il tag e i vincoli di esecuzione dell'oggetto OneoffTask. Invece, impostiamo i vincoli e l'ID attività quando creiamo WorkRequest. Specifica inoltre che l'attività non deve essere eseguita a meno che non ci sia una connessione di rete. Non è necessario richiedere esplicitamente una connessione di rete con GCMNetworkManager, poiché GCMNetworkManager richiede una connessione di rete per impostazione predefinita, ma WorkManager non richiede una connessione di rete, a meno che tu non aggiunga specificamente questo vincolo. Una volta definito WorkRequest, lo accodiamo a 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);

Mappature delle API

Questa sezione descrive come alcune funzionalità e alcuni vincoli di GCMNetworkManager vengono mappati agli equivalenti di WorkManager.

Mappature dei vincoli

GCMNetworkManager consente di impostare una serie di vincoli sul momento in cui deve essere eseguita l'attività. Nella maggior parte dei casi, esiste un vincolo di WorkManager equivalente chiaro. In questa sezione sono elencati gli equivalenti.

Imposta vincoli sulle attività GCMNetworkManager chiamando il metodo appropriato nell'oggetto Builder dell'attività. Ad esempio, puoi impostare un requisito di rete chiamando Task.Builder.setRequiredNetwork().

In WorkManager, crei un oggetto Constraints.Builder e chiami i metodi dell'oggetto per impostare i vincoli, ad esempio Constraints.Builder.setRequiredNetworkType()), quindi utilizzerai Builder per creare un oggetto Vincoli da collegare alla richiesta di lavoro. Per ulteriori informazioni, consulta Definizione delle richieste di lavoro.

Vincolo GCMNetworkManager Equivalente WorkManager Notes
setPersisted() (non obbligatorio) Tutti i job di WorkManager sono salvati in modo permanente su tutti i riavvii dei dispositivi
setRequiredNetwork() setRequiredNetworkType() Per impostazione predefinita GCMNetworkManager richiede l'accesso alla rete. Per impostazione predefinita, WorkManager non richiede l'accesso alla rete. Se il job richiede l'accesso alla rete, devi utilizzare setRequiredNetworkType(CONNECTED) o impostare un tipo di rete più specifico.
setRequiresCharging()

Altre mappature

Oltre ai vincoli, esistono altre impostazioni che puoi applicare alle attività di GCMNetworkManager. Questa sezione elenca il modo corrispondente per applicare queste impostazioni a un job di WorkManager.

Tag

Tutte le attività di GCMNetworkManager devono avere una stringa tag, che puoi impostare chiamando il metodo setTag() del generatore. I job WorkManager sono identificati in modo univoco da un ID, generato automaticamente da WorkManager; puoi ottenere questo ID chiamando WorkRequest.getId(). Inoltre, le richieste di lavoro possono facoltativamente avere uno o più tag. Per impostare un tag per il job di WorkManager, chiama il metodo WorkRequest.Builder.addTag() prima di utilizzare questo Builder per creare WorkRequest.

In GCMNetworkManager puoi chiamare setUpdateCurrent() per specificare se l'attività deve sostituire qualsiasi attività esistente con lo stesso tag. L'approccio equivalente di WorkManager prevede di accodare l'attività chiamando enqueueUniqueWork() o enqueueUniquePeriodicWork(). Se utilizzi questi metodi, assegni al job un nome univoco e specifichi in che modo WorkManager deve gestire la richiesta se esiste già un job in attesa con questo nome. Per ulteriori informazioni, consulta Gestione di lavoro univoco.

Parametri attività

Puoi passare i parametri a un job GCMNetworkManager chiamando Task.Builder.setExtras() e trasmettendo un Bundle contenente i parametri. WorkManager ti consente di passare un oggetto Data al job di WorkManager, contenente i parametri sotto forma di coppie chiave/valore. Per maggiori dettagli, vedi Assegnare dati di input.