Interfaccia del player

Un player è il componente dell'app che facilita la riproduzione degli elementi multimediali. L'interfaccia Media3 Player definisce una struttura per le funzionalità generalmente gestite da un player. Questo include:

  • Che influiscono sui controlli di riproduzione, ad esempio riproduzione, pausa e ricerca
  • Eseguire query sulle proprietà dei contenuti multimediali in riproduzione, ad esempio la posizione di riproduzione
  • Gestire una playlist/coda di elementi multimediali
  • Configurazione delle proprietà di riproduzione, come riproduzione casuale, ripetizione, velocità e volume
  • Rendering del video sullo schermo

Media3 fornisce anche un'implementazione dell'interfaccia Player, chiamata ExoPlayer.

Un'interfaccia comune tra i componenti

Diversi componenti di Media3 implementano l'interfaccia Player, ad esempio:

Componente Descrizione e note sul comportamento
ExoPlayer Un'API per lettore multimediale e l'implementazione predefinita dell'interfaccia Player.
MediaController Interagisce con un MediaSession per inviare comandi di riproduzione. Se Player e MediaSession si trovano in un Service separato da Activity o Fragment in cui si trova l'interfaccia utente del lettore, puoi assegnare MediaController come lettore per l'interfaccia utente PlayerView. Le chiamate ai metodi di riproduzione e playlist vengono inviate al tuo Player tramite il tuo MediaSession.
MediaBrowser Oltre alle funzionalità offerte da un MediaController, interagisce con un MediaLibrarySession per sfogliare i contenuti multimediali disponibili.
SimpleBasePlayer Un'implementazione Player che riduce al minimo il numero di metodi da implementare. Utile quando utilizzi un player personalizzato che vuoi connettere a un MediaSession.
ForwardingSimpleBasePlayer Una sottoclasse SimpleBasePlayer progettata per inoltrare la riproduzione a un altro Player, consentendo al contempo le stesse personalizzazioni del comportamento coerenti di SimpleBasePlayer. Utilizza questa classe per eliminare o modificare operazioni di riproduzione specifiche.
CastPlayer Un'implementazione Player che comunica con un'app ricevitore Cast. Il comportamento dipende dalla sessione Cast sottostante.

Sebbene un MediaSession non implementi l'interfaccia Player, richiede un Player durante la creazione. Il suo scopo è fornire l'accesso a Player da altri processi o thread.

Architettura di riproduzione di Media3

Se hai accesso a un Player, devi chiamare direttamente i suoi metodi per inviare comandi di riproduzione. Puoi pubblicizzare la riproduzione e concedere a fonti esterne il controllo della riproduzione implementando un MediaSession. Queste fonti esterne implementano un MediaController, che facilita la connessione a una sessione multimediale e l'emissione di richieste di comandi di riproduzione.

Quando riproduci contenuti multimediali in background, devi ospitare la sessione multimediale e il player all'interno di un MediaSessionService o MediaLibraryService che viene eseguito come servizio in primo piano. In questo modo, puoi separare il player dall'attività nella tua app che contiene la UI per il controllo della riproduzione. Potrebbe essere necessario utilizzare un controller multimediale.

Un diagramma che mostra come i componenti di riproduzione di Media3 si inseriscono nell'architettura di un'app multimediale.
Figura 1: l'interfaccia Player svolge un ruolo chiave nell'architettura di Media3.

Stato del giocatore

Lo stato di un media player che implementa l'interfaccia Player è costituito principalmente da 4 categorie di informazioni:

  1. Stato di riproduzione
  2. Playlist di elementi multimediali
  3. Proprietà di riproduzione/pausa, ad esempio:
    • playWhenReady: Un'indicazione se l'utente vuole che i contenuti multimediali vengano riprodotti quando possibile o rimangano in pausa
    • Motivo della soppressione della riproduzione: Un'indicazione del motivo per cui la riproduzione viene soppressa, se applicabile, anche se playWhenReady è true
    • isPlaying: Un'indicazione se il player è attualmente in riproduzione, che sarà solo true se lo stato di riproduzione è STATE_READY, playWhenReady è true e la riproduzione non è soppressa
  4. Posizione di riproduzione, tra cui:

