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

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

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