Signaler l'état d'une requête de travail

Ce guide explique comment signaler l'état d'une requête de tâche exécutée dans un service d'arrière-plan au composant qui a envoyé la requête. Cela vous permet, par exemple, de signaler l'état de la requête dans l'interface utilisateur d'un objet Activity. La méthode recommandée pour envoyer et recevoir un état consiste à utiliser un LocalBroadcastManager, ce qui limite les objets Intent de diffusion aux composants de votre propre application.

État du rapport à partir d'un JobIntentService

Pour envoyer l'état d'une requête de tâche dans un JobIntentService à d'autres composants, créez d'abord un Intent contenant l'état dans ses données étendues. Si vous le souhaitez, vous pouvez ajouter une action et un URI de données à ce Intent.

Envoyez ensuite Intent en appelant LocalBroadcastManager.sendBroadcast(). Cette opération envoie le Intent à n'importe quel composant de votre application qui s'est enregistré pour le recevoir. Pour obtenir une instance de LocalBroadcastManager, appelez getInstance().

Par exemple :

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

L'étape suivante consiste à gérer les objets de diffusion Intent entrants dans le composant qui a envoyé la requête de travail d'origine.

Recevoir des annonces d'état d'un JobIntentService

Pour recevoir des objets de diffusion Intent, utilisez une sous-classe de BroadcastReceiver. Dans la sous-classe, implémentez la méthode de rappel BroadcastReceiver.onReceive(), que LocalBroadcastManager appelle lorsqu'elle reçoit une Intent. LocalBroadcastManager transmet le Intent entrant à BroadcastReceiver.onReceive().

Par exemple :

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.
         */
...
    }
}

Une fois que vous avez défini l'élément BroadcastReceiver, vous pouvez définir des filtres qui correspondent à des actions, des catégories et des données spécifiques. Pour ce faire, créez un IntentFilter. Le premier extrait montre comment définir le filtre:

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

Pour enregistrer BroadcastReceiver et IntentFilter auprès du système, obtenez une instance de LocalBroadcastManager et appelez sa méthode registerReceiver(). L'extrait suivant montre comment enregistrer BroadcastReceiver et son 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);
        ...

Un seul élément BroadcastReceiver peut gérer plusieurs types d'objets Intent de diffusion, chacun ayant sa propre action. Cette fonctionnalité vous permet d'exécuter un code différent pour chaque action, sans avoir à définir un BroadcastReceiver distinct pour chaque action. Pour définir un autre IntentFilter pour le même BroadcastReceiver, créez le IntentFilter et répétez l'appel de registerReceiver(). Par exemple :

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

L'envoi d'une annonce Intent ne démarre pas et ne reprend pas de Activity. Le BroadcastReceiver d'une Activity reçoit et traite les objets Intent même lorsque votre application est en arrière-plan, mais ne la force pas au premier plan. Si vous souhaitez informer l'utilisateur d'un événement qui s'est produit en arrière-plan alors que votre application n'était pas visible, utilisez un Notification. Ne lancez jamais de Activity en réponse à une annonce Intent entrante.