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 umożliwiające 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-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"

Zapoznaj się z informacjami o wersji Jetpack Media, aby znaleźć najnowszą wersję alfa i zintegrować CastPlayer z aplikacją. Wszystkie moduły muszą być w tej samej wersji.

Więcej informacji o dostępnych modułach biblioteki znajdziesz na stronie Google Maven AndroidX Media3.

Konfigurowanie odtwarzacza CastPlayer

Aby skonfigurować CastPlayer, zaktualizuj plik AndroidManifest.xml, dodając dostawcę opcji.

Dostawca opcji

Funkcja CastPlayer wymaga skonfigurowania jej 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. Użytkownik może na przykład 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 ExoPlayer (do odtwarzania lokalnego) i CastPlayer (do odtwarzania zdalnego) należy tworzyć w usłudze, takiej jak MediaSessionService lub MediaLibraryService. Najpierw utwórz instancję ExoPlayera, a potem podczas tworzenia instancji CastPlayera 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 sposoby dodania 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ć funkcję kompozycyjną 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ć element MediaRouteButton w pliku layout.xml aktywności. Aby dokończyć konfigurację MediaRouteButton, użyj MediaRouteButtonFactoryMedia3 Cast w Activitykodzie.

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 monitorować zmiany lokalizacji odtwarzania multimediów. Gdy playbackType zmienia się z PLAYBACK_TYPE_LOCAL na PLAYBACK_TYPE_REMOTE, możesz dostosować interfejs zgodnie z potrzebami. 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.