Informar status do trabalho

Neste guia, mostramos como informar o status de uma solicitação de trabalho executada em um serviço em segundo plano ao componente que enviou a solicitação. Isso permite, por exemplo, informar o status a solicitação na interface de um objeto Activity. A maneira recomendada de enviar e receber status é usar um LocalBroadcastManager, que limita objetos Intent de transmissão aos componentes no seu próprio app.

Relatar o status a partir de um JobIntentService

Para enviar o status de uma solicitação de trabalho em uma JobIntentService para outros componentes, primeiro crie um Intent que contenha o status em seu dados estendidos. Como opção, você pode adicionar um URI de ação e dados a essa Intent.

Em seguida, envie Intent chamando LocalBroadcastManager.sendBroadcast(). Isso envia o Intent para qualquer no aplicativo que foi registrado para recebê-lo. Para acessar uma instância de LocalBroadcastManager, chame getInstance().

Exemplo:

Kotlin

...
// Defines a custom Intent action
const val BROADCAST_ACTION = "com.example.android.threadsample.BROADCAST"
...
// Defines the key for the status "extra" in an Intent
const val EXTENDED_DATA_STATUS = "com.example.android.threadsample.STATUS"
...
class RSSPullService : JobIntentService() {
    ...
    /*
     * Creates a new Intent containing a Uri object
     * BROADCAST_ACTION is a custom Intent action
     */
    val localIntent = Intent(BROADCAST_ACTION).apply {
        // Puts the status into the Intent
        putExtra(EXTENDED_DATA_STATUS, status)
    }
    // Broadcasts the Intent to receivers in this app.
    LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent)
    ...
}

Java

public final class Constants {
    ...
    // Defines a custom Intent action
    public static final String BROADCAST_ACTION =
        "com.example.android.threadsample.BROADCAST";
    ...
    // Defines the key for the status "extra" in an Intent
    public static final String EXTENDED_DATA_STATUS =
        "com.example.android.threadsample.STATUS";
    ...
}
public class RSSPullService extends JobIntentService {
...
    /*
     * Creates a new Intent containing a Uri object
     * BROADCAST_ACTION is a custom Intent action
     */
    Intent localIntent =
            new Intent(Constants.BROADCAST_ACTION)
            // Puts the status into the Intent
            .putExtra(Constants.EXTENDED_DATA_STATUS, status);
    // Broadcasts the Intent to receivers in this app.
    LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
...
}

A próxima etapa é processar os objetos Intent de transmissão de entrada no o componente que enviou a solicitação de trabalho original.

Receber transmissões de status a partir de um JobIntentService

Para receber objetos Intent de transmissão, use uma subclasse de BroadcastReceiver. Na subclasse, implemente a Chamada de retorno de BroadcastReceiver.onReceive() , que LocalBroadcastManager invoca quando recebe um Intent. LocalBroadcastManager transmite o Intent de entrada para BroadcastReceiver.onReceive()

Exemplo:

Kotlin

// Broadcast receiver for receiving status updates from the IntentService.
private class DownloadStateReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        ...
        /*
         * Handle Intents here.
         */
        ...
    }
}

Java

// Broadcast receiver for receiving status updates from the IntentService.
private class DownloadStateReceiver extends BroadcastReceiver
{
    // Called when the BroadcastReceiver gets an Intent it's registered to receive
    @Override
    public void onReceive(Context context, Intent intent) {
...
        /*
         * Handle Intents here.
         */
...
    }
}

Depois de definir o BroadcastReceiver, é possível definir filtros que correspondem a ações, categorias e dados específicos. Para fazer isso, crie um IntentFilter. Este primeiro snippet mostra como definir o filtro:

Kotlin

// Class that displays photos
class DisplayActivity : FragmentActivity() {
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        super.onCreate(savedInstanceState)
        ...
        // The filter's action is BROADCAST_ACTION
        var statusIntentFilter = IntentFilter(BROADCAST_ACTION).apply {
            // Adds a data filter for the HTTP scheme
            addDataScheme("http")
        }
        ...

Java

// Class that displays photos
public class DisplayActivity extends FragmentActivity {
    ...
    public void onCreate(Bundle stateBundle) {
        ...
        super.onCreate(stateBundle);
        ...
        // The filter's action is BROADCAST_ACTION
        IntentFilter statusIntentFilter = new IntentFilter(
                Constants.BROADCAST_ACTION);

        // Adds a data filter for the HTTP scheme
        statusIntentFilter.addDataScheme("http");
        ...

Para registrar o BroadcastReceiver e o IntentFilter com o sistema, receba uma instância de LocalBroadcastManager e chamar registerReceiver() . O próximo snippet mostra como registrar o BroadcastReceiver e o IntentFilter:

Kotlin

        // Instantiates a new DownloadStateReceiver
        val downloadStateReceiver = DownloadStateReceiver()
        // Registers the DownloadStateReceiver and its intent filters
        LocalBroadcastManager.getInstance(this)
                .registerReceiver(downloadStateReceiver, statusIntentFilter)
        ...

Java

        // Instantiates a new DownloadStateReceiver
        DownloadStateReceiver downloadStateReceiver =
                new DownloadStateReceiver();
        // Registers the DownloadStateReceiver and its intent filters
        LocalBroadcastManager.getInstance(this).registerReceiver(
                downloadStateReceiver,
                statusIntentFilter);
        ...

Um único BroadcastReceiver pode processar mais de um tipo de objeto Intent de transmissão, cada um com sua própria ação. Esse recurso permite que você executar códigos diferentes para cada ação, sem precisar definir BroadcastReceiver para cada ação. Para definir outro IntentFilter igual BroadcastReceiver, crie a IntentFilter e Repita a chamada para registerReceiver(). Exemplo:

Kotlin

        /*
         * Instantiates a new action filter.
         * No data filter is needed.
         */
        statusIntentFilter = IntentFilter(ACTION_ZOOM_IMAGE)
        // Registers the receiver with the new filter
        LocalBroadcastManager.getInstance(this)
                .registerReceiver(downloadStateReceiver, statusIntentFilter)

Java

        /*
         * Instantiates a new action filter.
         * No data filter is needed.
         */
        statusIntentFilter = new IntentFilter(Constants.ACTION_ZOOM_IMAGE);
        // Registers the receiver with the new filter
        LocalBroadcastManager.getInstance(this).registerReceiver(
                downloadStateReceiver,
                statusIntentFilter);

O envio de uma transmissão Intent não inicia nem retoma uma Activity. O BroadcastReceiver de um O Activity recebe e processa objetos Intent, mesmo quando o app está em segundo plano, mas não o força a ficar em primeiro plano. Se você querem notificar o usuário sobre um evento que ocorreu em segundo plano enquanto o app não estava visível, use um Notification. Nunca inicie uma Activity em resposta a uma transmissão recebida Intent.