Erste Schritte mit CastPlayer

Der CastPlayer ist eine Jetpack Media3-Player-Implementierung, die sowohl die lokale Wiedergabe als auch das Streamen auf ein für Google Cast optimiertes Remote-Gerät unterstützt. CastPlayer vereinfacht das Hinzufügen von Cast-Funktionen zu Ihrer App und bietet umfangreiche Funktionen für das nahtlose Umschalten zwischen lokaler und Remote-Wiedergabe. In diesem Leitfaden erfahren Sie, wie Sie CastPlayer in Ihre Media-App einbinden.

Informationen zur Integration von Cast in andere Plattformen finden Sie im Cast SDK.

Für Google Cast optimiertes Gerät kaufen

Wenn du CastPlayer testen möchtest, benötigst du ein für Google Cast optimiertes Gerät. Zur Auswahl stehen Android TV, Chromecast, Smart Speaker und Smart Displays. Prüfe, ob dein Gerät eingerichtet und mit demselben WLAN wie dein Entwickler-Smartphone verbunden ist, damit es erkannt werden kann.

Build-Abhängigkeiten hinzufügen

Wenn Sie CastPlayer verwenden möchten, fügen Sie die AndroidX Media3- und CastPlayer-Abhängigkeiten der Datei build.gradle Ihres App-Moduls hinzu.

Kotlin

implementation("androidx.media3:media3-exoplayer:1.9.2")
implementation("androidx.media3:media3-ui:1.9.2")
implementation("androidx.media3:media3-session:1.9.2")
implementation("androidx.media3:media3-cast:1.9.2")

Groovy

implementation "androidx.media3:media3-exoplayer:1.9.2"
implementation "androidx.media3:media3-ui:1.9.2"
implementation "androidx.media3:media3-session:1.9.2"
implementation "androidx.media3:media3-cast:1.9.2"

CastPlayer konfigurieren

Um den CastPlayer zu konfigurieren, aktualisieren Sie die Datei AndroidManifest.xml mit einem Optionsanbieter.

Optionsanbieter

Für die CastPlayer ist ein Optionsanbieter erforderlich, um ihr Verhalten zu konfigurieren. Für eine einfache Einrichtung können Sie die DefaultCastOptionsProvider verwenden, indem Sie sie Ihrer AndroidManifest.xml-Datei hinzufügen. Dabei werden Standardeinstellungen verwendet, einschließlich der Standardempfängeranwendung.

<application>
  ...
  <meta-data
    android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
    android:value="androidx.media3.cast.DefaultCastOptionsProvider" />
  ...
</application>

Wenn Sie die Konfiguration anpassen möchten, implementieren Sie eine eigene benutzerdefinierte OptionsProvider. Weitere Informationen finden Sie im Leitfaden CastOptions.

Empfänger für die Medienübertragung hinzufügen

Wenn Sie Ihrem Manifest ein MediaTransferReceiver hinzufügen, kann die System-UI für Google Cast optimierte Geräte im Netzwerk erkennen und Medien umleiten, ohne die App-Aktivität zu öffnen. Ein Nutzer kann beispielsweise über die Media-Benachrichtigung das Gerät ändern, auf dem die Medien Ihrer App wiedergegeben werden.

<application>
  ...
  <receiver android:name="androidx.mediarouter.media.MediaTransferReceiver" />
  ...
</application>

CastPlayer erstellen

Für die Remote-Wiedergabe mit Cast muss Ihre App die Wiedergabe auch dann verwalten können, wenn der Nutzer nicht mit einer Aktivität aus Ihrer App interagiert, z. B. über die Systembenachrichtigung für Medien. Aus diesem Grund sollten Sie Ihre ExoPlayer-Instanzen (für die lokale Wiedergabe) und CastPlayer-Instanzen (für die Remote-Wiedergabe) in einem Dienst wie MediaSessionService oder MediaLibraryService erstellen. Erstellen Sie zuerst Ihre ExoPlayer-Instanz und legen Sie dann beim Erstellen Ihrer CastPlayer-Instanz ExoPlayer als lokale Player-Instanz fest. Du kannst dann die Medienwiedergabe über die Medienbenachrichtigung oder die Benachrichtigung auf dem Sperrbildschirm zwischen deinem Mobilgerät und dem für Google Cast optimierten Gerät wechseln. Media3 verwendet die Funktion Output Switcher (Ausgabewähler), um die Übertragung des Players zu verarbeiten, wenn sich die Ausgaberoute von lokal zu remote oder von remote zu lokal ändert.

