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

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

Signaler l'état à partir d'un JobIntentService

Pour envoyer l'état d'une demande de travail dans une JobIntentService vers autre commencez par créer un Intent contenant l'état dans son les données étendues. Si vous le souhaitez, vous pouvez ajouter un URI d'action et de données à cet Intent

Ensuite, envoyez Intent en appelant LocalBroadcastManager.sendBroadcast() Le Intent est alors envoyé composant de votre application qui a été enregistré pour le recevoir. Pour obtenir une instance de LocalBroadcastManager, appelez getInstance()

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 Intent de diffusion entrante dans le composant qui a envoyé la demande de travail d'origine.

Recevoir des annonces d'état depuis un JobIntentService

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

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

Après avoir défini 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 avec le système, récupère une instance de LocalBroadcastManager et l'appeler registerReceiver() . L'extrait suivant montre comment enregistrer le 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 même BroadcastReceiver peut gérer plusieurs types de diffusion. Intent, chacun avec sa propre action. Cette fonctionnalité vous permet un code distinct pour chaque action, sans avoir à définir BroadcastReceiver pour chaque action. Pour définir une autre IntentFilter pour la même valeur BroadcastReceiver, créez les IntentFilter et répéter l'appel au registerReceiver() 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 diffusion Intent ne permet pas de lancer ni de reprendre une Activity Le BroadcastReceiver d'une Activity reçoit et traite même les objets Intent lorsque votre application est exécutée en arrière-plan, mais ne la force pas au premier plan. Si vous vous souhaitez informer l'utilisateur d'un événement qui s'est produit en arrière-plan alors que votre application visible, utilisez un Notification. Ne démarrez jamais une Activity en réponse à une diffusion entrante Intent