Проигрыватель – это компонент приложения, который позволяет воспроизводить медиаконтент.
Интерфейс Media3 Player задает структуру для функций, которые обычно выполняет проигрыватель. К ним относятся:
- управлять воспроизведением, например запускать, приостанавливать и перематывать контент;
- запрашивать свойства воспроизводимого контента, например позицию воспроизведения;
- управление плейлистом или очередью медиаконтента;
- настраивать параметры воспроизведения, например перемешивание, повтор, скорость и громкость;
- Отрисовка видео на экране
В Media3 также реализован интерфейс Player, который называется ExoPlayer.
Единый интерфейс между компонентами
Интерфейс Player реализуют несколько компонентов Media3, например:
| Компонент | Описание и примечания о поведении |
|---|---|
ExoPlayer |
API медиапроигрывателя и реализация интерфейса Player по умолчанию. |
MediaController |
Взаимодействует с MediaSession для отправки команд воспроизведения. Если ваши элементы Player и MediaSession находятся в компоненте Service, отдельном от Activity или Fragment, где размещен интерфейс проигрывателя, вы можете назначить элемент MediaController проигрывателем для компонента интерфейса, например PlayerView или Player Composable. Вызовы методов воспроизведения и плейлистов отправляются на устройство "Player" через MediaSession.
|
MediaBrowser |
Помимо функций, предлагаемых MediaController, взаимодействует с MediaLibrarySession для просмотра доступного медиаконтента.
|
SimpleBasePlayer |
Реализация Player, которая сокращает количество методов, которые нужно реализовать, до минимума. Полезно, если вы используете собственный проигрыватель, который хотите подключить к MediaSession.
|
ForwardingSimpleBasePlayer |
Подкласс SimpleBasePlayer, предназначенный для пересылки операций воспроизведения в другой объект Player, но при этом позволяющий настраивать поведение так же, как и SimpleBasePlayer. Используйте этот класс, чтобы запретить или изменить определенные операции воспроизведения.
|
RemoteCastPlayer |
Реализация Player для управления воспроизведением в удаленном приложении-получателе Cast.
|
CastPlayer |
Реализация Player для управления воспроизведением контента Cast как на локальном, так и на удаленном устройстве.
|
Хотя MediaSession не реализует интерфейс Player, при его создании требуется Player. Его цель – предоставить доступ к Player
из других процессов или потоков.
Архитектура воспроизведения Media3
Если у вас есть доступ к Player, вы можете вызывать его методы напрямую, чтобы отправлять команды воспроизведения. Вы можете транслировать воспроизведение и предоставлять внешним источникам возможность управлять им, реализовав MediaSession. В этих внешних источниках реализован MediaController, который позволяет подключаться к сеансу мультимедиа и отправлять запросы на воспроизведение.
Если вы хотите, чтобы медиаконтент воспроизводился в фоновом режиме, вам нужно разместить сеанс и проигрыватель в MediaSessionService или MediaLibraryService, которые работают как активная служба. В этом случае вы сможете отделить проигрыватель от Activity в приложении, содержащего интерфейс для управления воспроизведением. В этом случае вам может понадобиться медиаконтроллер.
Player играет ключевую роль в архитектуре Media3.Состояние проигрывателя
Состояние медиаплеера, реализующего интерфейс Player, состоит в основном из четырех категорий информации:
- Статус воспроизведения
- Восстановите с помощью
getPlaybackState(). - В интерфейсе определены следующие значения состояния:
STATE_IDLE,STATE_BUFFERING,STATE_READYиSTATE_ENDED.
- Восстановите с помощью
- Плейлист мультимедийных объектов
- Последовательность из
MediaItemэкземпляров для воспроизведения. - Восстановление с помощью
getCurrentTimeline() - Объекты
Playerмогут предоставлять методы для работы с плейлистами, например добавления или удаленияMediaItem, а также удобные методы, такие какgetCurrentMediaItem().
- Последовательность из
- Свойства воспроизведения и паузы, например:
playWhenReady: Указывает, хочет ли пользователь, чтобы мультимедиа воспроизводилось, когда это возможно, или оставалось на паузе.- Причина блокировки воспроизведения – если применимо, причина блокировки воспроизведения, даже если
playWhenReadyимеет значениеtrue. isPlaying: Указывает, воспроизводится ли видео в данный момент. Значениеtrueбудет только в том случае, если состояние воспроизведения –STATE_READY, значениеplayWhenReady–trueи воспроизведение не подавлено.
- Позиция воспроизведения, в том числе:
- Индекс текущего медиаконтента:
Индекс текущего
MediaItemв плейлисте. isPlayingAd: Указывает, воспроизводится ли вставленное объявление.- Текущая позиция воспроизведения:
Текущая позиция воспроизведения в текущем
MediaItemили вставленном объявлении.
- Индекс текущего медиаконтента:
Индекс текущего
Кроме того, интерфейс Player позволяет получить доступ к доступным дорожкам, метаданным медиаконтента, скорости воспроизведения, громкости и другим вспомогательным свойствам воспроизведения.
Отслеживание изменений
Используйте Player.Listener, чтобы отслеживать изменения в Player. Подробнее о том, как создать и использовать прослушиватель, можно узнать в документации ExoPlayer о событиях проигрывателя.
Обратите внимание, что интерфейс прослушивателя не включает обратные вызовы для отслеживания обычного воспроизведения. Чтобы постоянно отслеживать ход воспроизведения, например для настройки интерфейса индикатора выполнения, необходимо запрашивать текущую позицию через определенные интервалы.
Kotlin
fun checkPlaybackPosition(delayMs: Long): Boolean = handler.postDelayed( { val currentPosition = player.currentPosition // Update UI based on currentPosition checkPlaybackPosition(delayMs) }, delayMs, )
Java
boolean checkPlaybackPosition(long delayMs) { return handler.postDelayed( () -> { long currentPosition = player.getCurrentPosition(); // Update UI based on currentPosition checkPlaybackPosition(delayMs); }, delayMs); }
Управление воспроизведением
Интерфейс Player позволяет управлять воспроизведением разными способами:
- Основные элементы управления воспроизведением, например
play(),pause(),prepare()иstop(). - Операции с плейлистами, например
addMediaItem()илиremoveMediaItem(). - Переход к другому элементу или позиции.
- Настроить режимы повтора и режим случайного воспроизведения.
- Изменить настройки выбора дорожек.
- Настройте скорость воспроизведения.
Реализации с собственным кодом Player
Чтобы создать собственный проигрыватель, можно расширить класс SimpleBasePlayer, входящий в состав Media3. Этот класс предоставляет базовую реализацию интерфейса Player, чтобы свести к минимуму количество методов, которые вам нужно реализовать.
Начните с переопределения метода getState(). Этот метод должен заполнять текущее состояние проигрывателя при вызове, включая:
- Набор доступных команд
- Свойства воспроизведения, например нужно ли начинать воспроизведение, когда статус воспроизведения
STATE_READY, индекс текущего медиаконтента и позиция воспроизведения в текущем контенте.
Kotlin
class CustomPlayer(looper: Looper) : SimpleBasePlayer(looper) { override fun getState(): State { return State.Builder() .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle // Configure additional playback properties .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build() } }
Java
private static final class CustomPlayer extends SimpleBasePlayer { public CustomPlayer(Looper looper) { super(looper); } @Override protected State getState() { return new State.Builder() .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle // Configure additional playback properties .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build(); } }
SimpleBasePlayer гарантирует, что State будет создан с допустимой комбинацией значений статуса. Он также будет обрабатывать слушателей и уведомлять их об изменениях состояния. Если вам нужно вручную запустить обновление состояния, вызовите функцию invalidateState().
Помимо метода getState(), вам нужно реализовать только те методы, которые используются для команд, объявленных доступными в вашем проигрывателе. Найдите метод обработчика, который можно переопределить и который соответствует нужной вам функции. Например, переопределите метод handleSeek(), чтобы поддерживать такие операции, как COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM и COMMAND_SEEK_TO_NEXT_MEDIA_ITEM.
Как изменить реализацию Player
Вместо того чтобы создавать полностью специальную директиву Player, вы можете использовать ForwardingSimpleBasePlayer, чтобы изменить статус и поведение существующей директивы Player. Подробнее о настройке канала рассказывается в руководстве.