Gérer la priorité audio

Au moins deux applications Android peuvent lire du contenu audio sur le même flux de sortie simultanément, et le système mélange tout. Bien que cela soit techniquement impressionnant, cela peut être très agaçant pour un utilisateur. Pour éviter que toutes les applications musicales ne soient lues en même temps, Android introduit le concept de priorité audio. Une seule application à la fois peut maintenir la priorité audio.

Lorsque votre application doit générer du contenu audio, elle doit demander la priorité audio. Une fois la mise au point effectuée, le son peut être émis. Toutefois, une fois le ciblage audio obtenu, il se peut que vous ne puissiez pas le conserver avant la fin de la lecture. Une autre application peut demander la sélection, ce qui prévaut sur votre mise en attente sur la priorité audio. Dans ce cas, votre application doit suspendre la lecture ou baisser son volume pour permettre aux utilisateurs d'entendre plus facilement la nouvelle source audio.

Avant Android 12 (niveau d'API 31), la sélection audio n'est pas gérée par le système. Par conséquent, bien que les développeurs d'applications soient encouragés à respecter les consignes concernant la priorité audio, si une application continue à lire un volume sonore fort même après avoir perdu la priorité audio sur un appareil équipé d'Android 11 (niveau d'API 30) ou version antérieure, le système ne peut pas l'empêcher. Toutefois, ce comportement nuit à l'expérience utilisateur et peut souvent conduire les utilisateurs à désinstaller l'application défaillante.

Une application audio bien conçue doit gérer la priorité audio conformément à ces consignes générales:

  • Appelez requestAudioFocus() immédiatement avant de commencer la lecture et vérifiez que l'appel renvoie AUDIOFOCUS_REQUEST_GRANTED. Appelez requestAudioFocus() dans le rappel onPlay() de votre session multimédia.

  • Lorsqu'une autre application obtient la priorité audio, arrêtez ou interrompez la lecture, ou baissez le volume (c'est-à-dire baisser) le volume.

  • Lorsque la lecture s'arrête (par exemple, lorsque l'application n'a plus rien à lire), abandonnez la sélection audio. Votre application n'a pas besoin d'abandonner le ciblage audio si l'utilisateur met en pause la lecture, mais peut la reprendre plus tard.

  • Utilisez AudioAttributes pour décrire le type de contenu audio lu par votre application. Par exemple, pour les applications qui lisent des contenus vocaux, spécifiez CONTENT_TYPE_SPEECH.

La sélection audio est gérée différemment selon la version d'Android en cours d'exécution:

Android 12 (niveau d'API 31) ou version ultérieure
La priorité audio est gérée par le système. Le système force la lecture audio d'une application à disparaître en fondu lorsqu'une autre application demande la priorité audio. Le système coupe également le son de la lecture audio lors de la réception d'un appel entrant.
Android 8.0 (niveau d'API 26) à Android 11 (niveau d'API 30)
La sélection audio n'est pas gérée par le système, mais inclut certaines modifications introduites à partir d'Android 8.0 (niveau d'API 26).
Android 7.1 (niveau d'API 25) ou version antérieure
La priorité audio n'est pas gérée par le système, et les applications gèrent la priorité audio à l'aide de requestAudioFocus() et abandonAudioFocus().

Focus audio sous Android 12 ou version ultérieure

Une application multimédia ou de jeu qui utilise la priorité audio ne doit pas lire de contenu audio une fois qu'elle n'est plus active. Sous Android 12 (niveau d'API 31) ou version ultérieure, le système applique ce comportement. Lorsqu'une application demande le ciblage audio alors qu'une autre application est ciblée et lit, le système force l'application en cours de lecture à disparaître en fondu. L'ajout du fondu à la fermeture permet une transition plus fluide lorsque vous passez d'une application à une autre.

Ce comportement de fondu se produit lorsque les conditions suivantes sont remplies:

  1. La première application en cours de lecture répond à tous ces critères:

  2. Une deuxième application demande la priorité audio avec AudioManager.AUDIOFOCUS_GAIN.

Lorsque ces conditions sont remplies, le système audio supprime la première application en fondu. À la fin de la fermeture en fondu, le système notifie la première application de la perte de sélection. Le son des lecteurs de l'application reste coupé jusqu'à ce que l'application demande à nouveau la priorité audio.

Comportements existants de la sélection audio

Vous devez également tenir compte de ces autres cas qui impliquent un changement de priorité audio.

Diminution automatique

La diminution automatique (réduction temporaire du niveau audio d'une application afin qu'une autre puisse être entendue clairement) a été introduite dans Android 8.0 (niveau d'API 26).

Ainsi, vous n'avez pas besoin d'implémenter la diminution dans votre application.

La diminution automatique se produit également lorsqu'une notification audio attire l'attention d'une application en cours de lecture. Le début de la lecture de la notification est synchronisé avec la fin de la plage de diminution.

La diminution automatique se produit lorsque les conditions suivantes sont remplies:

  1. La première application en cours de lecture répond à tous ces critères:

  2. Une deuxième application demande la priorité audio avec AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK.

Lorsque ces conditions sont remplies, le système audio écarte tous les joueurs actifs de la première application pendant que la deuxième application est active. Lorsque la deuxième application abandonne le focus, elle la retire. La première application n'est pas notifiée lorsqu'elle perd son focus. Elle n'a donc rien à faire.

Notez que la diminution automatique n'est pas effectuée lorsque l'utilisateur écoute du contenu vocal, car il risque de manquer une partie du programme. Par exemple, le guidage vocal pour les itinéraires routiers n'est pas abaissé.

Couper la lecture audio en cours pour les appels téléphoniques entrants

Certaines applications ne se comportent pas correctement et continuent de lire du contenu audio lors des appels téléphoniques. Cette situation oblige l'utilisateur à rechercher l'application incriminée, à la fermer ou à couper le son afin d'entendre son appel. Pour éviter cela, le système peut couper le son des autres applications lors d'un appel entrant. Le système appelle cette fonctionnalité lorsqu'un appel téléphonique entrant est reçu et qu'une application remplit les conditions suivantes:

  • L'application dispose de l'attribut d'utilisation AudioAttributes.USAGE_MEDIA ou AudioAttributes.USAGE_GAME.
  • L'application a bien demandé la priorité audio (toute acquisition de sélection) et lit du contenu audio.

Si une application poursuit la lecture pendant l'appel, le son de la lecture est coupé jusqu'à la fin de l'appel. Toutefois, si une application démarre la lecture pendant l'appel, le son du lecteur n'est pas coupé si l'utilisateur a lancé la lecture intentionnellement.

Focus audio sur Android 8.0 à Android 11

À partir d'Android 8.0 (niveau d'API 26), lorsque vous appelez requestAudioFocus(), vous devez fournir un paramètre AudioFocusRequest. AudioFocusRequest contient des informations sur le contexte audio et les fonctionnalités de votre application. Le système utilise ces informations pour gérer automatiquement le gain et la perte de ciblage audio. Pour libérer la sélection audio, appelez la méthode abandonAudioFocusRequest() qui accepte également AudioFocusRequest comme argument. Utilisez la même instance AudioFocusRequest lorsque vous demandez et abandonnez la sélection.

Pour créer un AudioFocusRequest, utilisez un AudioFocusRequest.Builder. Étant donné qu'une requête de sélection doit toujours spécifier le type de la requête, le type est inclus dans le constructeur du compilateur. Utilisez les méthodes du compilateur pour définir les autres champs de la requête.

Le champ FocusGain est obligatoire. Tous les autres champs sont facultatifs.

MéthodeNotes
setFocusGain() Ce champ est obligatoire dans chaque requête. Elle utilise les mêmes valeurs que le durationHint utilisé dans l'appel de requestAudioFocus() avant Android 8.0 : AUDIOFOCUS_GAIN, AUDIOFOCUS_GAIN_TRANSIENT, AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK ou AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE.
setAudioAttributes() AudioAttributes décrit le cas d'utilisation de votre application. Le système les examine lorsqu'une application gagne ou perd la priorité audio. Les attributs remplacent la notion de type de flux. Sous Android 8.0 (niveau d'API 26) et versions ultérieures, les types de flux pour toute opération autre que les commandes de volume sont obsolètes. Utilisez les mêmes attributs dans la requête de sélection que dans votre lecteur audio (comme illustré dans l'exemple suivant ce tableau).

Utilisez d'abord un AudioAttributes.Builder pour spécifier les attributs, puis utilisez cette méthode pour les attribuer à la requête.

Si aucune valeur n'est spécifiée, AudioAttributes est défini par défaut sur AudioAttributes.USAGE_MEDIA.

setWillPauseWhenDucked() Lorsqu'une autre application demande le ciblage avec AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, celle qui est ciblée ne reçoit généralement pas de rappel onAudioFocusChange(), car le système peut faire la diminution seul. Lorsque vous devez suspendre la lecture au lieu de baisser le volume, appelez setWillPauseWhenDucked(true), puis créez et définissez une OnAudioFocusChangeListener, comme décrit dans la section Atténuation automatique.
setAcceptsDelayedFocusGain() Une requête de sélection audio peut échouer lorsque le ciblage est verrouillé par une autre application. Cette méthode active le gain de sélection différée, c'est-à-dire la possibilité d'acquérir la sélection de manière asynchrone lorsqu'elle devient disponible.

Notez que l'obtention de la priorité différée ne fonctionne que si vous spécifiez également un AudioManager.OnAudioFocusChangeListener dans la requête audio, car votre application doit recevoir le rappel pour savoir que la sélection a été accordée.

setOnAudioFocusChangeListener() Un élément OnAudioFocusChangeListener n'est requis que si vous spécifiez également willPauseWhenDucked(true) ou setAcceptsDelayedFocusGain(true) dans la requête.

Il existe deux méthodes pour définir l'écouteur: l'une avec et l'autre sans argument de gestionnaire. Le gestionnaire est le thread sur lequel l'écouteur s'exécute. Si vous ne spécifiez pas de gestionnaire, le gestionnaire associé à l'élément Looper principal est utilisé.

L'exemple suivant montre comment utiliser un AudioFocusRequest.Builder pour créer un AudioFocusRequest, et demander et abandonner la priorité audio:

Kotlin

// initializing variables for audio focus and playback management
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run {
    setAudioAttributes(AudioAttributes.Builder().run {
        setUsage(AudioAttributes.USAGE_GAME)
        setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        build()
    })
    setAcceptsDelayedFocusGain(true)
    setOnAudioFocusChangeListener(afChangeListener, handler)
    build()
}
val focusLock = Any()

var playbackDelayed = false
var playbackNowAuthorized = false

// requesting audio focus and processing the response
val res = audioManager.requestAudioFocus(focusRequest)
synchronized(focusLock) {
    playbackNowAuthorized = when (res) {
        AudioManager.AUDIOFOCUS_REQUEST_FAILED -> false
        AudioManager.AUDIOFOCUS_REQUEST_GRANTED -> {
            playbackNow()
            true
        }
        AudioManager.AUDIOFOCUS_REQUEST_DELAYED -> {
            playbackDelayed = true
            false
        }
        else -> false
    }
}

// implementing OnAudioFocusChangeListener to react to focus changes
override fun onAudioFocusChange(focusChange: Int) {
    when (focusChange) {
        AudioManager.AUDIOFOCUS_GAIN ->
            if (playbackDelayed || resumeOnFocusGain) {
                synchronized(focusLock) {
                    playbackDelayed = false
                    resumeOnFocusGain = false
                }
                playbackNow()
            }
        AudioManager.AUDIOFOCUS_LOSS -> {
            synchronized(focusLock) {
                resumeOnFocusGain = false
                playbackDelayed = false
            }
            pausePlayback()
        }
        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
            synchronized(focusLock) {
                // only resume if playback is being interrupted
                resumeOnFocusGain = isPlaying()
                playbackDelayed = false
            }
            pausePlayback()
        }
        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
            // ... pausing or ducking depends on your app
        }
    }
}

Java

// initializing variables for audio focus and playback management
audioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);
playbackAttributes = new AudioAttributes.Builder()
        .setUsage(AudioAttributes.USAGE_GAME)
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .build();
focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
        .setAudioAttributes(playbackAttributes)
        .setAcceptsDelayedFocusGain(true)
        .setOnAudioFocusChangeListener(afChangeListener, handler)
        .build();
final Object focusLock = new Object();

boolean playbackDelayed = false;
boolean playbackNowAuthorized = false;

// requesting audio focus and processing the response
int res = audioManager.requestAudioFocus(focusRequest);
synchronized(focusLock) {
    if (res == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
        playbackNowAuthorized = false;
    } else if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
        playbackNowAuthorized = true;
        playbackNow();
    } else if (res == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
        playbackDelayed = true;
        playbackNowAuthorized = false;
    }
}

// implementing OnAudioFocusChangeListener to react to focus changes
@Override
public void onAudioFocusChange(int focusChange) {
    switch (focusChange) {
        case AudioManager.AUDIOFOCUS_GAIN:
            if (playbackDelayed || resumeOnFocusGain) {
                synchronized(focusLock) {
                    playbackDelayed = false;
                    resumeOnFocusGain = false;
                }
                playbackNow();
            }
            break;
        case AudioManager.AUDIOFOCUS_LOSS:
            synchronized(focusLock) {
                resumeOnFocusGain = false;
                playbackDelayed = false;
            }
            pausePlayback();
            break;
        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
            synchronized(focusLock) {
                // only resume if playback is being interrupted
                resumeOnFocusGain = isPlaying();
                playbackDelayed = false;
            }
            pausePlayback();
            break;
        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
            // ... pausing or ducking depends on your app
            break;
        }
    }
}

