Rispondere ai pulsanti multimediali

I pulsanti multimediali sono pulsanti hardware presenti su dispositivi Android e altri dispositivi periferici, ad esempio il pulsante di pausa/riproduzione delle 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 gli eventi chiave del pulsante multimediale sono costanti che iniziano con KEYCODE_MEDIA (ad esempio, KEYCODE_MEDIA_PLAY).

Le app devono essere in grado di gestire gli eventi relativi ai pulsanti multimediali in tre casi, nell'ordine di seguito priorità:

  • Quando l'attività UI dell'app è visibile
  • Quando l'attività UI è nascosta e la sessione multimediale dell'app è attiva
  • Quando l'attività dell'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 onKeyDown() . A seconda della versione di Android in esecuzione, il sistema può instradare l'evento in due modi un controller multimediale:

  • Se utilizzi Android 5.0 (livello API 21) o versioni successive, chiama FLAG_HANDLES_MEDIA_BUTTONS MediaBrowserCompat.ConnectionCallback.onConnected. In questo modo chiama automaticamente il controller dispatchMediaButtonEvent(), che traduce il codice chiave in un callback di sessione multimediale.
  • Prima di Android 5.0 (livello API 21), devi modificare onKeyDown() per gestire personalmente l'evento. Per maggiori dettagli, vedi Gestire i pulsanti multimediali in una sessione multimediale attiva. Il seguente snippet di codice mostra come intercettare e chiama submitMediaButtonEvent(). Assicurati di restituire true a indicano 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 proverà a trovare un sessione multimediale in grado di gestirla. Anche in questo caso, a seconda della versione in esecuzione Android esistono due modi per cercare una sessione multimediale:

  • Se utilizzi Android 8.0 (livello API 26) o versioni successive, il sistema tenta di trovare l'ultima app con una MediaSession che ha riprodotto l'audio localmente. Se la sessione è ancora attivo, Android invia l'evento direttamente a quest'ultimo. Altrimenti, se sessione non attiva e ha un ricevitore mediabutton, Android invia l'evento al destinatario, che riavvierà la sessione e potrà ricevere l'evento. Per maggiori dettagli, consulta Utilizzare i pulsanti multimediali per riavviare una sessione multimediale inattiva. Se la sessione non ha un ricevitore con pulsante multimediale, il sistema scarta i contenuti multimediali. e non succederà nulla. La logica è mostrata di seguito diagramma:

  • Prima di Android 8.0 (livello API 26), il sistema tenta di inviare l'evento a un sessione multimediale attiva. Se ci sono più sessioni multimediali attive, Android prova per scegliere una sessione multimediale che si sta preparando per la riproduzione (buffering/collegamento), in riproduzione o in pausa, anziché in uno che è stato interrotto. (Vedi Gestire i pulsanti multimediali in una sessione multimediale attiva per ulteriori informazioni.) Se non sono attive , Android prova a inviare l'evento all'ultima sessione attiva. Per maggiori dettagli, consulta Utilizzare i 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 eventi relativi ai pulsanti multimediali alla sessione multimediale attiva chiamando onMediaButtonEvent(). Per impostazione predefinita, questo callback traduce il KeyEvent nel metodo di callback della sessione multimediale appropriato corrispondente al codice della chiave.

Prima di Android 5.0 (livello API 21), Android gestisce gli eventi relativi al pulsante multimediale trasmettendo un intent con l'azione ACTION_MEDIA_BUTTON. L'app deve registrare un BroadcastRicevir per intercettare questi intent. La MediaButtonReceiver è stato progettato specificamente per questo scopo. È una lezione di Android media-compats che gestisce ACTION_MEDIA_BUTTON e traduce gli intent in arrivo chiamate al metodo MediaSessionCompat.Callback appropriate.

Un MediaButtonReceiver è un BroadcastReceiver di breve durata. Inoltra i messaggi in arrivo intent al servizio che gestisce la sessione multimediale. Se vuoi utilizzare Nei sistemi precedenti ad Android 5.0, è necessario includere i pulsanti multimediali MediaButtonReceiver nel 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. ad analizzare l'intent. e generare il callback per la sessione multimediale, includi il metodo MediaButtonReceiver.handleIntent() nel valore 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);
 }

Utilizzare i pulsanti multimediali per riavviare una sessione multimediale inattiva

Se Android è in grado di identificare l'ultima sessione multimediale attiva, prova a riavviarla inviando un intent ACTION_MEDIA_BUTTON a un componente registrato nel file manifest (ad esempio un servizio o BroadcastReceiver).

Ciò consente all'app di riavviare la riproduzione mentre la relativa UI non è visibile, come accade per la maggior parte delle app audio.

Questo comportamento viene attivato automaticamente quando utilizzi MediaSessionCompat. Se usare MediaSession del framework Android o Support Library 24.0.0 tramite 25.1.1 È necessario chiamare setMediaButtonReceiver per consentire a un pulsante multimediale di riavviare un sessione multimediale inattiva.

Puoi disattivare questo comportamento in Android 5.0 (livello API 21) e versioni successive tramite impostazione di un ricevitore per il pulsante null media:

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 di pulsanti multimediali

Il comportamento predefinito per onMediaButtonEvent() estrae il codice chiave e utilizza lo stato attuale 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 i pulsanti multimediali in tutte le app, devi utilizzare il comportamento predefinito e deviare solo per uno scopo specifico. Se viene visualizzato un pulsante richiede una gestione personalizzata, sostituisci onMediaButtonEvent() , estrai il valore KeyEvent utilizzando intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT), gestire personalmente l'evento e restituire true.

Riepilogo

Per gestire correttamente gli eventi relativi ai pulsanti multimediali in tutte le versioni di Android, devi: specifica FLAG_HANDLES_MEDIA_BUTTONS quando crei una sessione multimediale.

Inoltre, a seconda delle versioni di Android che intendi supportare, devi inoltre soddisfare i seguenti requisiti:

Su Android 5.0 o versioni successive:

  • Chiama MediaControllerCompat.setMediaController() dal callback onConnected() del controller multimediale
  • Per consentire a un pulsante multimediale di riavviare una sessione non attiva, crea dinamicamente un MediaButtonReceiver chiamando setMediaButtonReceiver() superando un PendingIntent

Se vengono eseguiti in sistemi precedenti ad Android 5.0:

  • Sostituisci il valore onKeyDown() dell'attività per gestire i pulsanti multimediali
  • Crea in modo statico un elemento MediaButtonReceiver aggiungendolo al file manifest dell'app