Gérer la priorité audio

Deux applications Android ou plus peuvent lire simultanément du contenu audio sur le même flux de sortie, 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 diffusées en même temps, Android introduit l'idée de mise au point audio. Une seule application peut être en mode focus audio à la fois.

Lorsque votre application doit diffuser du contenu audio, elle doit demander la priorité audio. Lorsqu'il est en mode focus, il peut diffuser du son. Toutefois, une fois que vous avez acquis la priorité audio, vous ne pourrez peut-être pas la conserver jusqu'à la fin de votre lecture. Une autre application peut demander la sélection, ce qui préempte votre maintien de la priorité audio. Dans ce cas, votre application doit mettre en pause 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, même si les développeurs d'applications sont encouragés à respecter les consignes relatives à la sélection audio, si une application continue de diffuser du contenu audio 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'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 fonctionne pas correctement.

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 à jouer 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 la lecture en pause, mais qu'il peut la reprendre plus tard.

  • Utilisez AudioAttributes pour décrire le type d'audio lu par votre application. Par exemple, pour les applications qui lisent de la parole, 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 le son de la lecture audio lorsqu'un appel entrant est reçu.
Android 8.0 (niveau d'API 26) à Android 11 (niveau d'API 30)
Le focus audio n'est pas géré 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 la gèrent à l'aide des éléments requestAudioFocus() et abandonAudioFocus().

Mise au point 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 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 est active et en cours de lecture, le système force la lecture de l'application en cours à s'estomper. L'ajout du fondu offre 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 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 atténue la première application. À la fin de l'atténuation, le système informe la première application de la perte de focus. 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 tenir compte des autres cas impliquant un changement de focus audio.

Atténuation automatique

La réduction automatique du volume (qui consiste à réduire temporairement le niveau audio d'une application pour que l'autre soit entendu clairement) a été introduite dans Android 8.0 (niveau d'API 26).

En demandant au système d'implémenter le masquage, vous n'avez pas besoin de l'implémenter dans votre application.

Le masquage automatique se produit également lorsqu'une notification audio capte 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 rampe de masquage.

Le masquage automatique 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 AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK.

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

Notez que le masquage automatique n'est pas effectué 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 masqué.

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

Certaines applications ne se comportent pas correctement et continuent de diffuser du contenu audio pendant les appels téléphoniques. Cette situation oblige l'utilisateur à rechercher et à couper le son ou à quitter l'application incriminée pour entendre son appel. Pour éviter cela, le système peut couper le son des autres applications lorsqu'un appel entrant est reçu. 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 demandé avec succès la priorité audio (tout gain de priorité) et lit de l'audio.

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

Mise au point audio sous 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 prend également un AudioFocusRequest comme argument. Utilisez la même instance AudioFocusRequest lorsque vous demandez et abandonnez la mise au point.

Pour créer un AudioFocusRequest, utilisez un AudioFocusRequest.Builder. Étant donné qu'une requête de mise au point doit toujours spécifier le type de la requête, le type est inclus dans le constructeur du générateur. Utilisez les méthodes du générateur 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. Il prend les mêmes valeurs que l'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 gagne et perd la sélection audio. Les attributs remplacent la notion de type de flux. Sous Android 8.0 (niveau d'API 26) ou version ultérieure, 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 mise au point que ceux que vous utilisez 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 attribuer les attributs à 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 sélection avec AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, l'application sélectionnée ne reçoit généralement pas de rappel onAudioFocusChange(), car le système peut effectuer le masquage 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 Atténuation automatique.
setAcceptsDelayedFocusGain() Une demande de priorité audio peut échouer lorsque la priorité est verrouillée par une autre application. Cette méthode permet d'obtenir un gain de priorité différé: la possibilité d'acquérir de manière asynchrone la priorité lorsqu'elle devient disponible.

Notez que l'obtention de la sélection 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 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é au Looper principal est utilisé.

L'exemple suivant montre comment utiliser un AudioFocusRequest.Builder pour créer un AudioFocusRequest, puis demander et abandonner la sélection 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 le masquage automatique soit un comportement acceptable pour les applications de lecture de musique et de vidéo, il n'est pas utile lorsque vous lisez du contenu parlé, 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 soit mise en pause lorsqu'elle est invitée à se fondre plutôt que de baisser son volume, 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 un masquage automatique.

Gain de mise au point différé

Parfois, le système ne peut pas accorder une demande de priorité audio, car elle 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 poursuivre la lecture audio, car elle n'a pas été mise au premier plan.

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

Pour gérer le gain de focus retardé, 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().

Priorité audio sous Android 7.1 et versions antérieures

Lorsque vous appelez requestAudioFocus(), vous devez spécifier un indice de durée, qui peut être accepté par une autre application qui détient actuellement la sélection et la lecture:

  • Demandez une 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 prévoyez que le détenteur précédent de la priorité audio arrêtera de lire.
  • Demandez une mise au point temporaire (AUDIOFOCUS_GAIN_TRANSIENT) lorsque vous ne prévoyez de lire de l'audio que pendant une courte période et que vous attendez que le détenteur précédent mette la lecture en pause.
  • Demandez une sélection temporaire avec masquage (AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) pour indiquer que vous ne prévoyez de lire de l'audio que pendant une courte période et que le propriétaire précédent de la sélection peut continuer à lire si son flux audio est masqué (baissé). Les deux sorties audio sont mélangées dans le flux audio. Le masquage est particulièrement adapté aux applications qui utilisent le flux audio de manière intermittente, par exemple pour les itinéraires vocaux.

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 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 mise au point audio permanente sur le flux STREAM_MUSIC et enregistre un OnAudioFocusChangeListener pour gérer les modifications ultérieures de la mise au point audio. (L'écouteur de modification est décrit dans la section Répondre à un changement de focus 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 informe le système que vous n'avez plus besoin de la sélection et désinscrit le OnAudioFocusChangeListener associé. Si vous avez demandé un focus temporaire, une application qui a été mise en pause ou atténuée sera avertie qu'elle peut continuer la lecture ou restaurer son volume.

Répondre à un changement de priorité audio

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

Perte de concentration temporaire
Si le changement de focus est temporaire (AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK ou AUDIOFOCUS_LOSS_TRANSIENT), votre application doit se mettre en sourdine (si vous ne vous appuyez pas sur la mise en sourdine automatique) ou suspendre 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 la récupérez. Lorsque l'application bloquante abandonne la sélection, vous recevez un rappel (AUDIOFOCUS_GAIN). À ce stade, vous pouvez rétablir le volume à son niveau normal ou redémarrer la lecture.

Perte définitive de la concentration
Si la perte de priorité audio est permanente (AUDIOFOCUS_LOSS), une autre application lit du contenu audio. Votre application doit suspendre immédiatement 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 le bouton de lecture dans une notification ou 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 à toute modification d'état. Par exemple, appelez removeCallbacks() dans 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.