Diminution automatique

Sous Android 8.0 (niveau d'API 26), lorsqu'une autre application demande à sélectionner AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, le système peut baisser le volume et restaurer le volume sans appeler le rappel onAudioFocusChange() de l'application.

Bien que la diminution automatique soit acceptable pour les applications de lecture de musique et de vidéos, elle n'est pas utile pour lire du contenu parlé, comme dans une application de livre audio. Dans ce cas, l'application doit se mettre en pause.

Si vous souhaitez que votre application se mette en pause lorsqu'elle est invitée à baisser le volume au lieu de baisser le volume, créez un OnAudioFocusChangeListener avec une méthode de rappel onAudioFocusChange() qui implémente le comportement de pause/reprise souhaité. Appelez setOnAudioFocusChangeListener() pour enregistrer l'écouteur, puis setWillPauseWhenDucked(true) pour indiquer au système d'utiliser votre rappel plutôt que d'effectuer une diminution automatique.

Gain de mise au point retardé

Parfois, le système ne peut pas accorder une demande de ciblage audio, car celui-ci est "verrouillé" par une autre application, par exemple lors d'un appel téléphonique. Dans ce cas, requestAudioFocus() renvoie AUDIOFOCUS_REQUEST_FAILED. Dans ce cas, votre application ne doit pas lancer la lecture audio, car elle n'a pas été ciblée.

La méthode setAcceptsDelayedFocusGain(true), qui permet à votre application de gérer une requête de sélection de manière asynchrone Lorsque cet indicateur est défini, une requête effectuée lorsque le focus est verrouillé renvoie AUDIOFOCUS_REQUEST_DELAYED. Lorsque la condition qui a verrouillé le ciblage audio n'existe plus, par exemple à la fin d'un appel téléphonique, le système accorde la requête de sélection en attente et appelle onAudioFocusChange() pour avertir votre application.

Pour gérer ce décalage, vous devez créer un OnAudioFocusChangeListener avec une méthode de rappel onAudioFocusChange() qui implémente le comportement souhaité et enregistrer l'écouteur en appelant setOnAudioFocusChangeListener().

Focus audio sous Android 7.1 ou version antérieure

Lorsque vous appelez requestAudioFocus(), vous devez spécifier une indication de durée, qui peut être respectée par une autre application actuellement active et en cours de lecture:

  • Demandez un ciblage audio permanent (AUDIOFOCUS_GAIN) lorsque vous prévoyez de lire du contenu audio dans un avenir proche (par exemple, lors de la lecture de musique) et que vous vous attendez à ce que le conteneur précédent de sélection audio arrête la lecture.
  • Demande une sélection temporaire (AUDIOFOCUS_GAIN_TRANSIENT) lorsque vous prévoyez de lire du contenu audio pendant une courte période et que le conteneur précédent met en pause la lecture.
  • Demandez une mise au point temporaire avec diminution (AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) pour indiquer que vous ne prévoyez de lire du contenu audio que pendant une courte période et que le propriétaire de la sélection précédent peut continuer à lire si la sortie audio est réduite. Les deux sorties audio sont mélangées dans le flux audio. La diminution est particulièrement adaptée aux applications qui utilisent le flux audio de manière intermittente, par exemple pour les itinéraires routiers audibles.

La méthode requestAudioFocus() nécessite également un AudioManager.OnAudioFocusChangeListener. Cet écouteur doit être créé dans l'activité ou le service propriétaire de votre session multimédia. Il implémente le rappel onAudioFocusChange() que votre application reçoit lorsqu'une autre application acquiert ou abandonne la priorité audio.

L'extrait suivant demande une sélection audio permanente sur le flux STREAM_MUSIC et enregistre un OnAudioFocusChangeListener pour gérer les modifications ultérieures de la sélection audio. (L'écouteur de modifications est abordé dans la section Répondre à un changement de ciblage audio.)

