Die Benutzeroberfläche des Players

Ein Player ist die Komponente Ihrer App, die die Wiedergabe von Media-Elementen ermöglicht. Die Media3-Schnittstelle Player bietet einen Überblick über die Funktionen, die in der Regel von einem Player ausgeführt werden. Dazu gehören:

  • Wiedergabesteuerelemente wie Wiedergabe, Pause und Suche
  • Eigenschaften der aktuell wiedergegebenen Medien abfragen, z. B. die Wiedergabeposition
  • Playlists/Wiedergabelisten mit Medienelementen verwalten
  • Wiedergabeeigenschaften wie Zufallswiedergabe, Wiederholung, Geschwindigkeit und Lautstärke konfigurieren
  • Video auf dem Bildschirm rendern

Media3 bietet auch eine Implementierung der Player-Schnittstelle namens ExoPlayer.

Eine gemeinsame Schnittstelle zwischen Komponenten

Mehrere Komponenten in Media3 implementieren die Player-Schnittstelle, z. B.:

Komponente Beschreibung und Verhaltenshinweise
ExoPlayer Eine Media Player API und die Standardimplementierung der Player-Schnittstelle.
MediaController Interagiert mit einem MediaSession, um Wiedergabebefehle zu senden. Wenn sich Player und MediaSession in einem Service befinden, das sich vom Activity oder Fragment unterscheidet, in dem sich die Benutzeroberfläche des Players befindet, können Sie MediaController als Player für die PlayerView-Benutzeroberfläche zuweisen. Wiedergabe- und Playlist-Methodenaufrufe werden über deine MediaSession an deine Player gesendet.
MediaBrowser Zusätzlich zu den Funktionen, die von einem MediaController angeboten werden, interagiert es mit einem MediaLibrarySession, um verfügbare Medieninhalte zu durchsuchen.
SimpleBasePlayer Eine Player-Implementierung, die die Anzahl der zu implementierenden Methoden auf ein Minimum reduziert. Das ist hilfreich, wenn Sie einen benutzerdefinierten Player verwenden, den Sie mit einem MediaSession verbinden möchten.
ForwardingSimpleBasePlayer Eine SimpleBasePlayer-Unterklasse, die Wiedergabevorgänge an ein anderes Player weiterleitet und gleichzeitig dieselben konsistenten Verhaltensanpassungen wie SimpleBasePlayer ermöglicht. Mit dieser Klasse können Sie bestimmte Wiedergabeaktionen unterdrücken oder ändern.
CastPlayer Eine Player-Implementierung, die mit einer Cast-Empfänger-App kommuniziert. Das Verhalten hängt von der zugrunde liegenden Cast-Sitzung ab.

Obwohl eine MediaSession die Player-Schnittstelle nicht implementiert, ist beim Erstellen eine Player erforderlich. Sie dient dazu, den Zugriff auf die Player über andere Prozesse oder Threads zu ermöglichen.

Media3-Wiedergabearchitektur

Wenn Sie Zugriff auf ein Player haben, sollten Sie die zugehörigen Methoden direkt aufrufen, um Wiedergabebefehle auszugeben. Sie können Ihre Wiedergabe bewerben und externen Quellen die Wiedergabesteuerung gewähren, indem Sie eine MediaSession implementieren. Diese externen Quellen implementieren eine MediaController, die die Verbindung zu einer Mediensitzung und die Ausgabe von Wiedergabebefehlen erleichtert.

Wenn Sie Medien im Hintergrund abspielen, müssen Sie Ihre Mediensitzung und Ihren Player in einem MediaSessionService oder MediaLibraryService unterbringen, der als Vordergrunddienst ausgeführt wird. In diesem Fall können Sie den Player von der Aktivität in Ihrer App trennen, die die Benutzeroberfläche für die Wiedergabesteuerung enthält. Dazu ist möglicherweise ein Media-Controller erforderlich.

