Antarmuka Pemutar

Pemutar adalah komponen aplikasi Anda yang memfasilitasi pemutaran item media. Antarmuka Media3 Player menyiapkan garis besar untuk fungsi yang umumnya ditangani oleh pemutar. Hal ini mencakup:

  • Memengaruhi kontrol pemutaran, seperti memutar, menjeda, dan mencari
  • Mengueri properti media yang sedang diputar, seperti posisi pemutaran
  • Mengelola playlist/antrean item media
  • Mengonfigurasi properti pemutaran, seperti pengacakan, pengulangan, kecepatan, dan volume
  • Merender video ke layar

Media3 juga menyediakan implementasi antarmuka Player, yang disebut ExoPlayer.

Antarmuka umum antar-komponen

Beberapa komponen di Media3 mengimplementasikan antarmuka Player, misalnya:

Komponen Deskripsi & catatan perilaku
ExoPlayer API pemutar media, dan implementasi default antarmuka Player.
MediaController Berinteraksi dengan MediaSession untuk mengirim perintah pemutaran. Jika Player dan MediaSession berada di Service yang terpisah dari Activity atau Fragment tempat UI pemain berada, Anda dapat menetapkan MediaController sebagai pemain untuk UI PlayerView. Panggilan metode pemutaran dan playlist dikirim ke Player melalui MediaSession.
MediaBrowser Selain fungsi yang ditawarkan oleh MediaController, berinteraksi dengan MediaLibrarySession untuk menjelajahi konten media yang tersedia.
SimpleBasePlayer Implementasi Player yang mengurangi jumlah metode yang harus diimplementasikan hingga minimum. Berguna saat menggunakan pemutar kustom yang ingin Anda hubungkan ke MediaSession.
ForwardingSimpleBasePlayer Subclass SimpleBasePlayer yang dirancang untuk meneruskan operasi pemutaran ke Player lain sambil memungkinkan penyesuaian perilaku yang konsisten yang sama seperti SimpleBasePlayer. Gunakan class ini untuk membatalkan atau mengubah operasi pemutaran tertentu.
CastPlayer Implementasi Player yang berkomunikasi dengan aplikasi penerima Cast. Perilaku bergantung pada sesi Cast yang mendasarinya.

Meskipun MediaSession tidak mengimplementasikan antarmuka Player, MediaSession memerlukan Player saat membuat MediaSession. Tujuannya adalah untuk memberikan akses ke Player dari proses atau thread lain.

Arsitektur pemutaran Media3

Jika memiliki akses ke Player, Anda harus memanggil metodenya secara langsung untuk mengeluarkan perintah pemutaran. Anda dapat mengiklankan pemutaran dan memberikan kontrol pemutaran ke sumber eksternal dengan menerapkan MediaSession. Sumber eksternal ini menerapkan MediaController, yang memfasilitasi koneksi ke sesi media dan mengeluarkan permintaan perintah pemutaran.

Saat memutar media di latar belakang, Anda perlu menempatkan sesi media dan pemutar dalam MediaSessionService atau MediaLibraryService yang berjalan sebagai layanan latar depan. Jika melakukannya, Anda dapat memisahkan pemutar dari Aktivitas di aplikasi yang berisi UI untuk kontrol pemutaran. Hal ini mungkin mengharuskan Anda menggunakan pengontrol media.

Diagram yang menunjukkan cara komponen pemutaran Media3 sesuai dengan arsitektur aplikasi media.
Gambar 1: Antarmuka Player memainkan peran penting dalam arsitektur Media3.

Status pemutar

Status pemutar media yang menerapkan antarmuka Player terutama terdiri dari 4 kategori informasi:

  1. Status pemutaran
  2. Playlist item media
  3. Properti putar/jeda, seperti:
    • playWhenReady: Indikasi apakah pengguna ingin media diputar jika memungkinkan atau tetap dijeda
    • Alasan penekanan pemutaran: Indikasi mengapa pemutaran ditekan, jika berlaku, meskipun playWhenReady adalah true
    • isPlaying: Indikasi apakah pemutar sedang memutar, yang hanya akan true jika status pemutaran adalah STATE_READY, playWhenReady adalah true, dan pemutaran tidak dibatalkan
  4. Posisi pemutaran, termasuk:

Selain itu, antarmuka Player memungkinkan akses ke track yang tersedia, metadata media, kecepatan pemutaran, volume, dan properti tambahan lainnya dari pemutaran.

Memantau perubahan

Gunakan Player.Listener untuk memproses perubahan dalam Player. Lihat dokumentasi ExoPlayer tentang Peristiwa pemutar untuk detail tentang cara membuat dan menggunakan pemroses.

Perhatikan bahwa antarmuka pemroses tidak menyertakan callback apa pun untuk melacak progres pemutaran normal. Untuk memantau progres pemutaran secara berkelanjutan, seperti untuk menyiapkan UI status progres, Anda harus mengkueri posisi saat ini pada interval yang tepat.

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);
}

Mengontrol pemutaran

Antarmuka Player menawarkan banyak cara untuk memanipulasi status dan mengontrol pemutaran:

Implementasi Player kustom

Untuk membuat pemutar kustom, Anda dapat memperluas SimpleBasePlayer yang disertakan dalam Media3. Class ini menyediakan penerapan dasar antarmuka Player untuk mengurangi jumlah metode yang perlu Anda terapkan hingga minimum.

Mulai dengan mengganti metode getState(). Metode ini harus mengisi status pemutar saat ini saat dipanggil, termasuk:

  • Kumpulan perintah yang tersedia
  • Properti pemutaran, seperti apakah pemutar harus mulai memutar saat status pemutaran adalah STATE_READY, indeks item media yang sedang diputar, dan posisi pemutaran dalam item saat ini

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 akan memastikan bahwa State dibuat dengan kombinasi nilai status yang valid. ViewModel ini juga akan menangani pemroses dan memberi tahu pemroses tentang perubahan status. Jika Anda perlu memicu update status secara manual, panggil invalidateState().

Selain metode getState(), Anda hanya perlu menerapkan metode yang digunakan untuk perintah yang dinyatakan tersedia oleh pemain Anda. Temukan metode handler yang dapat diganti yang sesuai dengan fungsi yang ingin Anda terapkan. Misalnya, ganti metode handleSeek() untuk mendukung operasi seperti COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM dan COMMAND_SEEK_TO_NEXT_MEDIA_ITEM.

Mengubah penerapan Player

Daripada membuat Player yang sepenuhnya kustom, Anda dapat menggunakan ForwardingSimpleBasePlayer untuk mengubah status dan perilaku Player yang ada. Lihat panduan di halaman Penyesuaian untuk mengetahui detail selengkapnya.