Screenshot der Benutzeroberfläche für die Ausgabewahl in Benachrichtigungen
Abbildung 1: (a) Geräte-Chip in der Medienbenachrichtigung (b) Für die Übertragung optimierte Geräte, die beim Tippen auf den Geräte-Chip angezeigt werden (c) Geräte-Chip in der Benachrichtigung auf dem Sperrbildschirm

Kotlin

override fun onCreate() {
  super.onCreate()

  val exoPlayer = ExoPlayer.Builder(context).build()
  val castPlayer = CastPlayer.Builder(context)
      .setLocalPlayer(exoPlayer)
      .build()

  mediaSession = MediaSession.Builder(context, castPlayer).build()
}

Java

@Override
public void onCreate() {
  super.onCreate();

  ExoPlayer exoPlayer = new ExoPlayer.Builder(context).build();
  CastPlayer castPlayer = new CastPlayer.Builder(context)
      .setLocalPlayer(exoPlayer)
      .build();

  mediaSession = new MediaSession.Builder(
    /* context= */ context, /* player= */ castPlayer).build();
}

UI-Elemente hinzufügen

Fügen Sie der Benutzeroberfläche Ihrer App ein MediaRouteButton hinzu. Wenn Sie auf MediaRouteButton tippen, wird ein Dialogfeld mit einer Liste der verfügbaren für Google Cast optimierten Geräte im Netzwerk geöffnet. Wenn der Nutzer ein Gerät auswählt, wird die Medienwiedergabe vom Mobilgerät auf das ausgewählte Empfängergerät übertragen. In diesem Abschnitt erfahren Sie, wie Sie die Schaltfläche hinzufügen und auf Ereignisse warten, um die Benutzeroberfläche zu aktualisieren, wenn die Wiedergabe zwischen lokalen und Remote-Geräten wechselt.

MediaRouteButton festlegen

Es gibt vier Möglichkeiten, die MediaRouteButton in die Benutzeroberfläche deiner Aktivität einzufügen. Die beste Wahl hängt vom Design und den Anforderungen Ihrer App ab.

  • Compose-UI: Fügen Sie eine Schaltflächen-Composable hinzu.
  • Benutzeroberfläche für Ansichten:
    • Fügen Sie die Schaltfläche dem App-Leistenmenü hinzu.
    • Fügen Sie den Button in PlayerView ein.
    • Fügen Sie die Schaltfläche als Standard-View hinzu.
Screenshot mit der Schaltfläche „MediaRouteButton“ auf der Benutzeroberfläche.
Abbildung 2: (a) MediaRouteButton in der Menüleiste, (b) als View, (c) in PlayerView und (d) Dialogfeld mit für Google Cast optimierten Geräten.

Dem Player ein Composable MediaRouteButton hinzufügen

Sie können das MediaRouteButton-Composable in die Benutzeroberfläche Ihres Players einfügen. Weitere Informationen finden Sie im Leitfaden zum Erstellen von Prompts.

Kotlin

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.media3.cast.MediaRouteButton

@Composable
fun PlayerComposeView(player: Player, modifier: Modifier = Modifier) {
  var controlsVisible by remember { mutableStateOf(false) }

  Box(
    modifier = modifier.clickable { controlsVisible = true },
    contentAlignment = Alignment.Center,
  ) {
    PlayerSurface(player = player, modifier = modifier)
    AnimatedVisibility(visible = controlsVisible, enter = fadeIn(), exit = fadeOut()) {
      Box(modifier = Modifier.fillMaxSize()) {
        MediaRouteButton(modifier = Modifier.align(Alignment.TopEnd))
        PrimaryControls(player = player, modifier = Modifier.align(Alignment.Center))
      }
    }
  }
}

@Composable
fun PrimaryControls(player: Player, modifier: Modifier = Modifier) {
  ...
}

MediaRouteButton zur PlayerView hinzufügen

Sie können die MediaRouteButton direkt über die UI-Steuerelemente der PlayerView hinzufügen. Nachdem Sie MediaController als Player für Ihr PlayerView festgelegt haben, geben Sie ein MediaRouteButtonViewProvider an, damit die Schaltfläche „Streamen“ auf dem Player angezeigt wird.

Kotlin

override fun onStart() {
  super.onStart()

  playerView.player = mediaController
  playerView.setMediaRouteButtonViewProvider(MediaRouteButtonViewProvider())
}

Java

@Override
public void onStart() {
  super.onStart();

  playerView.setPlayer(mediaController);
  playerView.setMediaRouteButtonViewProvider(new MediaRouteButtonViewProvider());
}

MediaRouteButton zum App-Leistenmenü hinzufügen

