Gérer la priorité audio

Deux applications Android ou plus peuvent lire du contenu audio sur le même flux de sortie simultanément, et le système mélange le 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 sélection audio. Une seule application peut avoir la priorité audio à la fois.

Lorsque votre application doit diffuser du contenu audio, elle doit demander la priorité audio. Lorsqu'il est sélectionné, il peut émettre un son. Toutefois, une fois que vous avez acquis la sélection audio, vous ne pourrez peut-être pas la conserver jusqu'à la fin de la lecture. Une autre application peut demander la priorité, ce qui préempte votre priorité audio. Dans ce cas, votre application doit mettre en pause la lecture ou baisser le 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. Ainsi, même si les développeurs d'applications sont encouragés à respecter les consignes de gestion de la sélection audio, si une application continue à émettre un son fort même après avoir perdu la sélection audio sur un appareil équipé d'Android 11 (niveau d'API 30) ou version antérieure, le système ne peut pas l'en empêcher. Toutefois, ce comportement de l'application nuit à l'expérience utilisateur et peut souvent inciter les utilisateurs à désinstaller l'application qui ne se comporte pas correctement.

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

  • Appelez requestAudioFocus() juste avant de commencer à lire 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 mettez en pause la lecture, ou baissez le volume.

  • Lorsque la lecture s'arrête (par exemple, lorsque l'application n'a plus rien à lire), abandonnez la priorité audio. Votre application n'a pas besoin d'abandonner la priorité audio si l'utilisateur met en pause la lecture, mais qu'il 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 exécutée :

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 à s'estomper lorsqu'une autre application demande la priorité audio. Le système coupe également la lecture audio lorsqu'un appel entrant est reçu.
Android 8.0 (niveau d'API 26) à Android 11 (niveau d'API 30)
La mise au point 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. Les applications gèrent la priorité audio à l'aide de requestAudioFocus() et de abandonAudioFocus().

Focus audio sous Android 12 et versions ultérieures

Une application multimédia ou de jeu qui utilise la priorité audio ne doit pas lire de contenu audio après avoir perdu la priorité. Sous Android 12 (niveau d'API 31) ou version ultérieure, le système applique ce comportement. Lorsqu'une application demande la priorité audio alors qu'une autre application l'a déjà et est en cours de lecture, le système force l'application en cours de lecture à s'estomper. L'ajout du fondu permet une transition plus fluide 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 remplit tous les critères suivants :

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

Lorsque ces conditions sont remplies, le système audio effectue un fondu de la première application. À la fin du fondu, le système informe la première application de la perte de sélection. Les lecteurs de l'application restent coupés jusqu'à ce que l'application demande à nouveau la priorité audio.

Comportements existants de la priorité audio

Vous devez également connaître les autres cas impliquant un changement de niveau de priorité audio.

Atténuation automatique

La diminution automatique (réduction temporaire du niveau audio d'une application pour que l'autre soit clairement audible) a été introduite dans Android 8.0 (niveau d'API 26).

En laissant le système implémenter l'atténuation, vous n'avez pas besoin de l'implémenter dans votre application.

L'atténuation automatique se produit également lorsqu'une notification audio prend le focus d'une application en cours de lecture. Le début de la lecture de la notification est synchronisé avec la fin de la rampe d'atténuation.

La réduction automatique du volume se produit lorsque les conditions suivantes sont remplies :

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

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

Lorsque ces conditions sont remplies, le système audio réduit le volume de tous les lecteurs actifs de la première application pendant que la deuxième application est active. Lorsque la deuxième application abandonne la sélection, elle les rétablit. La première application n'est pas avertie lorsqu'elle perd le focus. Elle n'a donc rien à faire.

Notez que l'atténuation automatique n'est pas effectuée lorsque l'utilisateur écoute du contenu vocal, car il pourrait manquer une partie du programme. Par exemple, le guidage vocal pour les itinéraires en voiture n'est pas atténué.

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 pendant les appels téléphoniques. Dans ce cas, l'utilisateur doit trouver l'application incriminée, puis la couper ou la quitter pour entendre son appel. Pour éviter cela, le système peut couper le son des autres applications lorsqu'un appel est 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 possède l'attribut d'utilisation AudioAttributes.USAGE_MEDIA ou AudioAttributes.USAGE_GAME.
  • L'application a bien demandé la priorité audio (tout gain de priorité) et lit du contenu audio.

Si une application continue de lire du contenu pendant l'appel, la lecture est coupée jusqu'à la fin de l'appel. Toutefois, si une application démarre la lecture pendant l'appel, le son de ce lecteur n'est pas coupé, car on suppose que l'utilisateur a démarré la lecture intentionnellement.

Focus audio d'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 la sélection audio. Pour libérer la sélection audio, appelez la méthode abandonAudioFocusRequest(), qui accepte également un 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 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éthodeRemarques
setFocusGain() Ce champ est obligatoire dans chaque requête. Il prend les mêmes valeurs que le durationHint utilisé dans l'appel à 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 obtient et perd la sélection audio. Les attributs remplacent la notion de type de flux. Sur Android 8.0 (niveau d'API 26) ou version ultérieure, les types de flux pour toute opération autre que le contrôle du volume sont obsolètes. Utilisez les mêmes attributs dans la requête de focus que ceux que vous utilisez dans votre lecteur audio (comme illustré dans l'exemple suivant ce tableau).

Utilisez un AudioAttributes.Builder pour spécifier d'abord 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 la priorité avec AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, l'application qui a la priorité ne reçoit généralement pas de rappel onAudioFocusChange(), car le système peut effectuer l'atténuation lui-même. Lorsque vous devez mettre en pause la lecture plutôt que de réduire le volume, appelez setWillPauseWhenDucked(true), puis créez et définissez un OnAudioFocusChangeListener, comme décrit dans la section Réduction automatique du volume.
setAcceptsDelayedFocusGain() Une demande de priorité audio peut échouer lorsque la priorité est verrouillée par une autre application. Cette méthode permet d'obtenir la priorité de manière différée : la possibilité d'acquérir la priorité de manière asynchrone lorsqu'elle devient disponible.

Notez que le gain de priorité différé 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 priorité a été accordée.

setOnAudioFocusChangeListener() Un 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 un argument de gestionnaire et l'autre sans. Le gestionnaire est le thread sur lequel l'écouteur s'exécute. Si vous ne spécifiez pas de gestionnaire, celui associé au Looper principal est utilisé.

L'exemple suivant montre comment utiliser un AudioFocusRequest.Builder pour créer un AudioFocusRequest, puis 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;
        }
    }
}

