Интерфейс проигрывателя

Проигрыватель – это компонент приложения, который обеспечивает воспроизведение мультимедийных объектов. Интерфейс Player в Media3 определяет функции, которые обычно выполняет проигрыватель. К ним относятся:

  • влиять на элементы управления воспроизведением, например на запуск, приостановку и перемотку;
  • Запрос свойств воспроизводимого контента, например позиции воспроизведения.
  • Управление плейлистом или очередью воспроизведения мультимедийных объектов.
  • Настройка свойств воспроизведения, таких как перемешивание, повтор, скорость и громкость
  • Рендеринг видео на экране

Media3 также предоставляет реализацию интерфейса Player, которая называется ExoPlayer.

Общий интерфейс между компонентами

Интерфейс Player реализуют несколько компонентов Media3, например:

Компонент Описание и особенности поведения
ExoPlayer API медиапроигрывателя и реализация интерфейса Player по умолчанию.
MediaController Взаимодействует с MediaSession для отправки команд воспроизведения. Если Player и MediaSession находятся в Service, отдельном от Activity или Fragment, где размещен интерфейс проигрывателя, вы можете назначить MediaController в качестве проигрывателя для компонента интерфейса, например PlayerView или composable-функции Player. Вызовы методов воспроизведения и плейлистов отправляются в 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, которые работают как активная служба. В этом случае вы можете отделить проигрыватель от действия в приложении, которое содержит интерфейс для управления воспроизведением. Для этого может потребоваться контроллер мультимедиа.

Диаграмма, показывающая, как компоненты воспроизведения Media3 вписываются в архитектуру мультимедийного приложения.
Рисунок 1. Интерфейс Player играет ключевую роль в архитектуре Media3.

Состояние проигрывателя

Состояние медиапроигрывателя, реализующего интерфейс Player, в основном состоит из четырех категорий информации:

  1. Статус воспроизведения
  2. Плейлист с мультимедийными объектами
    • Последовательность экземпляров MediaItem для воспроизведения.
    • Получить с помощью getCurrentTimeline()
    • Экземпляры Player могут предоставлять методы для работы с плейлистами, например добавление или удаление MediaItem, а также удобные методы, такие как getCurrentMediaItem().
  3. Свойства воспроизведения и паузы, например:
    • playWhenReady – указывает, хочет ли пользователь, чтобы медиаконтент воспроизводился, когда это возможно, или оставался на паузе.
    • Причина запрета на воспроизведение. Указывает, почему воспроизведение запрещено, даже если playWhenReady имеет значение true.
    • isPlaying – указывает, воспроизводится ли видео в проигрывателе. Значение true возможно, только если состояние воспроизведения – STATE_READY, playWhenReady – true и воспроизведение не подавлено.
  4. Место начала воспроизведения, в том числе:

Кроме того, интерфейс 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 позволяет управлять состоянием и воспроизведением:

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. Подробную информацию вы найдете в руководстве на странице настройки.