Giao diện trình phát

Trình phát là thành phần của ứng dụng giúp phát các mục nội dung nghe nhìn. Giao diện Player của Media3 thiết lập một bản phác thảo cho chức năng thường do người chơi xử lý. Trong đó có:

  • Ảnh hưởng đến các chế độ điều khiển phát, chẳng hạn như phát, tạm dừng và tua
  • Truy vấn các thuộc tính của nội dung đa phương tiện đang phát, chẳng hạn như vị trí phát
  • Quản lý danh sách phát/hàng đợi các mục nội dung nghe nhìn
  • Định cấu hình các thuộc tính phát, chẳng hạn như phát ngẫu nhiên, lặp lại, tốc độ và âm lượng
  • Kết xuất video lên màn hình

Media3 cũng cung cấp cách triển khai giao diện Player, có tên là ExoPlayer.

Giao diện chung giữa các thành phần

Một số thành phần trong Media3 triển khai giao diện Player, ví dụ:

Thành phần Nội dung mô tả và ghi chú về hành vi
ExoPlayer API trình phát nội dung nghe nhìn và cách triển khai mặc định của giao diện Player.
MediaController Tương tác với MediaSession để gửi lệnh phát. Nếu PlayerMediaSession nằm trong Service tách biệt với Activity hoặc Fragment nơi giao diện người dùng của người chơi nằm, thì bạn có thể chỉ định MediaController làm trình phát cho giao diện người dùng PlayerView. Các lệnh gọi phương thức phát và danh sách phát sẽ được gửi đến Player thông qua MediaSession.
MediaBrowser Ngoài chức năng do MediaController cung cấp, hãy tương tác với MediaLibrarySession để duyệt xem nội dung nghe nhìn có sẵn.
SimpleBasePlayer Phương thức triển khai Player giúp giảm số lượng phương thức cần triển khai xuống mức tối thiểu. Hữu ích khi sử dụng trình phát tuỳ chỉnh mà bạn muốn kết nối với MediaSession.
ForwardingSimpleBasePlayer Một lớp con SimpleBasePlayer được thiết kế để chuyển tiếp các thao tác phát sang một Player khác, đồng thời cho phép các tuỳ chỉnh hành vi nhất quán giống như SimpleBasePlayer. Sử dụng lớp này để ngăn chặn hoặc sửa đổi các thao tác phát cụ thể.
CastPlayer Cách triển khai Player giao tiếp với ứng dụng nhận Cast. Hành vi phụ thuộc vào phiên Cast cơ bản.

Mặc dù MediaSession không triển khai giao diện Player, nhưng bạn cần có Player khi tạo giao diện. Mục đích của lớp này là cung cấp quyền truy cập vào Player từ các quy trình hoặc luồng khác.

Cấu trúc phát Media3

Nếu có quyền truy cập vào Player, bạn nên gọi trực tiếp các phương thức của Player để đưa ra lệnh phát. Bạn có thể quảng cáo tính năng phát và cấp quyền kiểm soát tính năng phát cho các nguồn bên ngoài bằng cách triển khai MediaSession. Các nguồn bên ngoài này triển khai một MediaController, giúp kết nối với một phiên phát nội dung đa phương tiện và đưa ra các yêu cầu về lệnh phát.

Khi phát nội dung nghe nhìn ở chế độ nền, bạn cần lưu trữ phiên phát nội dung nghe nhìn và trình phát trong MediaSessionService hoặc MediaLibraryService chạy dưới dạng dịch vụ trên nền trước. Nếu làm như vậy, bạn có thể tách trình phát khỏi Hoạt động trong ứng dụng chứa giao diện người dùng để điều khiển chế độ phát. Điều này có thể yêu cầu bạn sử dụng trình điều khiển nội dung nghe nhìn.

Sơ đồ cho thấy cách các thành phần phát Media3 phù hợp với cấu trúc ứng dụng đa phương tiện.
Hình 1: Giao diện Player đóng vai trò quan trọng trong cấu trúc của Media3.

Trạng thái của người chơi

