Premiers pas avec CastPlayer

CastPlayer est une implémentation Player Jetpack Media3 qui prend en charge la lecture locale et la diffusion sur un appareil Cast à distance. CastPlayer simplifie l'ajout de la fonctionnalité Cast à votre application et fournit des fonctionnalités riches pour passer facilement de la lecture locale à la lecture à distance. Ce guide vous explique comment intégrer CastPlayer à votre application multimédia.

Pour intégrer Cast à d'autres plates-formes, consultez le SDK Cast.

Ajouter CastPlayer en tant que dépendance

Pour commencer à utiliser CastPlayer, ajoutez les dépendances AndroidX Media3 et CastPlayer dont vous avez besoin dans le fichier build.gradle de votre module d'application.

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"

Consultez les notes de version de Jetpack Media pour trouver la dernière version alpha et intégrer CastPlayer à votre application. Tous les modules doivent être de la même version.

Pour en savoir plus sur les modules de bibliothèque disponibles, consultez la page Google Maven AndroidX Media3.

Configurer votre CastPlayer

Pour configurer le CastPlayer, mettez à jour votre fichier AndroidManifest.xml avec un fournisseur d'options.

Fournisseur d'options

Le CastPlayer nécessite un fournisseur d'options pour configurer son comportement. Pour une configuration de base, vous pouvez utiliser le fournisseur d'options par défaut en l'ajoutant à votre fichier AndroidManifest.xml. Il utilise les paramètres par défaut, y compris l'application réceptrice par défaut.

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

Pour personnaliser la configuration, implémentez votre propre OptionsProvider personnalisé. Pour savoir comment, consultez le guide CastOptions.

Ajouter un récepteur pour les transferts de contenus multimédias

L'ajout d'un MediaTransferReceiver à votre fichier manifeste permet à l'UI système de rediriger les contenus multimédias sans ouvrir l'activité de l'application. Par exemple, un utilisateur peut changer l'appareil sur lequel les contenus multimédias de votre application sont lus à partir de la notification multimédia.

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

Créer un CastPlayer

Pour la lecture à distance avec Cast, votre application doit être en mesure de gérer la lecture même lorsque l'utilisateur n'interagit pas avec une activité de votre application, par exemple via la notification multimédia du système. Pour cette raison, vous devez créer vos instances ExoPlayer (pour la lecture locale) et CastPlayer (pour la lecture à distance) dans un service, tel que MediaSessionService ou MediaLibraryService. Commencez par créer votre instance ExoPlayer, puis, lorsque vous créez votre instance CastPlayer, définissez ExoPlayer comme instance de lecteur local. Media3 pourra alors gérer les transferts de lecteur lorsque la route de sortie passe de locale à distante ou de distante à 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();
}

Ajouter des éléments d'interface utilisateur

Ajoutez un MediaRouteButton à l'UI de votre application pour permettre aux utilisateurs de sélectionner un appareil Cast. Cette section vous explique comment ajouter le bouton et écouter les événements pour mettre à jour votre UI lorsque la lecture bascule entre les appareils locaux et distants.

Définir le MediaRouteButton

Il existe quatre méthodes possibles pour ajouter le MediaRouteButton à l'UI de votre activité afin que les utilisateurs puissent interagir avec. Le choix dépendra de l'apparence et du fonctionnement de l'UI pour l'activité de votre lecteur.

Ajouter un bouton de route média composable au lecteur

Vous pouvez ajouter le composable MediaRouteButton à l'UI de votre lecteur. Pour en savoir plus, consultez le guide 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) {
  ...
}

Ajouter le bouton de route média à PlayerView

Vous pouvez ajouter MediaRouteButton directement dans les commandes de l'interface utilisateur de PlayerView. Après avoir défini le MediaController comme lecteur pour votre PlayerView, fournissez un MediaRouteButtonViewProvider pour afficher le bouton Cast sur le lecteur.

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());
}

Ajouter le bouton de route média au menu de la barre d'application

Cette méthode configure un bouton de route média dans le menu de la barre d'application. Pour afficher ce style de bouton, vous devez mettre à jour le fichier manifeste et 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);
    ...
}

Ajouter le bouton de sélection de route multimédia en tant que vue

Vous pouvez également configurer un MediaRouteButton dans votre fichier layout.xml d'activité. Pour terminer la configuration de MediaRouteButton, utilisez MediaRouteButtonFactory Media3 Cast dans votre code 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);
}

Écouteur d'activité

Créez un Player.Listener dans votre Activity pour écouter les modifications apportées à l'emplacement de lecture du contenu multimédia. Lorsque playbackType passe de PLAYBACK_TYPE_LOCAL à PLAYBACK_TYPE_REMOTE, vous pouvez ajuster votre UI si nécessaire. Pour éviter les fuites de mémoire et limiter l'activité de l'écouteur uniquement lorsque votre application est visible, enregistrez l'écouteur dans onStart et désenregistrez-le dans 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);
}

Pour en savoir plus sur l'écoute et la réponse aux événements de lecture, consultez le guide sur les événements du lecteur.