Due o più app per Android possono riprodurre audio nello stesso stream di output in contemporanea e il sistema mescola tutto insieme. Anche se impressionante dal punto di vista tecnico, può essere molto aggravante per un utente. Per evitare ogni di musica in esecuzione contemporaneamente, Android introduce l'idea di al focus. Solo un'app può mantenere lo stato attivo dell'audio alla volta.
Quando la tua app deve produrre audio, deve richiedere la messa a fuoco audio. Quando ha a fuoco, può riprodurre suoni. Tuttavia, una volta acquisito il focus audio, potresti non essere in grado di tenerlo attivo fino a quando non finisci di giocare. Un'altra app può richiedere lo stato attivo, prerilascia il blocco sul focus audio. In questo caso, l'app dovrebbe essere messa in pausa o abbassarne il volume per consentire agli utenti di sentire più facilmente la nuova sorgente audio.
Prima di Android 12 (livello API 31), il focus audio non è gestito dal sistema. Quindi, mentre gli sviluppatori di app sono invitati a rispettare le linee guida relative agli audio, se un'app continua a riprodurre ad alto volume anche dopo aver perso l'audio su un dispositivo con Android 11 (livello API 30) o versioni precedenti, il sistema non può evitarlo. Tuttavia, questo comportamento dell'app determina un'esperienza utente negativa e spesso può comportare di disinstallare l'app che funziona in modo anomalo.
Un'app audio ben progettata dovrebbe gestire il focus audio in base a queste caratteristiche generali linee guida:
Chiama
requestAudioFocus()
subito prima di iniziare a giocare e verifica che la chiamata restituisceAUDIOFOCUS_REQUEST_GRANTED
Fai la chiamata arequestAudioFocus()
nel callbackonPlay()
della sessione multimediale.Quando un'altra app acquisisce la priorità dell'audio, interrompe o mette in pausa la riproduzione o riduce abbassare) il volume.
Quando la riproduzione si interrompe (ad esempio, quando nell'app non c'è più spazio da riprodurre), per abbandonare l'audio attivo. La tua app non deve abbandonare lo stato attivo dell'audio se l'utente mette in pausa la riproduzione, ma potrebbe riprendere la riproduzione in un secondo momento.
Utilizza
AudioAttributes
per descrivere il tipo di audio riprodotto dall'app. Ad esempio, per le app che riproducono il parlato, specificareCONTENT_TYPE_SPEECH
Lo stato attivo dell'audio viene gestito in modo diverso a seconda della versione di Android che è in esecuzione:
- Android 12 (livello API 31) o versioni successive
- Il focus dell'audio è gestito dal sistema. Il sistema forza la riproduzione audio da un un'app in dissolvenza quando un'altra app richiede il focus audio. Il sistema disattiva anche la riproduzione audio quando ricevi una chiamata.
- Da Android 8.0 (livello API 26) ad Android 11 (livello API 30)
- Il focus audio non è gestito dal sistema, ma include alcune modifiche che sono state introdotta a partire da Android 8.0 (livello API 26).
- Android 7.1 (livello API 25) e versioni precedenti
- La messa a fuoco audio non è gestita dal sistema e le app gestiscono la messa a fuoco audio utilizzando
il
requestAudioFocus()
eabandonAudioFocus()
.
Focus audio in Android 12 e versioni successive
Un'app di giochi o contenuti multimediali che utilizza l'audio attivo non dovrebbe riprodurre audio dopo aver perso il focus. In Android 12 (livello API 31) e versioni successive, il sistema applica questa comportamento degli utenti. Quando un'app richiede lo stato attivo per l'audio mentre un'altra app ne ha è in riproduzione, il sistema forza la dissolvenza dell'app in riproduzione. L'aggiunta della classe la dissolvenza in uscita garantisce una transizione più fluida da un'app all'altra.
Questo comportamento di dissolvenza in uscita si verifica quando vengono soddisfatte le seguenti condizioni:
La prima app attualmente in riproduzione soddisfa tutti i seguenti criteri:
- L'app include
AudioAttributes.USAGE_MEDIA
oppure Attributo di utilizzoAudioAttributes.USAGE_GAME
. - L'app ha richiesto la messa a fuoco audio con
AudioManager.AUDIOFOCUS_GAIN
. - L'app non sta riproducendo audio con il tipo di contenuti
AudioAttributes.CONTENT_TYPE_SPEECH
.
- L'app include
Una seconda app richiede il focus audio con
AudioManager.AUDIOFOCUS_GAIN
.
Quando queste condizioni sono soddisfatte, la prima app del sistema audio viene disattivata. Al alla fine della dissolvenza in uscita, il sistema avvisa la prima app della perdita di messa a fuoco. L'app l'audio dei lettori rimane disattivato finché l'app non richiede di nuovo lo stato attivo dell'audio.
Comportamenti esistenti del focus audio
Dovresti inoltre essere a conoscenza di questi altri casi che prevedono un cambio audio il focus.
Attenuazione automatica automatica
Attenuazione automatica automatica (riduzione temporanea del livello audio di un'app per un'altra si può sentire chiaramente) è stata introdotta in Android 8.0 (livello API 26).
Poiché il sistema implementa il attenuazione automatica, non sarà necessario implementarla la tua app.
Attenuazione automatica automatica si verifica anche quando una notifica audio raggiunge l'obiettivo da un'app di riproduzione. L'inizio della riproduzione della notifica è sincronizzato con la fine della rampa per abbattersi.
Attenuazione automatica automatica si verifica quando si verificano le seguenti condizioni:
La prima app attualmente in riproduzione soddisfa tutti i seguenti criteri:
- L'app ha richiesto correttamente il focus audio con qualsiasi tipo di focus incremento.
- L'app non sta riproducendo audio con il tipo di contenuti
AudioAttributes.CONTENT_TYPE_SPEECH
. - L'app non è stata impostata
AudioFocusRequest.Builder.setWillPauseWhenDucked(true)
Una seconda app richiede il focus audio con
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
Quando queste condizioni sono soddisfatte, il sistema audio abbassa tutti i player attivi di la prima app, mentre la seconda con lo stato attivo. Quando la seconda app abbandona il focus, li rimuove. La prima app non riceve una notifica quando perde lo stato attivo. in modo che non debba fare nulla.
Tieni presente che l'attenuazione automatica non viene eseguita quando l'utente ascolta contenuti vocali, perché l'utente potrebbe perdere parte del programma. Ad esempio: la guida vocale per le indicazioni stradali non è oscurata.
Disattiva la riproduzione audio corrente per le telefonate in arrivo
Alcune app non funzionano correttamente e continuano a riprodurre l'audio durante le telefonate. Questa situazione costringe l'utente a trovare l'app in questione e a disattivarne l'audio o a chiuderla per ascoltare la loro chiamata. Per evitarlo, il sistema può disattivare l'audio di altri app durante una chiamata in arrivo. Il sistema richiama questa funzione quando quando si riceve una telefonata e un'app soddisfa le seguenti condizioni:
- L'app include l'
AudioAttributes.USAGE_MEDIA
o Attributo di utilizzoAudioAttributes.USAGE_GAME
. - L'app ha richiesto la messa a fuoco audio (qualsiasi guadagno) e la riproduzione è in corso audio.
Se la riproduzione di un'app continua durante la chiamata, la riproduzione viene disattivata fino a quando termina la chiamata. Tuttavia, se la riproduzione di un'app si avvia durante la chiamata, il player non viene disattivato, supponendo che l'utente abbia avviato intenzionalmente la riproduzione.
Focus audio da Android 8.0 ad Android 11
A partire da Android 8.0 (livello API 26), quando chiami
requestAudioFocus()
devi fornire un parametro AudioFocusRequest
. AudioFocusRequest
Contiene informazioni sul contesto audio e sulle funzionalità della tua app. La
sistema utilizza queste informazioni per gestire il guadagno e la perdita dell'audio
automaticamente. Per rilasciare lo stato attivo dell'audio, chiama il metodo
abandonAudioFocusRequest()
che accetta anche AudioFocusRequest
come argomento. Usa lo stesso
AudioFocusRequest
sia quando richiedi che abbandoni lo stato attivo.
Per creare una AudioFocusRequest
, usa un
AudioFocusRequest.Builder
. Poiché una richiesta di messa a fuoco deve
specificare sempre il tipo di richiesta, il tipo è incluso nel costruttore
per lo strumento di creazione. Utilizza i metodi del builder per impostare gli altri campi del
richiesta.
Il campo FocusGain
è obbligatorio. tutti gli altri campi sono facoltativi.
Metodo | Note |
---|---|
setFocusGain()
|
Questo campo è obbligatorio in tutte le richieste. Prende gli stessi valori di
durationHint usato nella chiamata precedente ad Android 8.0 a requestAudioFocus() :
AUDIOFOCUS_GAIN AUDIOFOCUS_GAIN_TRANSIENT
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK o AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE .
|
setAudioAttributes()
|
AudioAttributes descrive il caso d'uso della tua app. La
di sistema li esamina quando un'app acquisisce e perde la messa a fuoco audio. Attributi
prevalgono sulla nozione di tipo di flusso. In Android 8.0 (livello API 26) e versioni successive,
i tipi di flussi per qualsiasi operazione diversa dai controlli del volume sono deprecati. Utilizza le funzionalità di
gli stessi attributi nella richiesta di impostazione dello stato attivo che utilizzi nel tuo lettore audio (ad esempio,
mostrato nell'esempio che segue questa tabella).
Usa un
Se non specificato, il valore predefinito di |
setWillPauseWhenDucked()
|
Quando un'altra app richiede lo stato attivo
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK , l'app su cui è attivo lo stato attivo non
di solito ricevono un
onAudioFocusChange()
perché il sistema può eseguire
si attenua da solo. Quando hai bisogno di mettere in pausa la riproduzione
abbassa il volume, chiama setWillPauseWhenDucked(true) , crea e imposta
OnAudioFocusChangeListener , come descritto nella sezione automatica
attenuazione automatica.
|
setAcceptsDelayedFocusGain()
|
Una richiesta di messa a fuoco audio può non riuscire quando lo stato attivo è bloccato da un'altra app.
Questo metodo consente il aumento della messa a fuoco ritardata, ovvero la capacità
per acquisire l'attenzione in modo asincrono
quando diventa disponibile.
Tieni presente che il guadagno dello stato attivo ritardato funziona solo se specifichi anche
|
setOnAudioFocusChangeListener()
|
Il campo OnAudioFocusChangeListener è obbligatorio solo se specifichi anche
willPauseWhenDucked(true) o setAcceptsDelayedFocusGain(true) nella richiesta.
Esistono due metodi per impostare il listener: uno con e uno senza un
è l'argomento del gestore. Il gestore è il thread su cui viene eseguito il listener. Se
non specificano un gestore, il gestore associato
È in uso |
L'esempio seguente mostra come utilizzare AudioFocusRequest.Builder
per creare
AudioFocusRequest
e richiedere e abbandonare lo stato attivo dell'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; } } }
Attenuazione automatica automatica
In Android 8.0 (livello API 26), quando un'altra app richiede lo stato attivo con
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
il sistema riesce a ridurre il volume e a ripristinare il volume
senza richiamare il callback onAudioFocusChange()
dell'app.
Sebbene l'attenuazione automatica automatica sia un comportamento accettabile per la riproduzione di musica e video app, non è utile durante la riproduzione di contenuti vocali, come in una app per audiolibri. In questo caso, l'app dovrebbe essere messa in pausa.
Se vuoi che la tua app venga messa in pausa quando ti viene chiesto di abbassare il volume anziché abbassarne il volume, crea un OnAudioFocusChangeListener
con
un metodo di callback onAudioFocusChange()
che implementa il comportamento di pausa/ripresa desiderato.
Chiama il numero setOnAudioFocusChangeListener()
per registrare l'ascoltatore, quindi chiama
setWillPauseWhenDucked(true)
per indicare al sistema di utilizzare la richiamata anziché eseguire l'attenuazione automatica automatica.
Ritardo della messa a fuoco
A volte il sistema non può soddisfare una richiesta di messa a fuoco audio perché questo è
"bloccato" da un'altra app, come durante una telefonata. In questo caso,
requestAudioFocus()
restituisce AUDIOFOCUS_REQUEST_FAILED
. In questi casi,
l'app non dovrebbe procedere con la riproduzione audio perché non ha
il focus.
Il metodo setAcceptsDelayedFocusGain(true)
che consente alla tua app di gestire una richiesta di impostazione dello stato attivo
in modo asincrono. Con questo flag impostato, viene effettuata una richiesta quando lo stato attivo è bloccato
restituisce AUDIOFOCUS_REQUEST_DELAYED
. Quando la condizione che ha bloccato l'audio
lo stato attivo non esiste più, ad esempio al termine di una telefonata,
accetta la richiesta di messa a fuoco in attesa e chiama onAudioFocusChange()
per inviare una notifica
dell'app.
Per gestire il guadagno ritardato della messa a fuoco, devi creare un
OnAudioFocusChangeListener
con un metodo di callback onAudioFocusChange()
che
il comportamento desiderato e la registrazione del listener richiamando
setOnAudioFocusChangeListener()
Focus audio in Android 7.1 e versioni precedenti
Quando chiami
requestAudioFocus()
devi specificare un suggerimento sulla durata, che può
essere rispettata da un'altra app che attualmente mantiene lo stato attivo e in riproduzione:
- Richiedi il focus audio permanente (
AUDIOFOCUS_GAIN
) quando prevedi di riprodurre l'audio per il prossimo futuro (ad esempio, durante la riproduzione di musica) e ti aspetti che precedente proprietario dell'audio attivo per interrompere la riproduzione. - Richiedi lo stato attivo temporaneo (
AUDIOFOCUS_GAIN_TRANSIENT
) quando prevedi di giocare solo per un breve periodo di tempo e ti aspetti che il titolare precedente venga messo in pausa che giocano. - Richiedi lo stato attivo temporaneo con la funzionalità di attenuazione automatica
(
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
) per indicare che prevedi di riprodurre l'audio per un breve periodo di tempo e che il precedente proprietario dell'elemento possa suona se "antra" (abbassa) l'output audio. Entrambe le uscite audio sono mixate nello stream audio. La funzionalità di attenuazione automatica è particolarmente adatta per le app che utilizzano audio a intermittenza, ad esempio per indicazioni stradali udibili.
Il metodo requestAudioFocus()
richiede anche un elemento AudioManager.OnAudioFocusChangeListener
. Questo listener dovrebbe essere
creato nella stessa attività o nello stesso servizio proprietario della sessione multimediale. it
implementa il callback onAudioFocusChange()
che la tua app riceve quando
alcune altre app acquisiscono o abbandonano il focus audio.
Il seguente snippet richiede un focus audio permanente sullo stream
STREAM_MUSIC
e registra un OnAudioFocusChangeListener
da gestire
le modifiche successive al focus audio. (Il listener delle modifiche viene discusso in
Rispondere a un cambio di impostazione dell'elemento attivo su 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 }
Al termine della riproduzione, chiama
abandonAudioFocus()
Kotlin
audioManager.abandonAudioFocus(afChangeListener)
Java
// Abandon audio focus when playback complete audioManager.abandonAudioFocus(afChangeListener);
In questo modo, il sistema viene informato che non hai più bisogno di messa a fuoco e viene annullata la registrazione del
OnAudioFocusChangeListener
associato. Se hai richiesto lo stato temporaneo,
all'app che è stata messa in pausa o abbassata, verrà notificata la possibilità di continuare la riproduzione o
ripristinare il suo volume.
Rispondere a un cambio di impostazione dello stato attivo per l'audio
Quando un'app acquisisce l'audio attivo, deve essere in grado di rilasciarlo quando un'altra app
richiede la focalizzazione sull'audio. In questi casi, la tua app
riceve una chiamata
onAudioFocusChange()
nel AudioFocusChangeListener
specificato durante la chiamata dell'app requestAudioFocus()
.
Il parametro focusChange
passato a onAudioFocusChange()
indica il tipo
di cambiamenti in atto. Corrisponde
al suggerimento sulla durata utilizzato dall'app per cui è impostato lo stato attivo. La tua app dovrebbe
di rispondere in modo appropriato.
- Perdita di messa a fuoco temporanea
-
Se la modifica dell'elemento attivo è temporanea (
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
oAUDIOFOCUS_LOSS_TRANSIENT
), la tua app dovrebbe ridursi (se non ti avvali sull'attenuazione automatica) o mettere in pausa la riproduzione, altrimenti manterranno lo stesso stato.In caso di perdita temporanea dell'audio attivo, devi continuare a monitorare le modifiche con messa a fuoco audio e preparati a riprendere la riproduzione normale quando recuperi il il focus. Quando l'app di blocco abbandona lo stato attivo, ricevi un callback (
AUDIOFOCUS_GAIN
) A questo punto, puoi ripristinare il volume al livello normale o riavvia la riproduzione. - Perdita permanente dell'attenzione
-
Se la perdita dello stato attivo dell'audio è permanente (
AUDIOFOCUS_LOSS
), viene eseguita un'altra app la riproduzione di audio. La tua app dovrebbe mettere subito in pausa la riproduzione, poiché non sarà mai ricevi una richiamata diAUDIOFOCUS_GAIN
. Per riavviare la riproduzione, l'utente deve eseguire un'azione esplicita, ad esempio premere il controllo di trasporto di Play in una notifica o nell'interfaccia utente dell'app.
Il seguente snippet di codice illustra come implementare il
OnAudioFocusChangeListener
e il relativo callback onAudioFocusChange()
. Nota come
utilizzo di Handler
per ritardare la richiamata di interruzione in caso di perdita permanente dell'audio
il focus.
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 } } };
Il gestore utilizza un Runnable
simile al seguente:
Kotlin
private var delayedStopRunnable = Runnable { mediaController.transportControls.stop() }
Java
private Runnable delayedStopRunnable = new Runnable() { @Override public void run() { getMediaController().getTransportControls().stop(); } };
Per assicurarti che l'interruzione ritardata non venga attivata se l'utente riavvia la riproduzione, chiama
mHandler.removeCallbacks(mDelayedStopRunnable)
in risposta a qualsiasi stato
modifiche. Ad esempio, chiama removeCallbacks()
nel campo onPlay()
del callback,
onSkipToNext()
e così via. Devi anche richiamare questo metodo nella
onDestroy()
durante la pulizia delle risorse utilizzate dal servizio.