Der CastPlayer ist eine Jetpack Media3 Player-Implementierung, die sowohl die lokale Wiedergabe als auch das Streaming 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, um nahtlos zwischen lokaler und Remote-Wiedergabe zu wechseln. In dieser Anleitung erfährst du, wie du
CastPlayer in deine Media-App einbindest.
Informationen zum Einbinden von Cast in andere Plattformen findest du im Cast SDK.
Gerät für Google Cast optimiert besorgen
Zum Testen von CastPlayer benötigst du ein für Google Cast optimiertes Gerät. Zur Auswahl stehen Android TV, Chromecast, Smart Speaker und Smart Displays. Achte darauf, dass dein Gerät eingerichtet und mit demselben WLAN wie dein mobiles Entwicklungsgerät verbunden ist, damit es erkannt werden kann.
Build-Abhängigkeiten hinzufügen
Wenn du CastPlayer verwenden möchtest, füge die AndroidX Media3- und CastPlayer-Abhängigkeiten der Datei build.gradle deines App-Moduls hinzu.
Kotlin
implementation("androidx.media3:media3-exoplayer:1.10.0")
implementation("androidx.media3:media3-ui:1.10.0")
implementation("androidx.media3:media3-session:1.10.0")
implementation("androidx.media3:media3-cast:1.10.0")
Groovy
implementation "androidx.media3:media3-exoplayer:1.10.0"
implementation "androidx.media3:media3-ui:1.10.0"
implementation "androidx.media3:media3-session:1.10.0"
implementation "androidx.media3:media3-cast:1.10.0"
CastPlayer konfigurieren
Um den CastPlayer zu konfigurieren, aktualisiere die Datei AndroidManifest.xml mit einem Optionsanbieter.
Optionsanbieter
Der CastPlayer benötigt einen Optionsanbieter, um sein Verhalten zu konfigurieren. Für eine
einfache Einrichtung kannst du den DefaultCastOptionsProvider verwenden, indem du ihn der Datei
AndroidManifest.xml hinzufügst. 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 du die Konfiguration anpassen möchtest, implementiere einen eigenen benutzerdefinierten OptionsProvider. Weitere Informationen findest du in der Anleitung zu CastOptions.
Empfänger für Medienübertragungen hinzufügen
Wenn du deinem Manifest einen 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. Ein Nutzer kann beispielsweise 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 muss deine App die Wiedergabe auch dann verwalten können, wenn der Nutzer nicht mit einer Activity deiner App interagiert, z. B. über die System-Medienbenachrichtigung. Aus diesem Grund solltest du deine
ExoPlayer (für die lokale Wiedergabe) und CastPlayer (für die Remote-Wiedergabe)
Instanzen in einem Dienst wie MediaSessionService oder MediaLibraryService erstellen.
Erstelle zuerst deine ExoPlayer-Instanz und lege dann beim Erstellen deiner
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 Ausgabewechsel , um Player-Übertragungen 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üge der UI deiner App einen MediaRouteButton hinzu. Wenn du auf den MediaRouteButton tippst, 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 erfährst du, wie du die Schaltfläche hinzufügst und auf Ereignisse wartest, um die UI zu aktualisieren, wenn die Wiedergabe zwischen lokalen und Remote-Geräten wechselt.
MediaRouteButton festlegen
Es gibt vier Möglichkeiten, den MediaRouteButton der UI deiner Aktivität hinzuzufügen. Die beste Wahl hängt vom Design und den Anforderungen deiner App ab.
- Compose-UI: Füge eine Schaltfläche hinzu.
- Views-UI:
- Füge die Schaltfläche dem App-Leistenmenü hinzu.
- Füge die Schaltfläche in
PlayerViewein. - Füge die Schaltfläche als Standard-
Viewhinzu.
Composable MediaRouteButton zum Player hinzufügen
Du kannst den MediaRouteButton Composable der UI deines Players hinzufügen. Weitere Informationen findest du in der Compose-Anleitung.
@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 zu PlayerView hinzufügen
Du kannst den MediaRouteButton direkt in den PlayerView's UI
Steuerelementen hinzufügen. Nachdem du MediaController als Player für deine
PlayerView festgelegt hast, gib einen MediaRouteButtonViewProvider an, um die Cast
Schaltfläche auf dem 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 dem App-Leistenmenü hinzufügen
Um ein MediaRouteButton im App-Leistenmenü einzurichten, 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 View hinzufügen
Du kannst einen MediaRouteButton in der Datei layout.xml deiner 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" />
Verwende zum Abschließen der Einrichtung für den 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); }
Activity-Listener
Erstelle in deiner Activity einen Player.Listener, um auf Änderungen am Wiedergabeort zu warten. Wenn sich playbackType zwischen PLAYBACK_TYPE_LOCAL und PLAYBACK_TYPE_REMOTE ändert, kannst du die UI nach Bedarf anpassen. Um Speicherlecks zu vermeiden und die Listener-Aktivität nur auf den Zeitraum zu beschränken, in dem deine App sichtbar ist, registriere den Listener in onStart und hebe 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 Warten auf Wiedergabeereignisse und zum Reagieren darauf findest du in der Anleitung zu Player-Ereignissen.