I pulsanti multimediali sono pulsanti hardware presenti su dispositivi Android e altre periferiche, ad esempio il pulsante di pausa/riproduzione sulle cuffie Bluetooth. Quando un utente preme un pulsante di contenuti multimediali, Android genera un KeyEvent
, che contiene un codice chiave che identifica il pulsante. I codici chiave per KeyEvents del pulsante multimediale sono costanti che iniziano con KEYCODE_MEDIA
(ad esempio, KEYCODE_MEDIA_PLAY
).
Le app dovrebbero essere in grado di gestire gli eventi dei pulsanti multimediali in tre casi, in questo ordine di priorità:
- Quando l'attività UI dell'app è visibile
- Quando l'attività UI è nascosta e la sessione multimediale dell'app è attiva
- Quando l'attività UI è nascosta e la sessione multimediale dell'app non è attiva e deve essere riavviata
Gestione dei pulsanti multimediali in un'attività in primo piano
L'attività in primo piano riceve l'evento chiave del pulsante multimediale nel relativo metodo onKeyDown()
. A seconda della versione di Android installata, il sistema può indirizzare l'evento a un controller multimediale in due modi:
- Se utilizzi Android 5.0 (livello API 21) o versioni successive, chiama
FLAG_HANDLES_MEDIA_BUTTONS
MediaBrowserCompat.ConnectionCallback.onConnected
. Questa operazione chiamerà automaticamente il controllerdispatchMediaButtonEvent()
del controller multimediale, in modo da tradurre il codice della chiave in un callback di sessione multimediale. - Prima di Android 5.0 (livello API 21), devi modificare
onKeyDown()
per gestire autonomamente l'evento. Per maggiori dettagli, consulta l'articolo Gestione dei pulsanti multimediali in una sessione multimediale attiva. Lo snippet di codice riportato di seguito mostra come intercettare il codice della chiave e chiamare dispatchMediaButtonEvent(). Assicurati di restituiretrue
per indicare che l'evento è stato gestito:Kotlin
fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return super.onKeyDown(keyCode, event) } when (keyCode) { KeyEvent.KEYCODE_MEDIA_PLAY -> { yourMediaController.dispatchMediaButtonEvent(event) return true } } return super.onKeyDown(keyCode, event) }
Java
@Override boolean onKeyDown(int keyCode, KeyEvent event) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return super.onKeyDown(keyCode, event); } switch (keyCode) { case KeyEvent.KEYCODE_MEDIA_PLAY: yourMediaController.dispatchMediaButtonEvent(event); return true; } return super.onKeyDown(keyCode, event); }
Trovare una sessione multimediale
Se l'attività in primo piano non gestisce l'evento, Android cercherà di trovare una sessione multimediale in grado di gestirlo. Anche in questo caso, a seconda della versione di Android disponibile, esistono due modi per cercare una sessione multimediale:
Se esegui Android 8.0 (livello API 26) o versioni successive, il sistema tenta di trovare l'ultima app con una MediaSession che ha riprodotto audio localmente. Se la sessione è ancora attiva, Android le invia l'evento direttamente. Altrimenti, se la sessione non è attiva e ha un ricevitore mediabutton, Android invia l'evento al destinatario, che riavvia la sessione e può ricevere l'evento. Per maggiori dettagli, vedi Utilizzo dei pulsanti multimediali per riavviare una sessione multimediale inattiva. Se la sessione non dispone di un ricevitore del pulsante multimediale, il sistema ignora l'evento del pulsante multimediale e non accade nulla. La logica è mostrata nel seguente schema:
Prima di Android 8.0 (livello API 26), il sistema tenta di inviare l'evento a una sessione multimediale attiva. Se sono presenti più sessioni multimediali attive, Android prova a scegliere una sessione multimediale che si sta preparando per la riproduzione (buffering/connessione), in riproduzione o in pausa, anziché una che viene interrotta. Per ulteriori dettagli, consulta Gestione dei pulsanti multimediali in una sessione multimediale attiva. Se non sono presenti sessioni attive, Android tenta di inviare l'evento alla sessione attiva più recente. Per maggiori dettagli, vedi Utilizzo dei pulsanti multimediali per riavviare una sessione multimediale inattiva. La logica è mostrata nel seguente diagramma:
Gestione dei pulsanti multimediali in una sessione multimediale attiva
Su Android 5.0 (livello API 21) e versioni successive, Android invia automaticamente gli eventi del pulsante multimediale alla sessione multimediale attiva chiamando
onMediaButtonEvent()
.
Per impostazione predefinita, questo callback converte l'evento KeyEvent nel metodo di callback della sessione multimediale appropriato che corrisponde al codice della chiave.
Prima di Android 5.0 (livello API 21), Android gestisce gli eventi dei pulsanti multimediali trasmettendo un intent con l'azione ACTION_MEDIA_BUTTON
. L'app deve registrare un BroadcastRicevir per intercettare questi intent. La classe MediaButtonReceiver
è stata progettata appositamente per questo scopo. È una classe di convenienza nella
libreria
media-compat di Android che
gestisce ACTION_MEDIA_BUTTON
e traduce gli intent in entrata
nelle chiamate del metodo MediaSessionCompat.Callback
appropriate.
Un MediaButtonReceiver
è un BroadcastRicevir di breve durata. Inoltra gli intent in entrata al servizio che gestisce la sessione multimediale. Se vuoi utilizzare i pulsanti multimediali nei sistemi precedenti ad Android 5.0, devi includere MediaButtonReceiver
nel file manifest con un filtro per intent MEDIA_BUTTON
.:
<receiver android:name="android.support.v4.media.session.MediaButtonReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
BroadcastReceiver
inoltra l'intent al tuo servizio. Per analizzare l'intent
e generare il callback per la tua sessione multimediale, includi il metodo MediaButtonReceiver.handleIntent()
nell'onStartCommand()
del tuo servizio.
In questo modo il codice chiave viene convertito nel metodo di callback della sessione appropriato.
Kotlin
private val mediaSessionCompat: MediaSessionCompat = ... override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { MediaButtonReceiver.handleIntent(mediaSessionCompat, intent) return super.onStartCommand(intent, flags, startId) }
Java
private MediaSessionCompat mediaSessionCompat = ...; public int onStartCommand(Intent intent, int flags, int startId) { MediaButtonReceiver.handleIntent(mediaSessionCompat, intent); return super.onStartCommand(intent, flags, startId); }
Utilizzo dei pulsanti multimediali per riavviare una sessione multimediale non attiva
Se Android è in grado di identificare l'ultima sessione multimediale attiva, prova a riavviarla inviando un intent ACTION_MEDIA_BUTTON
a un componente registrato con manifest (ad esempio un servizio o BroadcastReceiver
).
In questo modo l'app può riavviare la riproduzione mentre la sua UI non è visibile, come avviene per la maggior parte delle app audio.
Questo comportamento viene attivato automaticamente quando utilizzi MediaSessionCompat
. Se utilizzi MediaSession
del framework Android o Support Library da 24.0.0 a 25.1.1, devi chiamare setMediaButtonReceiver
per consentire a un pulsante multimediale di riavviare una sessione multimediale non attiva.
Puoi disattivare questo comportamento in Android 5.0 (livello API 21) e versioni successive impostando un ricevitore con pulsante multimediale null:
Kotlin
// Create a MediaSessionCompat mediaSession = MediaSessionCompat(context, LOG_TAG) mediaSession.setMediaButtonReceiver(null)
Java
// Create a MediaSessionCompat mediaSession = new MediaSessionCompat(context, LOG_TAG); mediaSession.setMediaButtonReceiver(null);
Personalizzazione dei gestori dei pulsanti multimediali
Il comportamento predefinito di onMediaButtonEvent()
estrae il codice della chiave e utilizza lo stato corrente della sessione multimediale e l'elenco di azioni supportate per determinare il metodo da chiamare. Ad esempio, KEYCODE_MEDIA_PLAY
richiama onPlay()
.
Per offrire un'esperienza coerente con il pulsante multimediale in tutte le app, devi utilizzare il comportamento predefinito e deviare soltanto per uno scopo specifico. Se un pulsante multimediale
richiede una gestione personalizzata, sostituisci il metodo
onMediaButtonEvent()
di callback, estrai KeyEvent
utilizzando
intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT)
,
gestisci l'evento autonomamente e restituisci true
.
Riepilogo
Per gestire correttamente gli eventi dei pulsanti multimediali in tutte le versioni di Android, devi specificare FLAG_HANDLES_MEDIA_BUTTONS
quando crei una sessione multimediale.
Inoltre, a seconda delle versioni di Android che intendi supportare, devi soddisfare anche i seguenti requisiti:
Su Android 5.0 o versioni successive:
- Chiama
MediaControllerCompat.setMediaController()
dal callbackonConnected()
del controller multimediale - Per consentire a un pulsante di contenuti multimediali di riavviare una sessione inattiva, crea in modo dinamico un
MediaButtonReceiver
chiamandosetMediaButtonReceiver()
e trasmettendo unPendingIntent
In caso di esecuzione su sistemi precedenti ad Android 5.0:
- Esegui l'override di
onKeyDown()
dell'attività per gestire i pulsanti multimediali - Crea in modo statico un
MediaButtonReceiver
aggiungendolo al file manifest dell'app