CastPlayer – это реализация Player в Jetpack Media3, которая поддерживает как локальное воспроизведение, так и трансляцию на удаленное устройство с поддержкой Cast. CastPlayer упрощает добавление функций трансляции в приложение и предоставляет широкие возможности для плавного переключения между локальным и удаленным воспроизведением. В этом руководстве рассказывается, как интегрировать CastPlayer в мультимедийное приложение.
Чтобы интегрировать Cast с другими платформами, ознакомьтесь с Cast SDK.
Приобретите устройство с поддержкой Cast
Чтобы протестировать CastPlayer, вам понадобится устройство с поддержкой Cast. например Android TV, Chromecast, умные колонки и умные дисплеи. Убедитесь, что устройство настроено и подключено к той же сети Wi-Fi, что и мобильное устройство, используемое для разработки.
Добавление зависимостей
Чтобы начать использовать CastPlayer, добавьте зависимости AndroidX Media3 и CastPlayer в файл build.gradle модуля приложения.
Kotlin
implementation("androidx.media3:media3-exoplayer:1.11.1")
implementation("androidx.media3:media3-ui:1.11.1")
implementation("androidx.media3:media3-session:1.11.1")
implementation("androidx.media3:media3-cast:1.11.1")
Яркий
implementation "androidx.media3:media3-exoplayer:1.11.1"
implementation "androidx.media3:media3-ui:1.11.1"
implementation "androidx.media3:media3-session:1.11.1"
implementation "androidx.media3:media3-cast:1.11.1"
Настройка CastPlayer
Чтобы настроить CastPlayer, добавьте в файл AndroidManifest.xml поставщика параметров.
Поставщик вариантов
Для настройки поведения CastPlayer требуется поставщик параметров. Для базовой настройки можно использовать DefaultCastOptionsProvider, добавив его в файл 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 в манифест, вы позволите системному интерфейсу обнаруживать устройства с поддержкой Cast в сети и перенаправлять медиаконтент, не открывая приложение. Например, пользователь может изменить устройство, на котором воспроизводится медиаконтент из вашего приложения, в уведомлении о медиа.
<application>
...
<receiver android:name="androidx.mediarouter.media.MediaTransferReceiver" />
...
</application>
Как создать CastPlayer
При удаленном воспроизведении с помощью Cast ваше приложение должно иметь возможность управлять воспроизведением, даже когда пользователь не взаимодействует с Activity из вашего приложения, например через системное уведомление о мультимедиа. Поэтому вам следует создать экземпляры ExoPlayer (для локального воспроизведения) и CastPlayer (для удаленного воспроизведения) в сервисе, например MediaSessionService или MediaLibraryService.
Сначала создайте экземпляр ExoPlayer, а затем при создании экземпляра CastPlayer задайте ExoPlayer в качестве экземпляра локального проигрывателя. После этого вы сможете переключать воспроизведение медиаконтента между мобильным устройством и устройством с поддержкой Cast в уведомлении о медиаконтенте или уведомлении на заблокированном экране. Media3 использует функцию переключателя вывода для обработки передачи проигрывателя, когда маршрут вывода меняется с локального на удаленный или наоборот.
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(); }
Добавьте элементы интерфейса
Добавьте MediaRouteButton в интерфейс приложения. При нажатии на значок MediaRouteButton открывается диалоговое окно со списком доступных устройств с поддержкой Cast в сети. Когда пользователь выбирает устройство, воспроизведение медиаконтента переносится с мобильного устройства на выбранное устройство-получатель. В этом разделе рассказывается, как добавить кнопку и прослушивать события, чтобы обновлять интерфейс при переключении воспроизведения между локальными и удаленными устройствами.
Настройка кнопки MediaRouteButton
Добавить MediaRouteButton в интерфейс можно четырьмя способами. Выбор зависит от дизайна и требований вашего приложения.
- Compose UI. Добавьте composable-функцию кнопки.
- Интерфейс представлений:
- Добавьте кнопку в меню панели приложения.
- Добавьте кнопку в тег
PlayerView. - Добавьте кнопку в виде стандартного элемента
View.
Добавьте Composable MediaRouteButton в проигрыватель
Вы можете добавить MediaRouteButton composable-функцию в интерфейс проигрывателя. Дополнительную информацию можно найти в руководстве по Compose.
@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) { // ... }
Добавьте MediaRouteButton в PlayerView
Вы можете добавить MediaRouteButton непосредственно в элементы управления пользовательского интерфейса PlayerView. После того как вы установите MediaController в качестве проигрывателя для PlayerView, укажите MediaRouteButtonViewProvider, чтобы на проигрывателе показывалась кнопка трансляции.
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()); }
Добавьте MediaRouteButton в меню панели приложения.
Чтобы настроить MediaRouteButton в меню панели приложения, создайте меню XML и переопределите onCreateOptionsMenu в 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, ) // ... return true }
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); // ... return true; }
Добавьте MediaRouteButton в качестве представления
Вы можете настроить MediaRouteButton в файле layout.xml.
<androidx.mediarouter.app.MediaRouteButton
android:id="@+id/media_route_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:mediaRouteButtonTint="@android:color/white" />
Чтобы завершить настройку MediaRouteButton, используйте Media3 Cast MediaRouteButtonFactory в коде 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) { super.onCreate(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:
Kotlin
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
private final 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); }
Подробную информацию о том, как отслеживать события воспроизведения и реагировать на них, можно найти в руководстве по событиям проигрывателя.