Kotlin

audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
lateinit var afChangeListener AudioManager.OnAudioFocusChangeListener

...
// Request audio focus for playback
val result: Int = audioManager.requestAudioFocus(
        afChangeListener,
        // Use the music stream.
        AudioManager.STREAM_MUSIC,
        // Request permanent focus.
        AudioManager.AUDIOFOCUS_GAIN
)

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // Start playback
}

Java

AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
AudioManager.OnAudioFocusChangeListener afChangeListener;

...
// Request audio focus for playback
int result = audioManager.requestAudioFocus(afChangeListener,
                             // Use the music stream.
                             AudioManager.STREAM_MUSIC,
                             // Request permanent focus.
                             AudioManager.AUDIOFOCUS_GAIN);

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // Start playback
}

Une fois la lecture terminée, appelez abandonAudioFocus().

Kotlin

audioManager.abandonAudioFocus(afChangeListener)

Java

// Abandon audio focus when playback complete
audioManager.abandonAudioFocus(afChangeListener);

Le système est ainsi informé que vous n'avez plus besoin de vous concentrer et annule l'enregistrement du OnAudioFocusChangeListener associé. Si vous avez demandé une mise au point temporaire, une application qui s'est mise en pause ou qui a baissé peut être informée qu'elle peut continuer à lire ou restaurer son volume.

