Die Benutzeroberfläche des Players

Ein Player ist die Komponente Ihrer App, die die Wiedergabe von Medienelementen ermöglicht. Die Media3-Schnittstelle Player enthält einen Überblick über die Funktionen, die im Allgemeinen von einem Player ausgeführt werden. Dazu zählen:

  • Auswirkungen auf Wiedergabesteuerungen, z. B. Wiedergabe, Pause und Suche
  • Attribute der aktuell wiedergegebenen Medien abfragen, z. B. die Wiedergabeposition
  • Playlist/Warteschlange mit Medienelementen verwalten
  • Wiedergabeeigenschaften wie Zufallsmix, Wiederholung, Geschwindigkeit und Lautstärke konfigurieren
  • Video wird auf dem Bildschirm gerendert

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

Eine gemeinsame Schnittstelle zwischen Komponenten

Mehrere Komponenten in Media3 implementieren die Player-Schnittstelle. Beispiele:

Komponente Beschreibung und Hinweise zum Verhalten
ExoPlayer Eine Mediaplayer-API und die Standardimplementierung der Player-Schnittstelle.
MediaController Interagiert mit einem MediaSession, um Wiedergabebefehle zu senden. Wenn sich Player und MediaSession in einer anderen Service als der Activity oder Fragment befinden, in der sich die Benutzeroberfläche Ihres Spielers befindet, können Sie Ihren MediaController als Player für die Benutzeroberfläche von PlayerView zuweisen. Aufrufe von Wiedergabe- und Playlist-Methoden werden über MediaSession an Player gesendet.
MediaBrowser Interagiert zusätzlich zu den von einem MediaController angebotenen Funktionen mit einem MediaLibrarySession, um verfügbare Medieninhalte zu durchsuchen.
ForwardingPlayer Eine Player-Implementierung, die Methodenaufrufe an eine andere Player weiterleitet. Verwenden Sie diese Klasse, um bestimmte Vorgänge zu unterdrücken oder zu ändern, indem Sie die entsprechenden Methoden überschreiben.
SimpleBasePlayer Eine Player-Implementierung, mit der die Anzahl der zu implementierenden Methoden auf ein Minimum reduziert wird. Dies ist hilfreich, wenn du einen benutzerdefinierten Player verwendest, den du mit einem MediaSession verbinden möchtest.
CastPlayer Eine Player-Implementierung, die mit einer Cast-Empfänger-App kommuniziert. Das Verhalten hängt von der zugrunde liegenden Cast-Sitzung ab.

Obwohl ein MediaSession die Player-Schnittstelle nicht implementiert, ist beim Erstellen eine Player-Schnittstelle erforderlich. Er dient dazu, anderen Prozessen oder Threads Zugriff auf das Player zu gewähren.

Media3-Wiedergabearchitektur

Wenn du Zugriff auf eine Player hast, solltest du die zugehörigen Methoden direkt aufrufen, um Wiedergabebefehle auszugeben. Du kannst eine MediaSession implementieren, um Werbung für deine Wiedergabe zu schalten und externen Quellen eine Wiedergabesteuerung zu ermöglichen. Diese externen Quellen implementieren einen MediaController, der das Herstellen einer Verbindung zu einer Mediensitzung und das Senden von Wiedergabebefehlsanfragen vereinfacht.

Wenn Medien im Hintergrund abgespielt werden, müssen Sie Ihre Mediensitzung und Ihren Player in einem MediaSessionService- oder MediaLibraryService-Element befinden, das als Dienst im Vordergrund ausgeführt wird. In diesem Fall kannst du deinen Player von der Aktivität in deiner App trennen, die die UI zur Wiedergabesteuerung enthält. Dazu kann es notwendig sein, einen Medienverantwortlichen zu nutzen.

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

Player-Status

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

  1. Wiedergabestatus
  2. Playlist mit Medienelementen
  3. Eigenschaften für Wiedergabe/Pause, z. B.:
    • playWhenReady: Gibt an, ob der Nutzer Medien nach Möglichkeit wiedergeben oder pausiert lassen möchte
    • Grund für die Wiedergabeunterdrückung: Gibt an, warum die Wiedergabe unterdrückt wurde, auch wenn für playWhenReady der Wert true gilt.
    • isPlaying: Gibt an, ob der Player gerade eine Wiedergabe ausführt. Dieser Wert ist nur true, wenn der Wiedergabestatus STATE_READY, playWhenReady ist true und die Wiedergabe nicht unterdrückt wurde.
  4. Wiedergabeposition, einschließlich:

Darüber hinaus ermöglicht die Schnittstelle Player den Zugriff auf die verfügbaren Titel, Medienmetadaten, die Wiedergabegeschwindigkeit, die Lautstärke und andere Hilfseigenschaften der Wiedergabe.

Auf Änderungen warten

Verwenden Sie einen Player.Listener, um Änderungen in einem Player zu beobachten. Informationen zum Erstellen und Verwenden eines Listeners finden Sie in der ExoPlayer-Dokumentation zu Player-Ereignissen.

Die Listener-Oberfläche enthält keine Callbacks, mit denen der normale Wiedergabefortschritt erfasst werden kann. Wenn Sie den Wiedergabefortschritt kontinuierlich beobachten möchten, z. B. um eine UI für eine Fortschrittsanzeige einzurichten, sollten Sie die aktuelle Position in entsprechenden 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 Schnittstelle Player 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 den in Media3 enthaltenen SimpleBasePlayer erweitern. Diese Klasse bietet eine Basisimplementierung der Player-Schnittstelle, um die Anzahl der zu implementierenden Methoden auf ein Minimum zu reduzieren.

Überschreiben Sie zuerst die Methode getState(). Mit dieser Methode wird der aktuelle Player-Status ausgefüllt, wenn sie aufgerufen wird. Dazu gehören:

  • Die verfügbaren Befehle
  • Wiedergabeeigenschaften, z. B. ob der Player die Wiedergabe starten soll, wenn der Wiedergabestatus STATE_READY ist, der Index des aktuell wiedergegebenen Medienelements 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 erzwingt, dass das State-Objekt mit einer gültigen Kombination von Statuswerten erstellt wird. Sie verarbeitet auch Listener und informiert Listener über Statusänderungen. Wenn Sie eine Statusaktualisierung manuell auslösen müssen, rufen Sie invalidateState() auf.

Über die Methode getState() hinaus musst du nur Methoden implementieren, die für Befehle verwendet werden, die dein Player für die Verfügbarkeit erklärt. Suchen Sie die überschreibbare Handler-Methode, die der zu implementierenden Funktionalität entspricht. Ü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.