Trạng thái của trình phát nội dung nghe nhìn triển khai giao diện Player chủ yếu bao gồm 4 danh mục thông tin:

  1. Trạng thái phát
  2. Danh sách phát các mục nội dung nghe nhìn
    • Một chuỗi các thực thể MediaItem để phát.
    • Truy xuất bằng getCurrentTimeline()
    • Các thực thể Player có thể cung cấp các phương thức thao tác với danh sách phát như thêm hoặc xoá MediaItem và các phương thức tiện lợi như getCurrentMediaItem().
  3. Thuộc tính phát/tạm dừng, chẳng hạn như:
    • playWhenReady: Cho biết người dùng có muốn phát nội dung nghe nhìn khi có thể hay tiếp tục tạm dừng
    • Lý do chặn phát: Cho biết lý do chặn phát, nếu có, ngay cả khi playWhenReadytrue
    • isPlaying: Cho biết liệu trình phát có đang phát hay không. Giá trị này sẽ chỉ là true nếu trạng thái phát là STATE_READY, playWhenReadytrue và chế độ phát không bị chặn
  4. Vị trí phát, bao gồm:

Ngoài ra, giao diện Player cho phép truy cập vào các bản nhạc có sẵn, siêu dữ liệu nội dung nghe nhìn, tốc độ phát, âm lượng và các thuộc tính phụ khác của bản phát.

Theo dõi các thay đổi

Sử dụng Player.Listener để theo dõi các thay đổi trong Player. Hãy xem tài liệu về ExoPlayer về Sự kiện của trình phát để biết thông tin chi tiết về cách tạo và sử dụng trình nghe.

Xin lưu ý rằng giao diện trình nghe không bao gồm bất kỳ lệnh gọi lại nào để theo dõi tiến trình phát thông thường. Để liên tục theo dõi tiến trình phát, chẳng hạn như thiết lập giao diện người dùng thanh tiến trình, bạn nên truy vấn vị trí hiện tại theo các khoảng thời gian thích hợp.

Kotlin

val handler = Handler(Looper.getMainLooper())
fun checkPlaybackPosition(delayMs: Long): Boolean =
  handler.postDelayed(
    {
      val currentPosition = player.currentPosition
      // Update UI based on currentPosition
      checkPlaybackPosition(delayMs)
    },
    delayMs)

Java

Handler handler = new Handler(Looper.getMainLooper());
boolean checkPlaybackPosition(long delayMs) {
    return handler.postDelayed(() -> {
        long currentPosition = player.getCurrentPosition();
        // Update UI based on currentPosition
        checkPlaybackPosition(delayMs);
    }, delayMs);
}

Điều khiển tính năng phát

Giao diện Player cung cấp nhiều cách để thao tác với trạng thái và kiểm soát chế độ phát:

Triển khai Player tuỳ chỉnh

Để tạo trình phát tuỳ chỉnh, bạn có thể mở rộng SimpleBasePlayer có trong Media3. Lớp này cung cấp phương thức triển khai cơ sở của giao diện Player để giảm thiểu số lượng phương thức bạn cần triển khai.

Bắt đầu bằng cách ghi đè phương thức getState(). Phương thức này sẽ điền trạng thái người chơi hiện tại khi được gọi, bao gồm:

  • Tập hợp các lệnh có sẵn
  • Thuộc tính phát, chẳng hạn như liệu trình phát có nên bắt đầu phát khi trạng thái phát là STATE_READY, chỉ mục của mục nội dung đa phương tiện đang phát và vị trí phát trong mục hiện tại hay không

Kotlin

class CustomPlayer : SimpleBasePlayer(looper) {
  override fun getState(): State {
    return State.Builder()
      .setAvailableCommands(...) // 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

public class CustomPlayer extends SimpleBasePlayer {
  public CustomPlayer(Looper looper) {
    super(looper);
  }

  @Override
  protected State getState() {
    return new State.Builder()
      .setAvailableCommands(...) // 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 sẽ thực thi việc tạo State bằng tổ hợp giá trị trạng thái hợp lệ. Lớp này cũng sẽ xử lý trình nghe và thông báo cho trình nghe về các thay đổi về trạng thái. Nếu bạn cần kích hoạt quá trình cập nhật trạng thái theo cách thủ công, hãy gọi invalidateState().

Ngoài phương thức getState(), bạn chỉ cần triển khai các phương thức được dùng cho các lệnh mà người chơi khai báo là có sẵn. Tìm phương thức trình xử lý có thể ghi đè tương ứng với chức năng bạn muốn triển khai. Ví dụ: ghi đè phương thức handleSeek() để hỗ trợ các thao tác như COMMAND_SEEK_IN_CURRENT_MEDIA_ITEMCOMMAND_SEEK_TO_NEXT_MEDIA_ITEM.