Wenn Sie ein MediaRouteButton im App-Leistenmenü einrichten möchten, erstellen Sie ein XML-Menü und überschreiben Sie onCreateOptionsMenu in Ihrem Activity.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:app="http://schemas.android.com/apk/res-auto">
  <item android:id="@+id/media_route_menu_item"
    android:title="@string/media_route_menu_title"
    app:showAsAction="always"
    app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"/>
</menu>

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    ...
    menuInflater.inflate(R.menu.sample_media_route_button_menu, menu)
    val menuItemFuture: ListenableFuture<MenuItem> =
        MediaRouteButtonFactory.setUpMediaRouteButton(
            context, menu, R.id.media_route_menu_item)
    Futures.addCallback(
        menuItemFuture,
        object : FutureCallback<MenuItem> {
            override fun onSuccess(menuItem: MenuItem?) {
                // Do something with the menu item.
            }

            override fun onFailure(t: Throwable) {
                // Handle the failure.
            }
        },
        executor)
    ...
}

Java

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    ...
    getMenuInflater().inflate(R.menu.sample_media_route_button_menu, menu);
    ListenableFuture<MenuItem> menuItemFuture =
        MediaRouteButtonFactory.setUpMediaRouteButton(
          context, menu, R.id.media_route_menu_item);
    Futures.addCallback(
        menuItemFuture,
        new FutureCallback<MenuItem>() {
          @Override
          public void onSuccess(MenuItem menuItem) {
            // Do something with the menu item.
          }

          @Override
          public void onFailure(Throwable t) {
            // Handle the failure.
          }
        },
        executor);
    ...
}

MediaRouteButton als Ansicht hinzufügen

Sie können ein MediaRouteButton in der Datei „layout.xml“ Ihrer Aktivität einrichten.

  <androidx.mediarouter.app.MediaRouteButton
      android:id="@+id/media_route_button"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:mediaRouteButtonTint="@android:color/white" />

Verwenden Sie für die Einrichtung des MediaRouteButton das Media3 Cast-MediaRouteButtonFactory in Ihrem Activity-Code.

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)

  findViewById<MediaRouteButton>(R.id.media_route_button)?.also {
    val unused = MediaRouteButtonFactory.setUpMediaRouteButton(context, it)
  }
}

Java

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    MediaRouteButton button = findViewById(R.id.media_route_button);
    ListenableFuture<Void> setUpFuture =
        MediaRouteButtonFactory.setUpMediaRouteButton(context, button);
}

Aktivitäts-Listener

Erstellen Sie in Ihrem Activity einen Player.Listener, um auf Änderungen des Wiedergabeorts von Medien zu reagieren. Wenn sich die playbackType zwischen PLAYBACK_TYPE_LOCAL und PLAYBACK_TYPE_REMOTE ändert, können Sie die Benutzeroberfläche nach Bedarf anpassen. Um Speicherlecks zu vermeiden und die Listener-Aktivität auf den Zeitraum zu beschränken, in dem Ihre App sichtbar ist, registrieren Sie den Listener in onStart und heben Sie die Registrierung in onStop auf:

Kotlin

import androidx.media3.common.DeviceInfo
import androidx.media3.common.Player

private val playerListener: Player.Listener =
  object : Player.Listener {
    override fun onDeviceInfoChanged(deviceInfo: DeviceInfo) {
      if (deviceInfo.playbackType == DeviceInfo.PLAYBACK_TYPE_LOCAL) {
        // Add UI changes for local playback.
      } else if (deviceInfo.playbackType == DeviceInfo.PLAYBACK_TYPE_REMOTE) {
        // Add UI changes for remote playback.
      }
    }
  }

override fun onStart() {
  super.onStart()
  mediaController.addListener(playerListener)
}

override fun onStop() {
  super.onStop()
  mediaController.removeListener(playerListener)
}

Java

import androidx.media3.common.DeviceInfo;
import androidx.media3.common.Player;

private Player.Listener playerListener =
    new Player.Listener() {
      @Override
      public void onDeviceInfoChanged(DeviceInfo deviceInfo) {
        if (deviceInfo.playbackType == DeviceInfo.PLAYBACK_TYPE_LOCAL) {
          // Add UI changes for local playback.
        } else if (deviceInfo.playbackType == DeviceInfo.PLAYBACK_TYPE_REMOTE) {
          // Add UI changes for remote playback.
        }
      }
    };

@Override
protected void onStart() {
  super.onStart();
  mediaController.addListener(playerListener);
}

@Override
protected void onStop() {
  super.onStop();
  mediaController.removeListener(playerListener);
}

Weitere Informationen zum Abhören und Reagieren auf Wiedergabeereignisse finden Sie im Leitfaden zu Player-Ereignissen.