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 deiner App und bietet umfangreiche Funktionen für den nahtlosen Wechsel zwischen lokaler und Remote-Wiedergabe. In diesem Leitfaden wird beschrieben, wie Sie CastPlayer in Ihre Medien-App einbinden.
Informationen zum Einbinden von Cast in andere Plattformen findest du im Cast SDK.
Für Google Cast optimiertes Gerät kaufen
Zum Testen von CastPlayer benötigst du ein für Google Cast optimiertes Gerät. Zu den Optionen gehören Android TV, Chromecast, Smart Speaker und Smart Displays. Prüfe, ob dein Gerät eingerichtet und mit demselben WLAN wie dein Entwicklungs-Smartphone verbunden ist, damit es gefunden werden kann.
Build-Abhängigkeiten hinzufügen
Wenn du CastPlayer verwenden möchtest, füge die AndroidX Media3- und CastPlayer-Abhängigkeiten zur Datei build.gradle deines App-Moduls hinzu.
Kotlin
implementation("androidx.media3:media3-exoplayer:1.11.1")
implementation("androidx.media3:media3-ui:1.11.1")
implementation("androidx.media3:media3-session:1.11.1")
implementation("androidx.media3:media3-cast:1.11.1")
Groovy
implementation "androidx.media3:media3-exoplayer:1.11.1"
implementation "androidx.media3:media3-ui:1.11.1"
implementation "androidx.media3:media3-session:1.11.1"
implementation "androidx.media3:media3-cast:1.11.1"
CastPlayer konfigurieren
Wenn Sie den CastPlayer konfigurieren möchten, aktualisieren Sie die Datei AndroidManifest.xml mit einem Optionsanbieter.
Anbieter von Optionen
Für den CastPlayer ist ein Optionsanbieter erforderlich, um sein Verhalten zu konfigurieren. Für eine einfache Einrichtung können Sie DefaultCastOptionsProvider verwenden, indem Sie es der Datei AndroidManifest.xml hinzufügen. Dabei werden die Standardeinstellungen verwendet, einschließlich der Standard-Empfänger-App.
<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 Ihre eigene benutzerdefinierte OptionsProvider. Weitere Informationen findest du im Leitfaden zu CastOptions.
Empfänger für Medienübertragungen hinzufügen
Wenn du deinem Manifest ein MediaTransferReceiver hinzufügst, kann die System-UI für Google Cast optimierte Geräte im Netzwerk erkennen und Medien umleiten, ohne die App-Aktivität zu öffnen. Beispielsweise kann ein Nutzer das Gerät, auf dem die Medien deiner App wiedergegeben werden, über die Medienbenachrichtigung ändern.
<application>
...
<receiver android:name="androidx.mediarouter.media.MediaTransferReceiver" />
...
</application>
CastPlayer erstellen
Für die Remote-Wiedergabe mit Cast sollte Ihre App die Wiedergabe auch dann verwalten können, wenn der Nutzer nicht mit einer Aktivität Ihrer App interagiert, z. B. über die Medienbenachrichtigung des Systems. 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 die ExoPlayer-Instanz und legen Sie dann beim Erstellen der CastPlayer-Instanz ExoPlayer als lokale Player-Instanz fest. Anschließend kannst du 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 Ausgabeauswahl, um die Übertragung des Players zu verarbeiten, wenn sich die Ausgaberoute von lokal zu remote oder von remote zu lokal ändert.
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 du auf das MediaRouteButton tippst, wird ein Dialogfeld mit einer Liste der im Netzwerk verfügbaren für Google Cast optimierten Geräte 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 wird beschrieben, 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 der Benutzeroberfläche Ihrer Aktivität hinzuzufügen. Die beste Wahl hängt vom Design und den Anforderungen Ihrer Anwendung ab.
- Compose UI: Fügen Sie eine komponierbare Funktion für eine Schaltfläche hinzu.
- Ansichten-UI:
- Fügen Sie die Schaltfläche dem Menü der App-Leiste hinzu.
- Fügen Sie den Button in
PlayerViewhinzu. - Fügen Sie die Schaltfläche als Standard-
Viewhinzu.
Dem Player ein Composable MediaRouteButton hinzufügen
Sie können die komponierbare Funktion MediaRouteButton der Benutzeroberfläche Ihres Players hinzufügen. Weitere Informationen finden Sie im Compose-Leitfaden.
@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) { // ... }
Füge die MediaRouteButton zur PlayerView hinzu.
Du kannst die MediaRouteButton direkt in den UI-Steuerelementen der PlayerView hinzufügen. Nachdem du den MediaController als Player für deine PlayerView festgelegt hast, gib einen MediaRouteButtonViewProvider an, um das Cast-Symbol im Player anzuzeigen.
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 zur App-Leiste hinzufügen
Wenn du im App-Leistenmenü ein MediaRouteButton einrichten möchtest, erstelle ein XML-Menü und überschreibe onCreateOptionsMenu in deiner 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, ) // ... return true }
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); // ... return true; }
MediaRouteButton als Ansicht hinzufügen
Sie können in der Datei „activity_layout.xml“ ein MediaRouteButton 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" />
Verwende zum Abschließen der Einrichtung für MediaRouteButton die Media3 Cast-MediaRouteButtonFactory in deinem 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) { super.onCreate(savedInstanceState); // ... MediaRouteButton button = findViewById(R.id.media_route_button); ListenableFuture<Void> setUpFuture = MediaRouteButtonFactory.setUpMediaRouteButton(context, button); }
Aktivitäts-Listener
Erstelle einen Player.Listener in deiner Activity, um auf Änderungen des Wiedergabeorts von Medien zu reagieren. Wenn sich der 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 die Zeit zu beschränken, in der Ihre App sichtbar ist, registrieren Sie den Listener in onStart und heben Sie die Registrierung in onStop auf:
Kotlin
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
private final 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.