Répondre à un changement de mise au point audio

Lorsqu'une application acquiert le ciblage audio, elle doit être en mesure de la libérer lorsqu'une autre application demande le ciblage audio pour elle-même. Dans ce cas, votre application reçoit un appel à la méthode onAudioFocusChange() dans le AudioFocusChangeListener que vous avez spécifié lorsque l'application a appelé requestAudioFocus().

Le paramètre focusChange transmis à onAudioFocusChange() indique le type de modification en cours. Il correspond à l'indication de durée utilisée par l'application qui doit être ciblée. Votre application doit répondre de manière appropriée.

Perte temporaire de focalisation
Si le changement de mise au point est temporaire (AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK ou AUDIOFOCUS_LOSS_TRANSIENT), votre application doit diminuer (si vous n'utilisez pas la Atténuation automatique) ou mettre la lecture en pause, mais elle doit conserver le même état.

En cas de perte temporaire de focalisation audio, vous devez continuer à surveiller les changements de focalisation audio et être prêt à reprendre la lecture normale une fois la mise au point rétablie. Lorsque l'application bloquante abandonne le ciblage, vous recevez un rappel (AUDIOFOCUS_GAIN). À ce stade, vous pouvez rétablir le volume à la normale ou redémarrer la lecture.

Perte permanente de la mise au point
Si la perte de priorité audio est permanente (AUDIOFOCUS_LOSS), une autre application lit du contenu audio. Votre application devrait immédiatement suspendre la lecture, car elle ne recevra jamais de rappel AUDIOFOCUS_GAIN. Pour redémarrer la lecture, l'utilisateur doit effectuer une action explicite, comme appuyer sur la commande de transport dans une notification ou une interface d'application.

L'extrait de code suivant montre comment implémenter OnAudioFocusChangeListener et son rappel onAudioFocusChange(). Notez l'utilisation d'un Handler pour retarder le rappel d'arrêt en cas de perte permanente de la priorité audio.

Kotlin

private val handler = Handler()
private val afChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange ->
    when (focusChange) {
        AudioManager.AUDIOFOCUS_LOSS -> {
            // Permanent loss of audio focus
            // Pause playback immediately
            mediaController.transportControls.pause()
            // Wait 30 seconds before stopping playback
            handler.postDelayed(delayedStopRunnable, TimeUnit.SECONDS.toMillis(30))
        }
        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
            // Pause playback
        }
        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
            // Lower the volume, keep playing
        }
        AudioManager.AUDIOFOCUS_GAIN -> {
            // Your app has been granted audio focus again
            // Raise volume to normal, restart playback if necessary
        }
    }
}

