Iniziare a utilizzare CastPlayer

CastPlayer è un'implementazione di Player di Jetpack Media3 che supporta sia la riproduzione locale sia 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.

Aggiungere CastPlayer come dipendenza

Per iniziare a utilizzare CastPlayer, aggiungi le dipendenze AndroidX Media3 e CastPlayer necessarie nel file build.gradle del modulo dell'app.

Kotlin

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

Groovy

implementation "androidx.media3:media3-exoplayer:1.9.0-alpha01"
implementation "androidx.media3:media3-ui:1.9.0-alpha01"
implementation "androidx.media3:media3-session:1.9.0-alpha01"
implementation "androidx.media3:media3-cast:1.9.0-alpha01"

Consulta le note di rilascio di Jetpack Media per trovare l'ultima versione alpha in modo da poter integrare CastPlayer nella tua app. Tutti i moduli devono avere la stessa versione.

Per ulteriori informazioni sui moduli della libreria disponibili, consulta la pagina Google Maven AndroidX Media3.

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 il provider di opzioni predefinito 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. Per scoprire come fare, consulta la guida CastOptions.

Aggiungere un destinatario per i trasferimenti di contenuti multimediali

L'aggiunta di un MediaTransferReceiver al manifest consente all'interfaccia utente di sistema di 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 di 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 player locale. Media3 potrà quindi gestire i trasferimenti del player quando la route di output cambia da locale a remota o da remota 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 per consentire agli utenti di selezionare un dispositivo di trasmissione. 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 metodi possibili per aggiungere MediaRouteButton all'interfaccia utente dell'attività con cui gli utenti possono interagire. La scelta dipende da come vuoi che appaia e funzioni l'interfaccia utente della tua attività del player.

Aggiungere un pulsante di route multimediale componibile al lettore

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) {
  ...
}

Aggiungere il pulsante di selezione dell'itinerario multimediale 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 il pulsante di selezione dell'itinerario multimediale al menu della barra delle app

Questo metodo configura un pulsante di percorso multimediale nel menu della barra dell'app. Per mostrare questo stile di pulsante, sono necessari aggiornamenti sia del file manifest sia di 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 il pulsante di selezione dell'itinerario multimediale come visualizzazione

In alternativa, puoi configurare un MediaRouteButton nel file layout.xml dell'attività. Per completare la configurazione di MediaRouteButton, utilizza MediaRouteButtonFactory di Media3 Cast nel 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.