Tạo và định cấu hình DefaultPreloadManager

Trang này mô tả cách tạo DefaultPreloadManager để tải trước nội dung nghe nhìn cho ứng dụng dựa trên chiến lược bạn chọn.

Trình quản lý tải trước dựa trên lớp trừu tượng BasePreloadManager cho phép bạn xếp hạng nội dung theo tiêu chí bạn chọn. Tài liệu này giải thích cách sử dụng lớp dẫn xuất DefaultPreloadManager, trong đó mỗi mục nội dung nghe nhìn được xếp hạng bằng một số nguyên đại diện cho vị trí của mục đó trong danh sách (ví dụ: vị trí của mục đó trong băng chuyền video). Trình quản lý tải trước ưu tiên tải các mục dựa trên mức độ gần của mục đó với mục mà người dùng đang phát. Bằng cách đó, nếu người dùng chuyển sang một mục khác, thì mục mới có thể bắt đầu phát ngay lập tức.

Có 3 bước để tạo một thực thể của DefaultPreloadManager:

  • Xác định TargetPreloadStatusControl mà trình quản lý tải trước có thể truy vấn để tìm hiểu xem mục nội dung nghe nhìn đã sẵn sàng để tải hay chưa và lượng dữ liệu cần tải.
  • Tạo trình tạo mà bạn sẽ dùng để tạo trình quản lý tải trước và tạo các đối tượng ExoPlayer của ứng dụng.
  • Sử dụng trình tạo để tạo trình quản lý tải trước bằng cách gọi phương thức build() của trình tạo.

Tạo chế độ kiểm soát trạng thái tải trước mục tiêu

Khi tạo DefaultPreloadManager.Builder, bạn sẽ truyền cho đối tượng này một đối tượng kiểm soát trạng thái tải trước mục tiêu mà bạn xác định. Đối tượng này triển khai giao diện TargetPreloadStatusControl. Khi trình quản lý tải trước chuẩn bị sẵn sàng để tải trước nội dung nghe nhìn, trình quản lý này sẽ gọi phương thức getTargetPreloadStatus() của chế độ kiểm soát trạng thái để xác định xem có nên chuẩn bị, tải hay lưu nội dung vào bộ nhớ đệm cho một mục nội dung nghe nhìn hay không. Quá trình tải sẽ tải trước dữ liệu đa phương tiện trực tiếp vào vùng đệm trong bộ nhớ của trình phát, giúp dữ liệu sẵn sàng phát ngay lập tức, trong khi quá trình lưu vào bộ nhớ đệm sẽ lưu dữ liệu đa phương tiện vào bộ nhớ đệm của ổ đĩa lưu trữ dài lâu để tiết kiệm bộ nhớ của trình phát. Trình điều khiển trạng thái có thể trả lời bằng một trong các mã trạng thái sau:

  • STAGE_SPECIFIED_RANGE_LOADED: Trình quản lý tải trước phải tải nội dung từ vị trí bắt đầu đã chỉ định và trong khoảng thời gian đã chỉ định (tính bằng mili giây) vào vùng đệm trong bộ nhớ của trình phát.
  • STAGE_SPECIFIED_RANGE_CACHED: Trình quản lý tải trước phải lưu nội dung vào bộ nhớ đệm từ vị trí bắt đầu đã chỉ định và trong khoảng thời gian đã chỉ định (tính bằng mili giây) vào bộ nhớ đệm của ổ đĩa.
  • STAGE_TRACKS_SELECTED: Trình quản lý tải trước phải tải và xử lý thông tin của bản nhạc nội dung, đồng thời chọn các bản nhạc. Trình quản lý tải trước chưa nên bắt đầu tải nội dung.
  • STAGE_SOURCE_PREPARED: Trình quản lý tải trước phải chuẩn bị nguồn nội dung. Ví dụ: nếu siêu dữ liệu của nội dung nằm trong một tệp kê khai riêng, thì trình quản lý tải trước có thể tìm nạp và phân tích cú pháp tệp kê khai đó.
  • null: Trình quản lý tải trước không được tải bất kỳ nội dung hoặc siêu dữ liệu nào cho mục nội dung nghe nhìn đó.