Atténuation automatique

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

Bien que l'atténuation automatique soit un comportement acceptable pour les applications de lecture de musique et de vidéo, elle n'est pas utile lors de la lecture de contenus parlés, comme dans une application de livre audio. Dans ce cas, l'application doit plutôt être mise en pause.

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

Gain de focus différé

Parfois, le système ne peut pas accorder une demande de priorité audio, car la priorité est "verrouillée" 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 procéder à la lecture audio, car elle n'a pas obtenu la sélection.

La méthode setAcceptsDelayedFocusGain(true), qui permet à votre application de gérer une demande de sélection de manière asynchrone. Lorsque cette option est définie, une requête effectuée lorsque la mise au point est verrouillée renvoie AUDIOFOCUS_REQUEST_DELAYED. Lorsque la condition qui a verrouillé la mise au point audio n'existe plus, par exemple lorsqu'un appel téléphonique se termine, le système accorde la demande de mise au point en attente et appelle onAudioFocusChange() pour en informer votre application.

Pour gérer le gain de focus différé, vous devez créer un OnAudioFocusChangeListener avec une méthode de rappel onAudioFocusChange() qui implémente le comportement souhaité, puis enregistrer l'écouteur en appelant setOnAudioFocusChangeListener().

Priorité audio dans 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 qui est actuellement active et en cours de lecture :

  • Demandez la priorité audio permanente (AUDIOFOCUS_GAIN) lorsque vous prévoyez de lire du contenu audio dans un avenir proche (par exemple, lorsque vous écoutez de la musique) et que vous vous attendez à ce que le détenteur précédent de la priorité audio arrête la lecture.
  • Demandez une priorité temporaire (AUDIOFOCUS_GAIN_TRANSIENT) lorsque vous prévoyez de lire du contenu audio pendant une courte période et que vous vous attendez à ce que le détenteur précédent mette la lecture en pause.
  • Demandez une priorité temporaire avec ducking (AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) pour indiquer que vous prévoyez de lire du contenu audio pendant une courte période et que le propriétaire de la priorité précédente peut continuer à lire s'il "ducke" (baisse) sa sortie audio. Les deux sorties audio sont mixées dans le flux audio. La réduction du volume est particulièrement adaptée aux applications qui utilisent le flux audio par intermittence, par exemple pour les instructions de navigation vocales.

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

L'extrait de code 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 modification est abordé dans la section Répondre à un changement de sélection 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
}

Lorsque vous avez terminé la lecture, appelez abandonAudioFocus().

Kotlin

audioManager.abandonAudioFocus(afChangeListener)

Java

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

Cela indique au système que vous n'avez plus besoin de la sélection audio et annule l'enregistrement du OnAudioFocusChangeListener associé. Si vous avez demandé une sélection temporaire, cela indique à une application qui a été mise en pause ou dont le volume a été réduit qu'elle peut continuer la lecture ou rétablir le volume.

Répondre à un changement de sélection audio

Lorsqu'une application acquiert la priorité audio, elle doit pouvoir la libérer lorsqu'une autre application la demande 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 qui se produit. Il correspond à l'indice de durée utilisé par l'application qui acquiert la sélection. Votre application doit réagir de manière appropriée.

Perte de concentration temporaire
Si le changement de niveau de priorité est temporaire (AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK ou AUDIOFOCUS_LOSS_TRANSIENT), votre application doit réduire le volume (si vous n'utilisez pas la réduction automatique du volume) ou mettre en pause la lecture, mais conserver le même état.

En cas de perte temporaire de la priorité audio, vous devez continuer à surveiller les changements de priorité audio et être prêt à reprendre la lecture normale lorsque vous récupérez la priorité. Lorsque l'application bloquante abandonne la sélection, vous recevez un rappel (AUDIOFOCUS_GAIN). À ce stade, vous pouvez rétablir le volume au niveau normal ou redémarrer la lecture.

Perte définitive de la mise au point
Si la perte de priorité audio est permanente (AUDIOFOCUS_LOSS), une autre application lit du contenu audio. Votre application doit suspendre la lecture immédiatement, 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 lecture dans une notification ou dans l'interface utilisateur de l'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 sélection 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 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 différé 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 les méthodes onPlay(), onSkipToNext(), etc. de votre rappel. Vous devez également appeler cette méthode dans le rappel onDestroy() de votre service lorsque vous nettoyez les ressources utilisées par votre service.