Pierwsze kroki z CastPlayer

CastPlayer to implementacja odtwarzacza Jetpack Media3, która obsługuje zarówno odtwarzanie lokalne, jak i przesyłanie na zdalne urządzenie obsługujące Cast. CastPlayer ułatwia dodawanie do aplikacji funkcji przesyłania i zapewnia bogate funkcje, które umożliwiają płynne przełączanie się między odtwarzaniem lokalnym a zdalnym. Z tego przewodnika dowiesz się, jak zintegrować CastPlayer z aplikacją multimedialną.

Aby zintegrować Cast z innymi platformami, zapoznaj się z pakietem Cast SDK.

Dodawanie CastPlayer jako zależności

Aby zacząć korzystać z CastPlayer, dodaj do pliku build.gradle modułu aplikacji potrzebne zależności AndroidX Media3 i CastPlayer.

Kotlin

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

Groovy

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

Konfigurowanie odtwarzacza CastPlayer

Aby skonfigurować CastPlayer, zaktualizuj plik AndroidManifest.xml za pomocą dostawcy opcji.

Dostawca opcji

Element CastPlayer wymaga skonfigurowania jego działania przez dostawcę opcji. W przypadku konfiguracji podstawowej możesz użyć domyślnego dostawcy opcji, dodając go do pliku AndroidManifest.xml. Używa domyślnych ustawień, w tym domyślnej aplikacji odbiornika.

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

Aby dostosować konfigurację, zaimplementuj własny element niestandardowy OptionsProvider. Więcej informacji znajdziesz w przewodniku CastOptions.

Dodawanie odbiorcy do przesyłania multimediów

Dodanie elementu MediaTransferReceiver do pliku manifestu umożliwia interfejsowi systemu przekierowywanie multimediów bez otwierania aktywności aplikacji. Na przykład użytkownik może zmienić urządzenie, na którym odtwarzane są multimedia z Twojej aplikacji, za pomocą powiadomienia o multimediach.

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

Tworzenie odtwarzacza CastPlayer

W przypadku odtwarzania zdalnego za pomocą Cast aplikacja powinna zarządzać odtwarzaniem nawet wtedy, gdy użytkownik nie wchodzi w interakcję z aktywnością w aplikacji, np. za pomocą systemowego powiadomienia o multimediach. Z tego powodu instancje ExoPlayera (do odtwarzania lokalnego) i CastPlayer należy tworzyć w usłudze, np. MediaSessionService lub MediaLibraryService. Najpierw utwórz instancję ExoPlayera, a potem podczas tworzenia instancji CastPlayer ustaw ExoPlayera jako lokalną instancję odtwarzacza. Media3 będzie wtedy mogło obsługiwać przenoszenie odtwarzacza, gdy trasa wyjściowa zmieni się z lokalnej na zdalną lub ze zdalnej na lokalną.

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

Dodawanie elementów interfejsu

Dodaj do interfejsu aplikacji ikonę MediaRouteButton, aby umożliwić użytkownikom wybieranie urządzenia Cast. W tej sekcji dowiesz się, jak dodać przycisk i nasłuchiwać zdarzeń, aby aktualizować interfejs, gdy odtwarzanie przełącza się między urządzeniami lokalnymi i zdalnymi.

Ustawianie elementu MediaRouteButton

Istnieją 4 metody dodawania elementu MediaRouteButton do interfejsu aktywności, aby użytkownicy mogli z nim wchodzić w interakcje. Wybór zależy od tego, jak ma wyglądać i działać interfejs aktywności odtwarzacza.

Dodawanie do odtwarzacza przycisku trasy multimediów z funkcją kompozycji

Możesz dodać komponent MediaRouteButton do interfejsu odtwarzacza. Więcej informacji znajdziesz w przewodniku 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) {
  ...
}

Dodawanie przycisku trasy multimediów do widoku PlayerView

Możesz dodać MediaRouteButton bezpośrednio w elementach interfejsu PlayerView. Po ustawieniu MediaController jako odtwarzacza dla elementu PlayerView podaj MediaRouteButtonViewProvider, aby wyświetlić przycisk przesyłania na odtwarzaczu.

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

Dodawanie przycisku trasy multimediów do menu paska aplikacji

Ta metoda konfiguruje przycisk trasy multimediów w menu paska aplikacji. Aby wyświetlić ten styl przycisku, musisz zaktualizować zarówno plik manifestu, jak i 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);
    ...
}

Dodawanie przycisku trasy multimediów jako widoku

Możesz też skonfigurować MediaRouteButton w pliku activity_layout.xml. Aby dokończyć konfigurację MediaRouteButton, użyj w kodzie Activity interfejsu Media3 Cast MediaRouteButtonFactory.

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

Detektor aktywności

Utwórz Player.ListenerActivity, aby nasłuchiwać zmian lokalizacji odtwarzania multimediów. Gdy playbackType zmieni się z PLAYBACK_TYPE_LOCAL na PLAYBACK_TYPE_REMOTE, możesz dostosować interfejs. Aby zapobiec wyciekom pamięci i ograniczyć aktywność odbiornika tylko do momentu, gdy aplikacja jest widoczna, zarejestruj odbiornik w funkcji onStart i wyrejestruj go w funkcji 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);
}

Więcej informacji o nasłuchiwaniu zdarzeń odtwarzania i reagowaniu na nie znajdziesz w przewodniku zdarzenia odtwarzacza.