Bạn cần có chiến lược để quyết định lượng nội dung cần tải cho mỗi mục nội dung nghe nhìn. Trong ví dụ này, nhiều nội dung hơn được tải cho các mục gần nhất với mục đang phát. Nếu người dùng đang phát nội dung có chỉ mục n, thì bộ điều khiển sẽ trả về các mã sau:

  • Chỉ mục n+1 (mục nội dung nghe nhìn tiếp theo): Tải 3.000 mili giây (3 giây) từ vị trí bắt đầu mặc định
  • Chỉ mục n-1 (mục nội dung nghe nhìn trước đó): Tải 1.000 mili giây (1 giây) từ vị trí bắt đầu mặc định
  • Các mục nội dung nghe nhìn khác trong phạm vi từ n-2 đến n+2: Trả về PreloadStatus.TRACKS_SELECTED
  • Các mục nội dung nghe nhìn khác trong phạm vi từ n-4 đến n+4: Trả về PreloadStatus.SOURCE_PREPARED
  • Đối với tất cả các mục nội dung nghe nhìn khác, hãy trả về 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
  }
}

Các điểm chính về mã

  • Bạn sẽ truyền một thực thể của MyTargetPreloadStatusControl đến trình tạo trình quản lý tải trước khi tạo trình quản lý đó.
  • currentPlayingIndex giữ chỉ mục của bất kỳ mục nội dung nghe nhìn nào đang phát. Ứng dụng có nhiệm vụ cập nhật giá trị đó.
  • Khi trình quản lý tải trước sẵn sàng tải nội dung, trình quản lý này sẽ gọi getTargetPreloadStatus và truyền thông tin xếp hạng mà bạn đã chỉ định cho mục nội dung nghe nhìn tương ứng đó. Trong trường hợp của DefaultPreloadManager, thông tin xếp hạng đó là một số nguyên, chỉ định vị trí của mục trong băng chuyền. Phương thức này chọn mã cần trả về bằng cách so sánh chỉ mục đó với chỉ mục của mục hiện được chọn.

Tạo trình quản lý tải trước

Để tạo trình quản lý tải trước, bạn cần có DefaultPreloadManager.Builder. Trình tạo đó được định cấu hình bằng bối cảnh hiện tại và chế độ kiểm soát trạng thái tải trước mục tiêu của ứng dụng. Bạn có thể tạo trình quản lý tải trước bằng tất cả cấu hình mặc định.

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

Trình tạo cũng cung cấp các phương thức setter mà bạn có thể dùng để đặt các thành phần tuỳ chỉnh của trình quản lý tải trước.

Ví dụ: bạn có thể tuỳ chỉnh tổng số byte vùng đệm mục tiêu cho tất cả các nguồn nội dung nghe nhìn tải trước trong DefaultPreloadManager để dữ liệu tải trước không vượt quá giới hạn đó. Bạn có thể định cấu hình giới hạn đó bằng cách sử dụng setPlayerTargetBufferBytes(String, int) trên một DefaultLoadControl.Builder tuỳ chỉnh có tên trình phát "preload" và chuyển thực thể đó đến trình tạo trình quản lý tải trước:

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()

Mặc dù các phương thức setter của trình tạo về cơ bản là không bắt buộc để tuỳ chỉnh, nhưng nếu muốn lưu vào bộ nhớ đệm bất kỳ mục nội dung nghe nhìn nào vào ổ đĩa, bạn phải định cấu hình trình tạo bằng Cache bằng cách gọi setCache(). Nếu không có bộ nhớ đệm nào được định cấu hình, thì việc cố gắng lưu các mục nội dung nghe nhìn vào bộ nhớ đệm sẽ dẫn đến IllegalStateException.

Tạo ExoPlayer để phát mục nội dung nghe nhìn được tải trước

Ngoài việc sử dụng trình tạo để tạo trình quản lý tải trước, bạn cũng sẽ sử dụng trình tạo này để tạo các đối tượng ExoPlayer mà ứng dụng của bạn dùng để phát nội dung, nhờ đó ExoPlayer chia sẻ chính xác các thành phần với trình quản lý tải trước. Bạn vẫn có thể đặt cấu hình cụ thể cho chế độ phát của ExoPlayer bằng cách truyền một thực thể ExoPlayer.Builder có các cấu hình đó.

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

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