Inoltre, l'interfaccia Player consente l'accesso a tracce disponibili, metadati dei contenuti multimediali, velocità di riproduzione, volume e altre proprietà ausiliarie della riproduzione.

Ascoltare le modifiche

Utilizza un Player.Listener per rilevare le modifiche in un Player. Consulta la documentazione di ExoPlayer sugli eventi del player per informazioni dettagliate su come creare e utilizzare un listener.

Tieni presente che l'interfaccia dell'ascoltatore non include callback per monitorare la normale avanzamento della riproduzione. Per monitorare continuamente l'avanzamento della riproduzione, ad esempio per impostare un'interfaccia utente della barra di avanzamento, devi eseguire query sulla posizione corrente a intervalli appropriati.

Kotlin

val handler = Handler(Looper.getMainLooper())
fun checkPlaybackPosition(delayMs: Long): Boolean =
  handler.postDelayed(
    {
      val currentPosition = player.currentPosition
      // Update UI based on currentPosition
      checkPlaybackPosition(delayMs)
    },
    delayMs)

Java

Handler handler = new Handler(Looper.getMainLooper());
boolean checkPlaybackPosition(long delayMs) {
    return handler.postDelayed(() -> {
        long currentPosition = player.getCurrentPosition();
        // Update UI based on currentPosition
        checkPlaybackPosition(delayMs);
    }, delayMs);
}

Controlla la riproduzione

L'interfaccia Player offre molti modi per manipolare lo stato e controllare la riproduzione:

Implementazioni personalizzate di Player

Per creare un player personalizzato, puoi estendere SimpleBasePlayer incluso in Media3. Questa classe fornisce un'implementazione di base dell'interfaccia Player per ridurre al minimo il numero di metodi da implementare.

Inizia eseguendo l'override del metodo getState(). Questo metodo deve compilare lo stato attuale del giocatore quando viene chiamato, tra cui:

  • L'insieme dei comandi disponibili
  • Proprietà di riproduzione, ad esempio se il player deve iniziare la riproduzione quando lo stato di riproduzione è STATE_READY, l'indice dell'elemento multimediale attualmente in riproduzione e la posizione di riproduzione all'interno dell'elemento corrente

Kotlin

class CustomPlayer : SimpleBasePlayer(looper) {
  override fun getState(): State {
    return State.Builder()
      .setAvailableCommands(...) // Set which playback commands the player can handle
      // Configure additional playback properties
      .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
      .setCurrentMediaItemIndex(0)
      .setContentPositionMs(0)
      .build()
  }
}

Java

public class CustomPlayer extends SimpleBasePlayer {
  public CustomPlayer(Looper looper) {
    super(looper);
  }

  @Override
  protected State getState() {
    return new State.Builder()
      .setAvailableCommands(...) // Set which playback commands the player can handle
      // Configure additional playback properties
      .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
      .setCurrentMediaItemIndex(0)
      .setContentPositionMs(0)
      .build();
  }
}

SimpleBasePlayer imporrà la creazione di State con una combinazione valida di valori di stato. Gestirà anche i listener e li informerà delle modifiche dello stato. Se devi attivare manualmente un aggiornamento dello stato, chiama il numero invalidateState().

Oltre al metodo getState(), devi implementare solo i metodi utilizzati per i comandi che il tuo lettore dichiara disponibili. Trova il metodo di gestione sostituibile che corrisponde alla funzionalità che vuoi implementare. Ad esempio, esegui l'override del metodo handleSeek() per supportare operazioni come COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM e COMMAND_SEEK_TO_NEXT_MEDIA_ITEM.

Modificare le implementazioni di Player

Anziché creare un Player completamente personalizzato, puoi utilizzare ForwardingSimpleBasePlayer per modificare lo stato e il comportamento di un Player esistente. Per ulteriori dettagli, consulta la guida alla pagina di personalizzazione.