Как создать и настроить DefaultPreloadManager

На этой странице рассказывается, как создать DefaultPreloadManager, который предварительно загружает медиаконтент для вашего приложения в соответствии с выбранной вами стратегией.

Менеджеры предварительной загрузки на основе абстрактного класса BasePreloadManager позволяют ранжировать контент по выбранным вами критериям. В этом документе рассказывается, как использовать производный класс DefaultPreloadManager, в котором каждому медиаобъекту присваивается целое число, обозначающее его позицию в списке (например, в карусели видео). Менеджер предварительной загрузки определяет приоритет загрузки объектов в зависимости от того, насколько они близки к объекту, который сейчас воспроизводит пользователь. В этом случае, если пользователь перейдет к другому объекту, воспроизведение начнется сразу.

Чтобы создать экземпляр DefaultPreloadManager, выполните три шага:

  • Определите TargetPreloadStatusControl, по которому менеджер предзагрузки сможет узнать, готов ли медиаконтент к загрузке и сколько его нужно загрузить.
  • Создайте конструктор, который будет использоваться для создания менеджера предзагрузки и объектов ExoPlayer вашего приложения.
  • Чтобы создать менеджер предзагрузки, вызовите метод build() конструктора.

Как создать элемент управления целевым статусом предзагрузки

При создании объекта DefaultPreloadManager.Builder вы передадите ему объект target preload status control, который определите сами. Этот объект реализует интерфейс TargetPreloadStatusControl. Когда менеджер предзагрузки готовится к предзагрузке медиаконтента, он вызывает метод getTargetPreloadStatus() контроллера статуса, чтобы определить, нужно ли подготовить, загрузить или кешировать контент для медиаобъекта. При предзагрузке медиаданные загружаются непосредственно в буфер памяти проигрывателя, чтобы их можно было воспроизвести мгновенно. При кешировании медиаданные сохраняются в постоянном кеше диска, чтобы сэкономить память проигрывателя. Контроллер статуса может ответить одним из следующих кодов статуса:

  • STAGE_SPECIFIED_RANGE_LOADED: менеджер предварительной загрузки должен загрузить контент из указанной начальной позиции в буфер памяти проигрывателя на указанную продолжительность (в миллисекундах).
  • STAGE_SPECIFIED_RANGE_CACHED: Менеджер предзагрузки должен кешировать контент с указанной начальной позиции в течение заданного времени (в миллисекундах) в кеш диска.
  • STAGE_TRACKS_SELECTED: менеджер предварительной загрузки должен загрузить и обработать информацию о дорожке контента и выбрать дорожки. Менеджер предзагрузки не должен начинать загрузку контента.
  • STAGE_SOURCE_PREPARED: менеджер предзагрузки должен подготовить источник контента. Например, если метаданные контента находятся в отдельном файле манифеста, менеджер предзагрузки может получить и обработать этот манифест.
  • null: менеджер предзагрузки не должен загружать контент или метаданные для этого медиаобъекта.

Вам нужно будет разработать стратегию загрузки контента для каждого медиаобъекта. В этом примере больше контента загружается для объектов, которые находятся ближе всего к воспроизводимому объекту. Если пользователь воспроизводит контент с индексом n, контроллер возвращает следующие коды:

  • Индекс n+1 (следующий медиаобъект): загрузка 3000 мс (3 секунды) с позиции начала по умолчанию.
  • Индекс n-1 (предыдущий медиаконтент): загрузка 1000 мс (1 секунда) от позиции начала по умолчанию.
  • Другие медиаобъекты в диапазоне от n-2 до n+2: Return PreloadStatus.TRACKS_SELECTED
  • Другие медиаобъекты в диапазоне от n-4 до n+4: клавиша "Ввод". PreloadStatus.SOURCE_PREPARED
  • Для всех остальных медиаобъектов возвращайте значение null.

