CastPlayer è un'implementazione di Player di Jetpack Media3 che supporta sia la riproduzione locale che la trasmissione a un dispositivo remoto compatibile con Google Cast. CastPlayer
semplifica l'aggiunta della funzionalità di trasmissione alla tua app e offre funzionalità avanzate per
passare facilmente dalla riproduzione locale a quella remota. Questa guida mostra come
integrare CastPlayer nella tua app multimediale.
Per integrare Cast con altre piattaforme, consulta l'SDK Cast.
Acquistare un dispositivo compatibile con Google Cast
Per testare CastPlayer, devi disporre di un dispositivo compatibile con Google Cast. Tra le opzioni figurano Android
TV, Chromecast, smart speaker e smart display. Verifica che il dispositivo sia
configurato e connesso alla stessa rete Wi-Fi del tuo dispositivo mobile di sviluppo per
il rilevamento.
Aggiungere dipendenze di build
Per iniziare a utilizzare CastPlayer, aggiungi le dipendenze AndroidX Media3 e CastPlayer
al file build.gradle del modulo dell'app.
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"
Configura CastPlayer
Per configurare CastPlayer, aggiorna il file AndroidManifest.xml con un provider di opzioni.
Fornitore di opzioni
CastPlayer richiede un fornitore di opzioni per configurarne il comportamento. Per una
configurazione di base, puoi utilizzare DefaultCastOptionsProvider aggiungendolo al file
AndroidManifest.xml. Vengono utilizzate le impostazioni predefinite, inclusa l'applicazione ricevitore predefinita.
<application>
...
<meta-data
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="androidx.media3.cast.DefaultCastOptionsProvider" />
...
</application>
Per personalizzare la configurazione, implementa il tuo OptionsProvider personalizzato. Consulta
la guida CastOptions per scoprire come.
Aggiungere un destinatario per i trasferimenti di contenuti multimediali
L'aggiunta di un MediaTransferReceiver al manifest consente all'interfaccia utente di sistema di
rilevare i dispositivi compatibili con Google Cast sulla rete e reindirizzare i contenuti multimediali senza aprire
l'attività dell'app. Ad esempio, un utente può cambiare il dispositivo che riproduce i contenuti multimediali
della tua app dalla notifica multimediale.
<application>
...
<receiver android:name="androidx.mediarouter.media.MediaTransferReceiver" />
...
</application>
Crea un CastPlayer
Per la riproduzione remota con Cast, l'app deve essere in grado di gestire la riproduzione anche
quando l'utente non interagisce con un'attività dell'app, ad esempio tramite
la notifica multimediale di sistema. Per questo motivo, devi creare le istanze
ExoPlayer (per la riproduzione locale) e CastPlayer (per la riproduzione remota)
in un servizio, ad esempio MediaSessionService o MediaLibraryService.
Innanzitutto, crea l'istanza ExoPlayer e poi, quando crei l'istanza
CastPlayer, imposta ExoPlayer come istanza del giocatore locale. Puoi
poi passare dalla riproduzione dei contenuti multimediali sul tuo dispositivo mobile a quella sul dispositivo compatibile con Cast
dalla notifica dei contenuti multimediali o dalla notifica del blocco schermo. Media3 utilizza la funzionalità Output
Switcher per gestire i trasferimenti del lettore quando il percorso di output cambia da locale a remoto o da remoto a locale.
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(); }
Aggiungere elementi UI
Aggiungi un MediaRouteButton all'interfaccia utente della tua app. Se tocchi MediaRouteButton
si apre una finestra di dialogo che mostra un elenco di dispositivi compatibili con Google Cast disponibili sulla
rete. Quando l'utente seleziona un dispositivo, la riproduzione dei contenuti multimediali viene trasferita dal
dispositivo mobile al dispositivo ricevitore selezionato. Questa sezione mostra come aggiungere
il pulsante e ascoltare gli eventi per aggiornare la UI quando la riproduzione passa
da dispositivi locali a dispositivi remoti.
Imposta MediaRouteButton
Esistono quattro modi per aggiungere MediaRouteButton all'interfaccia utente dell'attività. La
scelta migliore dipende dal design e dai requisiti della tua app.
- UI di composizione: aggiungi un composable del pulsante.
- Interfaccia utente delle visualizzazioni:
- Aggiungi il pulsante al menu della barra delle app.
- Aggiungi il pulsante all'interno di
PlayerView. - Aggiungi il pulsante come
Viewstandard.
Aggiungere un componente componibile MediaRouteButton al player
Puoi aggiungere il composable MediaRouteButton all'interfaccia utente del tuo player. Per ulteriori informazioni, consulta la guida Compose.
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) { ... }
Aggiungi MediaRouteButton a PlayerView
Puoi aggiungere MediaRouteButton direttamente nei controlli dell'interfaccia utente di PlayerView. Dopo aver impostato MediaController come lettore per il tuo
PlayerView, fornisci un MediaRouteButtonViewProvider per visualizzare il pulsante Trasmetti
sul lettore.
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()); }
Aggiungere MediaRouteButton al menu della barra delle app
Per configurare un MediaRouteButton nel menu della barra delle app, crea un menu XML e
esegui l'override di onCreateOptionsMenu in 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); ... }
Aggiungere MediaRouteButton come visualizzazione
Puoi configurare un MediaRouteButton nel file layout.xml dell'attività.
<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" />
Per completare la configurazione di MediaRouteButton, utilizza MediaRouteButtonFactory Media3 Cast nel tuo codice Activity.
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); }
Activity Listener
Crea un Player.Listener nel tuo Activity per rilevare le modifiche alla posizione di riproduzione dei contenuti multimediali. Quando playbackType cambia tra PLAYBACK_TYPE_LOCAL
e PLAYBACK_TYPE_REMOTE, puoi regolare l'interfaccia utente in base alle tue esigenze. Per evitare perdite di memoria e limitare l'attività del listener solo a quando l'app è visibile, registra il listener in onStart e annullane la registrazione in onStop:
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); }
Per saperne di più sull'ascolto e sulla risposta agli eventi di riproduzione, consulta la guida Eventi del player.