Java

private Handler handler = new Handler();
AudioManager.OnAudioFocusChangeListener afChangeListener =
  new AudioManager.OnAudioFocusChangeListener() {
    public void onAudioFocusChange(int focusChange) {
      if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
        // Permanent loss of audio focus
        // Pause playback immediately
        mediaController.getTransportControls().pause();
        // Wait 30 seconds before stopping playback
        handler.postDelayed(delayedStopRunnable,
          TimeUnit.SECONDS.toMillis(30));
      }
      else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
        // Pause playback
      } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
        // Lower the volume, keep playing
      } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
        // Your app has been granted audio focus again
        // Raise volume to normal, restart playback if necessary
      }
    }
  };

Le gestionnaire utilise un élément Runnable qui se présente comme suit:

Kotlin

private var delayedStopRunnable = Runnable {
    mediaController.transportControls.stop()
}

Java

private Runnable delayedStopRunnable = new Runnable() {
    @Override
    public void run() {
        getMediaController().getTransportControls().stop();
    }
};

Pour vous assurer que l'arrêt retardé ne se déclenche pas si l'utilisateur redémarre la lecture, appelez mHandler.removeCallbacks(mDelayedStopRunnable) en réponse à tout changement d'état. Par exemple, appelez removeCallbacks() dans le onPlay(), le onSkipToNext(), etc. du rappel. Vous devez également appeler cette méthode dans le rappel onDestroy() de votre service lors du nettoyage des ressources utilisées par votre service.