Начало работы с CastPlayer

CastPlayer — это реализация Jetpack Media3 Player , которая поддерживает как локальное воспроизведение, так и трансляцию на удалённое устройство с поддержкой Cast. CastPlayer упрощает добавление функций трансляции в ваше приложение и предоставляет широкие возможности для удобного переключения между локальным и удалённым воспроизведением. В этом руководстве показано, как интегрировать CastPlayer в ваше медиаприложение.

Для интеграции Cast с другими платформами см. Cast SDK .

Добавить CastPlayer как зависимость

Чтобы начать использовать CastPlayer, добавьте необходимые зависимости AndroidX Media3 и CastPlayer в файл build.gradle вашего модуля приложения.

Котлин

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")

Круто

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"

Чтобы найти последнюю альфа-версию, необходимую для интеграции CastPlayer в ваше приложение, ознакомьтесь с примечаниями к выпуску Jetpack Media . Все модули должны быть одной версии.

Дополнительную информацию о доступных библиотечных модулях см. на странице Google Maven AndroidX Media3 .

Настройте свой CastPlayer

Чтобы настроить CastPlayer , обновите файл AndroidManifest.xml , указав поставщик опций.

Поставщик опций

Для настройки поведения CastPlayer требуется поставщик параметров. Для базовой настройки можно использовать поставщик параметров по умолчанию, добавив его в файл AndroidManifest.xml . При этом будут использоваться настройки по умолчанию, включая приложение-приёмник по умолчанию.

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

Чтобы настроить конфигурацию, реализуйте собственный OptionsProvider . Инструкции см. в руководстве по CastOptions.

Добавить приемник для передачи медиафайлов

Добавление объекта MediaTransferReceiver в манифест позволяет системному пользовательскому интерфейсу перенаправлять медиаданные без открытия активности приложения. Например, пользователь может изменить устройство, воспроизводящее медиаданные вашего приложения, из уведомления о медиафайле .

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

Создайте CastPlayer

Для удалённого воспроизведения с помощью Cast ваше приложение должно иметь возможность управлять воспроизведением, даже когда пользователь не взаимодействует с Activity из вашего приложения, например, через системное уведомление о медиа. Поэтому необходимо создать экземпляры ExoPlayer (для локального воспроизведения) и CastPlayer (для удалённого воспроизведения) в сервисе, например, MediaSessionService или MediaLibraryService . Сначала создайте экземпляр ExoPlayer, а затем при создании экземпляра CastPlayer укажите ExoPlayer в качестве локального экземпляра проигрывателя. После этого Media3 сможет обрабатывать передачу проигрывателей при изменении маршрута вывода с локального на удалённый или с удалённого на локальный.

Котлин

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

Ява

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

Добавить элементы пользовательского интерфейса

Добавьте кнопку MediaRouteButton в пользовательский интерфейс вашего приложения, чтобы пользователи могли выбирать устройство Cast. В этом разделе показано, как добавить кнопку и отслеживать события для обновления пользовательского интерфейса при переключении воспроизведения между локальным и удалённым устройствами.

Установите MediaRouteButton

Существует четыре возможных способа добавить MediaRouteButton в пользовательский интерфейс вашей активности для взаимодействия с пользователями. Выбор зависит от того, как должен выглядеть и работать пользовательский интерфейс вашей активности проигрывателя.

Добавить кнопку «Компонуемый медиа-маршрут» в проигрыватель

Вы можете добавить компонуемую MediaRouteButton в пользовательский интерфейс вашего проигрывателя. Подробнее см. в руководстве по компоновке .

Котлин

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

Добавьте кнопку маршрутизации медиа в PlayerView

Вы можете добавить MediaRouteButton непосредственно в элементы управления пользовательского интерфейса PlayerView . После настройки MediaController в качестве проигрывателя для PlayerView предоставьте поставщик MediaRouteButtonViewProvider для отображения кнопки трансляции на проигрывателе.

Котлин

override fun onStart() {
  super.onStart()

  playerView.player = mediaController
  playerView.setMediaRouteButtonViewProvider(MediaRouteButtonViewProvider())
}

Ява

@Override
public void onStart() {
  super.onStart();

  playerView.setPlayer(mediaController);
  playerView.setMediaRouteButtonViewProvider(new MediaRouteButtonViewProvider());
}

Добавить кнопку маршрутизации мультимедиа в меню панели приложения

Этот метод настраивает кнопку маршрутизации медиа в меню панели приложения. Для отображения этого стиля кнопки необходимо обновить как файл манифеста, так и 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>

Котлин

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

Ява

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

Добавить кнопку маршрутизации медиа в качестве представления

В качестве альтернативы вы можете настроить MediaRouteButton в файле layout.xml вашей активности. Для завершения настройки MediaRouteButton используйте Media3 Cast MediaRouteButtonFactory в коде вашей Activity .

Котлин

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)

  findViewById<MediaRouteButton>(R.id.media_route_button)?.also {
    val unused = MediaRouteButtonFactory.setUpMediaRouteButton(context, it)
  }
}

Ява

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    MediaRouteButton button = findViewById(R.id.media_route_button);
    ListenableFuture<Void> setUpFuture =
        MediaRouteButtonFactory.setUpMediaRouteButton(context, button);
}

Слушатель активности

Создайте Player.Listener в вашей Activity для отслеживания изменений места воспроизведения медиафайлов. При изменении типа playbackType между PLAYBACK_TYPE_LOCAL и PLAYBACK_TYPE_REMOTE вы можете настроить пользовательский интерфейс по своему усмотрению. Чтобы предотвратить утечки памяти и ограничить активность прослушивателя только временем, когда ваше приложение отображается, зарегистрируйте его в onStart и отмените регистрацию в onStop :

Котлин

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

Ява

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

Дополнительную информацию о прослушивании и реагировании на события воспроизведения см. в руководстве по событиям проигрывателя .