class MyTargetPreloadStatusControl(var currentPlayingIndex: Int = 0) :
  TargetPreloadStatusControl<Int, DefaultPreloadManager.PreloadStatus> {

  override fun getTargetPreloadStatus(index: Int): DefaultPreloadManager.PreloadStatus {
    if (index - currentPlayingIndex == 1) { // next track
      // return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and
      // suggest loading 3000ms from the default start position
      return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L)
    } else if (index - currentPlayingIndex == -1) { // previous track
      // return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and
      // suggest loading 3000ms from the default start position
      return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L)
    } else if (abs(index - currentPlayingIndex) == 2) {
      // return a PreloadStatus that is labelled by STAGE_TRACKS_SELECTED
      return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_TRACKS_SELECTED
    } else if (abs(index - currentPlayingIndex) <= 4) {
      // return a PreloadStatus that is labelled by STAGE_SOURCE_PREPARED
      return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_SOURCE_PREPARED
    }
    return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_NOT_PRELOADED
  }
}

Ключевые моменты

  • При создании сборщика менеджера предзагрузки вы передадите ему экземпляр MyTargetPreloadStatusControl.
  • currentPlayingIndex содержит индекс текущего медиафайла. Приложение должно поддерживать актуальность этого значения.
  • Когда менеджер предварительной загрузки готов загрузить контент, он вызывает getTargetPreloadStatus и передает информацию о ранжировании, которую вы указали для соответствующего медиаобъекта. В случае с DefaultPreloadManager эта информация представляет собой целое число, указывающее позицию объекта в карусели. Метод определяет, какой код нужно вернуть, сравнивая индекс с индексом выбранного в данный момент элемента.

Как создать менеджер предзагрузки

Чтобы создать менеджер предзагрузки, вам понадобится DefaultPreloadManager.Builder. Этот конструктор настроен с учетом текущего контекста и целевого статуса предварительной загрузки приложения. Вы можете создать менеджер предзагрузки со всеми конфигурациями по умолчанию.

val targetPreloadStatusControl = MyTargetPreloadStatusControl()
val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
val preloadManager = preloadManagerBuilder.build()

Также в конструкторе есть методы установки, которые можно использовать для настройки специальных компонентов менеджера предзагрузки.

Например, вы можете задать целевой общий размер буфера в байтах для всех источников медиаконтента, предварительно загружаемого в DefaultPreloadManager, чтобы объем предварительно загруженных данных не превышал заданный лимит. Вы можете задать этот лимит с помощью setPlayerTargetBufferBytes(String, int) на специальном объекте DefaultLoadControl.Builder с названием проигрывателя "preload" и передать этот объект в конструктор менеджера предзагрузки:

val targetPreloadStatusControl = MyTargetPreloadStatusControl()
val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl)

preloadManagerBuilder.setLoadControl(
  DefaultLoadControl.Builder()
    .setPlayerTargetBufferBytes("preload", 128 * 1024 * 1024) // 128 MiB
    .build()
)
val preloadManager = preloadManagerBuilder.build()

Методы установки в конструкторе в основном используются для настройки, но если вы хотите кешировать медиаконтент на диск, вам нужно настроить конструктор с помощью Cache, вызвав setCache(). Если кеш не настроен, попытка кешировать медиаконтент приведет к ошибке IllegalStateException.

Создайте ExoPlayer, чтобы воспроизвести предзагруженный медиаконтент.

Компоновщик используется не только для создания менеджера предзагрузки, но и для создания объектов ExoPlayer, которые приложение использует для воспроизведения контента. Благодаря этому ExoPlayer корректно передает компоненты менеджеру предзагрузки. Вы можете задать настройки воспроизведения для ExoPlayer, передав экземпляр ExoPlayer.Builder с этими настройками.

// Direct creation
val exoPlayer = preloadManagerBuilder.buildExoPlayer()

// Creation with custom playback specific configurations
val skipSilenceExoPlayerBuilder = ExoPlayer.Builder(context).setSkipSilenceEnabled(true)
val skipSilenceExoPlayer = preloadManagerBuilder.buildExoPlayer(skipSilenceExoPlayerBuilder)