Ein Diagramm, das zeigt, wie Media3-Wiedergabekomponenten in die Architektur einer Media-App passen.
Abbildung 1: Die Player-Schnittstelle spielt eine wichtige Rolle in der Architektur von Media3.

Player-Status

Der Status eines Mediaplayers, der die Player-Schnittstelle implementiert, besteht hauptsächlich aus vier Kategorien von Informationen:

  1. Wiedergabestatus
  2. Playlist mit Medienelementen
  3. Attribute für die Wiedergabe/Pause, z. B.:
    • playWhenReady: Gibt an, ob Medien nach Möglichkeit abgespielt oder pausiert bleiben sollen.
    • Grund für die Unterdrückung der Wiedergabe: Ein Hinweis darauf, warum die Wiedergabe unterdrückt wird, falls zutreffend, auch wenn playWhenReady = true
    • isPlaying: Gibt an, ob der Player gerade wiedergegeben wird. Der Wert ist nur true, wenn der Wiedergabestatus STATE_READY ist, playWhenReady true ist und die Wiedergabe nicht unterdrückt wird.
  4. Wiedergabeposition, einschließlich:

Außerdem bietet die Player-Schnittstelle Zugriff auf die verfügbaren Tracks, Medienmetadaten, Wiedergabegeschwindigkeit, Lautstärke und andere Hilfseigenschaften der Wiedergabe.

Auf Änderungen achten

Verwenden Sie einen Player.Listener, um auf Änderungen in einem Player zu reagieren. In der ExoPlayer-Dokumentation unter Player events finden Sie weitere Informationen zum Erstellen und Verwenden eines Listeners.

Die Listener-Schnittstelle enthält keine Callbacks, um den normalen Wiedergabefortschritt zu verfolgen. Wenn Sie den Wiedergabefortschritt kontinuierlich überwachen möchten, z. B. um eine Fortschrittsanzeige einzurichten, sollten Sie die aktuelle Position in angemessenen Intervallen abfragen.

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);
}

Wiedergabe steuern

Die Player-Schnittstelle bietet viele Möglichkeiten, den Status zu ändern und die Wiedergabe zu steuern:

Benutzerdefinierte Player-Implementierungen

Wenn Sie einen benutzerdefinierten Player erstellen möchten, können Sie die in Media3 enthaltene SimpleBasePlayer erweitern. Diese Klasse bietet eine Basisimplementierung der Player-Schnittstelle, um die Anzahl der Methoden, die Sie implementieren müssen, auf ein Minimum zu reduzieren.

Überschreiben Sie zuerst die Methode getState(). Mit dieser Methode sollte der aktuelle Spielerstatus beim Aufrufen ausgefüllt werden, einschließlich:

  • Die verfügbaren Befehle
  • Wiedergabeeigenschaften, z. B. ob der Player mit der Wiedergabe beginnen soll, wenn der Wiedergabestatus STATE_READY ist, der Index des aktuell wiedergegebenen Media-Elements und die Wiedergabeposition innerhalb des aktuellen Elements

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 sorgt dafür, dass State mit einer gültigen Kombination von Statuswerten erstellt wird. Außerdem werden Listener verwaltet und über Zustandsänderungen informiert. Wenn Sie ein Statusupdate manuell auslösen müssen, rufen Sie invalidateState() auf.

Außer der Methode getState() müssen Sie nur Methoden implementieren, die für Befehle verwendet werden, die Ihr Player als verfügbar deklariert. Suchen Sie die überschreibbare Handler-Methode, die der Funktion entspricht, die Sie implementieren möchten. Überschreiben Sie beispielsweise die Methode handleSeek(), um Vorgänge wie COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM und COMMAND_SEEK_TO_NEXT_MEDIA_ITEM zu unterstützen.

Player-Implementierungen ändern

Anstatt ein vollständig benutzerdefiniertes Player zu erstellen, können Sie mit ForwardingSimpleBasePlayer den Status und das Verhalten eines vorhandenen Player ändern. Weitere Informationen finden Sie im Leitfaden auf der Seite „Anpassung“.