1. Sebelum memulai
Screenshot: Aplikasi Android YouTube
ExoPlayer adalah pemutar media tingkat aplikasi yang dibuild di atas API media tingkat rendah di Android. ExoPlayer memiliki sejumlah keunggulan dibandingkan MediaPlayer bawaan di Android. Pemutar ini mendukung banyak format media yang sama seperti MediaPlayer, ditambah format adaptif, seperti DASH dan SmoothStreaming. ExoPlayer sangat mudah disesuaikan dan diperluas, sehingga mampu berfungsi dalam banyak kasus penggunaan tingkat lanjut. Pemutar ini adalah project open source yang digunakan oleh aplikasi Google, termasuk YouTube dan Google Play Movies & TV.
Prasyarat
- Pengetahuan pengembangan Android dan Android Studio tingkat menengah
Yang akan Anda lakukan
- Membuat instance
SimpleExoPlayer
, yang menyiapkan dan memutar media dari berbagai sumber. - Mengintegrasikan ExoPlayer dengan siklus proses aktivitas aplikasi untuk mendukung layanan latar belakang, latar depan, dan pemutaran kembali dalam lingkungan tunggal atau multi-jendela.
- Menggunakan
MediaItem
untuk membuat playlist. - Memutar streaming video adaptif, yang menyesuaikan kualitas media dengan bandwidth yang tersedia.
- Mendaftarkan pemroses peristiwa untuk memantau status pemutaran dan menunjukkan cara pemroses dapat digunakan untuk mengukur kualitas pemutaran.
- Menggunakan komponen UI ExoPlayer standar, kemudian menyesuaikannya dengan gaya aplikasi Anda.
Yang akan Anda butuhkan
- Versi stabil terbaru Android Studio.
- Perangkat Android dengan JellyBean (4.1) atau yang lebih tinggi, idealnya dengan Nougat (7.1) atau yang lebih tinggi karena mendukung multi-jendela.
2. Memulai persiapan
Mendapatkan kode
Untuk memulai, download project Android Studio:
Atau, Anda dapat membuat clone repositori GitHub:
git clone https://github.com/googlecodelabs/exoplayer-intro.git
Struktur direktori
Membuat clone atau unzip memberi Anda folder root (exoplayer-intro
), yang berisi project gradle tunggal dengan beberapa modul; satu modul aplikasi dan satu modul untuk setiap langkah codelab ini, bersama dengan semua materi yang Anda butuhkan.
Mengimpor project
- Mulai Android Studio.
- Pilih File > New > Import Project*.*
- Pilih file
build.gradle
root.
Screenshot: Struktur project saat mengimpor
Setelah build selesai, Anda akan melihat enam modul: modul app
(tipe application) dan lima modul dengan nama exoplayer-codelab-N
(dengan N
adalah 00
hingga 04,
, masing-masing tipe library). Modul app
sebenarnya kosong, hanya memiliki satu manifes. Semua materi dari modul yang ditentukan saat ini exoplayer-codelab-N
digabungkan ketika aplikasi di-build menggunakan dependensi gradle di app/build.gradle
.
app/build.gradle
dependencies {
implementation project(":exoplayer-codelab-00")
}
Aktivitas pemutar media Anda disimpan di modul exoplayer-codelab-N
. Alasan untuk menyimpannya dalam modul library terpisah adalah agar Anda dapat membagikannya di antara APK dengan target platform yang berbeda, seperti seluler dan Android TV. Ini juga memungkinkan Anda untuk memanfaatkan fitur-fitur, seperti Pengiriman Dinamis, yang memungkinkan fitur pemutaran media Anda diinstal hanya ketika pengguna membutuhkannya.
- Deploy dan jalankan aplikasi untuk memeriksa semuanya berjalan lancar. Aplikasi harus mengisi layar dengan latar belakang hitam.
Screenshot: Aplikasi kosong berjalan
3. Streaming!
Menambahkan dependensi ExoPlayer
ExoPlayer adalah project open source yang dihosting di GitHub. Setiap rilis didistribusikan melalui Google Maven, yang merupakan salah satu repositori paket default yang digunakan oleh Android Studio dan Gradle. Setiap rilis diidentifikasi secara unik oleh string dengan format berikut:
com.google.android.exoplayer:exoplayer:X.X.X
Anda dapat menambahkan ExoPlayer ke project Anda hanya dengan mengimpor class dan komponen UI-nya. Ukurannya cukup kecil, memiliki footprint yang diperkecil sekitar 70 sampai 300 kB, tergantung pada fitur yang disertakan dan format yang didukung. Library ExoPlayer dibagi menjadi modul-modul untuk memungkinkan developer mengimpor fungsionalitas yang mereka butuhkan saja. Untuk informasi lebih lanjut tentang struktur modular ExoPlayer, lihat Menambahkan modul ExoPlayer.
- Buka file
build.gradle
dari modulplayer-lib
. - Tambahkan baris berikut ke bagian
dependencies
dan sinkronkan project.
exoplayer-codelab-00/build.gradle
dependencies {
[...]
implementation 'com.google.android.exoplayer:exoplayer-core:2.12.0'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.12.0'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.12.0'
}
Tambahkan PlayerView element
- Buka file resource tata letak
activity_player.xml
dari modulexoplayer-codelab-00
. - Tempatkan kursor di dalam elemen
FrameLayout
. - Mulailah mengetik
<PlayerView
dan biarkan Android Studio melengkapi otomatis elemenPlayerView
. - Gunakan
match_parent
untukwidth
danheight
. - Deklarasikan ID sebagai
video_view
.
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Untuk ke depannya, Anda merujuk ke elemen UI ini sebagai tampilan video.
- Di
PlayerActivity
, Anda kini dapat memperoleh referensi ke hierarki tampilan yang dibuat dari file XML yang baru saja Anda edit.
PlayerActivity.kt
private val viewBinding by lazy(LazyThreadSafetyMode.NONE) {
ActivityPlayerBinding.inflate(layoutInflater)
}
- Setel root pohon tampilan Anda sebagai tampilan konten Aktivitas Anda. Periksa juga apakah properti
videoView
terlihat di referensiviewBinding
Anda, dan tipenya adalahPlayerView
.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(viewBinding.root)
}
Membuat ExoPlayer
Untuk memutar media streaming, Anda memerlukan objek ExoPlayer
. Cara paling sederhana untuk membuatnya adalah dengan menggunakan class SimpleExoPlayer.Builder
. Seperti namanya, class ini menggunakan pola builder untuk mem-build instance SimpleExoPlayer
.
SimpleExoPlayer
adalah implementasi yang nyaman dan serba guna dari antarmuka ExoPlayer
.
Tambahkan metode pribadi initializePlayer
untuk membuat SimpleExoPlayer
Anda.
PlayerActivity.kt
private var player: SimpleExoPlayer? = null
[...]
private fun initializePlayer() {
player = SimpleExoPlayer.Builder(this)
.build()
.also { exoPlayer ->
viewBinding.videoView.player = exoPlayer
}
}
Buat SimpleExoPlayer.Builder
menggunakan konteks Anda, lalu panggil build
untuk membuat objek SimpleExoPlayer
Anda. Kemudian, tugaskan ke player
, yang perlu Anda deklarasikan sebagai kolom anggota. Anda kemudian menggunakan properti yang dapat diubah viewBinding.videoView.player
untuk melakukan binding player
ke tampilan yang sesuai.
Membuat item media
Sekarang player
Anda membutuhkan konten untuk diputar. Untuk itu, Anda perlu membuat MediaItem
. Ada berbagai jenis MediaItem
, tetapi mulailah dengan membuat satu untuk file MP3 di internet.
Cara paling sederhana untuk membuat MediaItem
adalah dengan menggunakan MediaItem.fromUri
, yang menerima URI file media. Tambahkan MediaItem
ke player
menggunakan player.setMediaItem
.
- Tambahkan kode berikut ke
initializePlayer
di dalam blockalso
:
PlayerActivity.kt
private fun initializePlayer() {
[...]
.also { exoPlayer ->
[...]
val mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3))
exoPlayer.setMediaItem(mediaItem)
}
}
Perlu diperhatikan bahwa R.string.media_url_mp3
ditentukan sebagai https://storage.googleapis.com/exoplayer-test-media-0/play.mp3 di strings.xml
.
Berbagi siklus proses Aktivitas dengan baik
player
kita dapat menghabiskan banyak resource termasuk memori, CPU, koneksi jaringan, dan codec hardware. Ketersediaan sebagian besar resource ini tidak banyak, terutama untuk codec hardware yang mungkin hanya ada satu. Anda harus melepaskan resource tersebut untuk digunakan aplikasi lain saat tidak menggunakannya, seperti saat aplikasi Anda ditempatkan di latar belakang.
Dengan kata lain, siklus proses pemutar Anda harus terikat dengan siklus proses aplikasi Anda. Untuk menerapkan ini, Anda perlu mengganti empat metode PlayerActivity
: onStart
, onResume
, onPause
, dan onStop
.
- Dengan
PlayerActivity
yang terbuka, klik Code menu > Override methods.... - Pilih
onStart
,onResume
,onPause
, danonStop
. - Lakukan inisialisasi pemutar di callback
onStart
atauonResume
, tergantung pada level API.
PlayerActivity.kt
public override fun onStart() {
super.onStart()
if (Util.SDK_INT >= 24) {
initializePlayer()
}
}
public override fun onResume() {
super.onResume()
hideSystemUi()
if ((Util.SDK_INT < 24 || player == null)) {
initializePlayer()
}
}
API Android level 24 dan yang lebih tinggi mendukung multi-jendela. Karena aplikasi Anda dapat terlihat, tetapi tidak aktif dalam mode jendela terpisah, Anda perlu melakukan inisialisasi pada pemutar di onStart
. API Android level 24 dan yang lebih rendah mengharuskan Anda menunggu selama mungkin sampai Anda mengambil resource, jadi tunggu sampai onResume
sebelum melakukan inisialisasi pada pemutar.
- Tambahkan metode
hideSystemUi
.
PlayerActivity.kt
@SuppressLint("InlinedApi")
private fun hideSystemUi() {
viewBinding.videoView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)
}
hideSystemUi
adalah metode helper yang dipanggil di onResume
, yang memungkinkan Anda untuk memiliki pengalaman layar penuh.
- Lepaskan resource dengan
releasePlayer
(yang akan segera Anda buat) dionPause
danonStop
.
PlayerActivity.kt
public override fun onPause() {
super.onPause()
if (Util.SDK_INT < 24) {
releasePlayer()
}
}
public override fun onStop() {
super.onStop()
if (Util.SDK_INT >= 24) {
releasePlayer()
}
}
Dengan API Level 24 dan yang lebih rendah, tidak ada jaminan onStop
akan dipanggil, jadi Anda harus melepaskan pemutar secepat mungkin di onPause
. Dengan API Level 24 dan yang lebih tinggi (yang membawa mode multi-jendela dan jendela-terpisah), onStop
pasti dipanggil. Dalam keadaan dijeda, aktivitas Anda masih terlihat, jadi Anda perlu menunggu untuk melepaskan pemutar sampai onStop
.
Sekarang Anda perlu membuat metode releasePlayer
, yang membebaskan resource pemutar dan menghancurkannya.
- Tambahkan kode berikut ke aktivitas:
PlayerActivity.kt
private var playWhenReady = true
private var currentWindow = 0
private var playbackPosition = 0L
[...]
private fun releasePlayer() {
player?.run {
playbackPosition = this.currentPosition
currentWindow = this.currentWindowIndex
playWhenReady = this.playWhenReady
release()
}
player = null
}
Sebelum Anda melepaskan dan menghancurkan pemutar, simpan informasi berikut:
- Putar/jeda status menggunakan
playWhenReady
. - Posisi pemutaran saat ini menggunakan
currentPosition
. - Indeks jendela saat ini menggunakan
currentWindowIndex
. Untuk informasi lebih lanjut tentang jendela, lihat Timeline.
Tindakan ini memungkinkan Anda untuk melanjutkan pemutaran dari tempat terakhir yang ditinggalkan pengguna. Yang perlu Anda lakukan adalah memberikan informasi status ini saat Anda melakukan inisialisasi pada pemutar.
Persiapan akhir
Yang perlu Anda lakukan sekarang adalah memberikan informasi status yang Anda simpan di releasePlayer
ke pemutar Anda selama inisialisasi.
- Tambahkan kode berikut ke
initializePlayer
:
PlayerActivity.kt
private fun initializePlayer() {
[...]
exoPlayer.playWhenReady = playWhenReady
exoPlayer.seekTo(currentWindow, playbackPosition)
exoPlayer.prepare()
}
Berikut ini yang terjadi:
playWhenReady
memberi tahu pemutar apakah akan memulai pemutaran segera setelah semua resource untuk pemutaran didapatkan. KarenaplayWhenReady
awalnya adalahtrue
, pemutaran dimulai secara otomatis saat pertama kali aplikasi berjalan.seekTo
memberi tahu pemutar untuk mencari posisi tertentu dalam jendela tertentu.currentWindow
danplaybackPosition
diinisialisasi ke nol sehingga pemutaran dimulai dari awal saat pertama kali aplikasi berjalan.prepare
memberi tahu pemutar untuk mendapatkan semua resource yang diperlukan untuk pemutaran.
Memutar audio
Akhirnya, tugas Anda selesai! Mulai aplikasi untuk memutar file MP3 dan lihat sematan karya seninya.
Screenshot: Aplikasi memainkan satu lagu.
Menguji siklus proses aktivitas
Uji apakah aplikasi berfungsi di berbagai status siklus proses aktivitas.
- Mulai aplikasi lain dan tempatkan aplikasi Anda di latar depan lagi. Apakah aplikasi melanjutkan pada posisi yang benar?
- Jeda aplikasi, pindahkan ke latar belakang, lalu ke latar depan lagi. Apakah aplikasi tetap dalam keadaan dijeda ketika ditempatkan di latar belakang dalam keadaan dijeda?
- Putar aplikasi. Bagaimana perilakunya jika Anda mengubah orientasi dari potret ke lanskap dan sebaliknya?
Memutar video
Jika Anda ingin memutar video, caranya semudah mengubah URI item media menjadi file MP4.
- Ubah URI di
initializePlayer
keR.string.media_url_mp4
. - Mulai kembali aplikasi dan uji perilakunya setelah ditempatkan di latar belakang dengan pemutaran video juga.
PlayerActivity.kt
private fun initializePlayer() {
[...]
val mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp4));
[...]
}
PlayerView
melakukan semuanya. Video dirender ke layar penuh, bukan karya seni.
Screenshot: Aplikasi sedang memutar video.
Anda hebat! Anda baru saja membuat aplikasi untuk streaming media dengan layar penuh di Android, lengkap dengan pengelolaan siklus proses, status tersimpan, serta kontrol UI!
4. Membuat playlist
Aplikasi Anda saat ini memutar satu file media, tetapi bagaimana jika Anda ingin memutar lebih dari satu file media, satu demi satu? Untuk itu, Anda memerlukan playlist.
Playlist dapat dibuat dengan menambahkan lebih banyak MediaItem
ke player
Anda menggunakan addMediaItem
. Hal ini memungkinkan pemutaran yang lancar, dan buffering ditangani di latar belakang sehingga pengguna tidak melihat indikator buffering dengan lingkaran berputar ketika mengubah item media.
- Tambahkan kode berikut ke
initializePlayer
:
PlayerActivity.kt
private void initializePlayer() {
[...]
exoPlayer.addMediaItem(mediaItem) // Existing code
val secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3));
exoPlayer.addMediaItem(secondMediaItem);
[...]
}
Periksa perilaku kontrol pemutar. Anda dapat menggunakan dan untuk melihat urutan item media.
Screenshot: Kontrol pemutaran menampilkan tombol sebelumnya dan berikutnya
Itu sangat mudah! Untuk informasi lebih lanjut, lihat dokumentasi developer di Item Media dan Playlist, dan artikel ini tentang API Playlist.
5. Streaming adaptif
Streaming adaptif adalah teknik streaming media dengan memvariasikan kualitas streaming berdasarkan bandwidth jaringan yang tersedia. Hal ini memungkinkan pengguna untuk menikmati media dengan kualitas terbaik yang dimungkinkan bandwidth mereka.
Biasanya, konten media yang sama dibagi menjadi beberapa trek dengan kualitas berbeda (kecepatan bit dan resolusi). Pemutar memilih trek berdasarkan bandwidth jaringan yang tersedia.
Setiap trek dibagi menjadi beberapa bagian dengan durasi tertentu, biasanya antara 2 sampai 10 detik. Ini memungkinkan pemutar untuk beralih dengan cepat di antara trek ketika bandwidth yang tersedia berubah. Pemutar bertanggung jawab untuk menggabungkan bagian-bagian ini agar pemutaran berjalan lancar.
Pemilihan trek adaptif
Inti dari streaming adaptif adalah memilih trek yang paling sesuai untuk lingkungan saat ini. Update aplikasi Anda untuk memutar media streaming adaptif dengan menggunakan pemilihan trek adaptif.
- Update
initializePlayer
dengan kode berikut:
PlayerActivity.kt
private fun initializePlayer() {
val trackSelector = DefaultTrackSelector(this).apply {
setParameters(buildUponParameters().setMaxVideoSizeSd())
}
player = SimpleExoPlayer.Builder(this)
.setTrackSelector(trackSelector)
.build()
[...]
}
Pertama, buat DefaultTrackSelector
, yang bertanggung jawab untuk memilih trek di item media. Lalu, beri tahu trackSelector
Anda untuk hanya memilih trek definisi standar atau lebih rendah. Itu adalah cara yang baik untuk menghemat data pengguna Anda dengan mengorbankan kualitas. Terakhir, teruskan trackSelector
Anda ke builder agar dapat digunakan ketika mem-build instance SimpleExoPlayer
.
Mem-build Item Media yang adaptif
DASH adalah format streaming adaptif yang banyak digunakan. Untuk melakukan streaming konten DASH, Anda perlu membuat MediaItem
seperti sebelumnya. Namun, kali ini kita harus menggunakan MediaItem.Builder
, bukan fromUri
.
Itu karena fromUri
menggunakan ekstensi file untuk menentukan format media yang mendasarinya tetapi URI DASH kita tidak memiliki ekstensi file sehingga kita harus menyediakan jenis MIME dari APPLICATION_MPD
ketika menyusun MediaItem
.
- Update
initializePlayer
sebagai berikut:
PlayerActivity.kt
private void initializePlayer() {
[...]
// Replace this line
val mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp4));
// With this
val mediaItem = MediaItem.Builder()
.setUri(getString(R.string.media_url_dash))
.setMimeType(MimeTypes.APPLICATION_MPD)
.build()
// Also remove the following lines
val secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3))
exoPlayer.addMediaItem(secondMediaItem)
}
- Mulai ulang aplikasi dan lihat streaming video adaptif dengan DASH yang sedang beraksi. Dengan ExoPlayer, semuanya mudah!
Format streaming adaptif lainnya
HLS (MimeTypes.APPLICATION_M3U8
) dan SmoothStreaming (MimeTypes.APPLICATION_SS
) adalah format streaming adaptif lain yang biasa digunakan, dan keduanya didukung oleh ExoPlayer. Untuk informasi lebih lanjut tentang menyusun sumber media adaptif lainnya, lihat aplikasi demo ExoPlayer.
6. Memproses peristiwa
Pada langkah sebelumnya, Anda telah mempelajari cara melakukan streaming media progresif dan adaptif. ExoPlayer melakukan banyak pekerjaan untuk Anda di belakang layar, termasuk yang berikut ini:
- Mengalokasikan memori
- Mendownload file container
- Mengekstrak metadata dari container
- Mendekode data
- Melakukan rendering video, audio, dan teks ke layar dan pengeras suara
Terkadang, mengetahui apa yang dilakukan ExoPlayer saat runtime sangat berguna untuk memahami dan meningkatkan pengalaman pemutaran bagi pengguna Anda.
Misalnya, Anda mungkin ingin menunjukkan perubahan status pemutaran di antarmuka pengguna dengan melakukan hal berikut:
- Menampilkan indikator pemuatan dengan lingkaran berputar ketika pemutar masuk ke status buffering
- Menampilkan overlay dengan opsi "tonton berikutnya" ketika trek telah berakhir
ExoPlayer menawarkan beberapa antarmuka pemroses yang menyediakan callback untuk peristiwa yang berguna. Anda menggunakan pemroses untuk menyimpan log status pemutar.
Memproses
- Buat
TAG
yang konstan di luar classPlayerActivity
, yang akan Anda gunakan untuk logging nanti.
PlayerActivity.kt
private const val TAG = "PlayerActivity"
- Implementasikan antarmuka
Player.EventListener
dalam fungsi factory di luar classPlayerActivity
. Ini digunakan untuk memberi tahu Anda tentang peristiwa pemutar yang penting, termasuk error dan perubahan status pemutaran. - Ganti
onPlaybackStateChanged
dengan menambahkan kode berikut:
PlayerActivity.kt
private fun playbackStateListener() = object : Player.EventListener {
override fun onPlaybackStateChanged(playbackState: Int) {
val stateString: String = when (playbackState) {
ExoPlayer.STATE_IDLE -> "ExoPlayer.STATE_IDLE -"
ExoPlayer.STATE_BUFFERING -> "ExoPlayer.STATE_BUFFERING -"
ExoPlayer.STATE_READY -> "ExoPlayer.STATE_READY -"
ExoPlayer.STATE_ENDED -> "ExoPlayer.STATE_ENDED -"
else -> "UNKNOWN_STATE -"
}
Log.d(TAG, "changed state to $stateString")
}
}
- Deklarasikan jenis anggota pribadi
Player.EventListener
dalamPlayerActivity
.
PlayerActivity.kt
class PlayerActivity : AppCompatActivity() {
[...]
private val playbackStateListener: Player.EventListener = playbackStateListener()
}
onPlaybackStateChanged
dipanggil ketika status pemutaran berubah. Status baru diberikan oleh parameter playbackState
.
Pemutar dapat berada di salah satu dari empat status berikut:
Status | Deskripsi |
| Pemutar telah dibuatkan instance, tetapi belum siap. |
| Pemutar tidak dapat melakukan pemutaran dari posisi saat ini karena tidak cukup data untuk buffering |
| Pemutar dapat langsung melakukan pemutaran dari posisi saat ini. Ini berarti pemutar akan mulai memutar media secara otomatis jika properti playWhenReady pemutar adalah |
| Pemutar telah selesai memutar media. |
Mendaftarkan pemroses Anda
Agar callback Anda dipanggil, Anda harus mendaftarkan playbackStateListener
dengan pemutar. Lakukan ini di initializePlayer
.
- Daftarkan pemroses sebelum pemutaran disiapkan.
PlayerActivity.kt
private void initializePlayer() {
[...]
exoPlayer.seekTo(currentWindow, playbackPosition)
exoPlayer.addListener(playbackStateListener)
[...]
}
Sekali lagi, Anda perlu merapikan untuk menghindari referensi menggantung dari pemutar yang dapat menyebabkan kebocoran memori.
- Hapus pemroses di
releasePlayer
:
PlayerActivity.kt
private void releasePlayer() {
player?.run {
[...]
removeListener(playbackStateListener)
release()
}
player = null
}
- Buka logcat dan jalankan aplikasi.
- Gunakan kontrol UI untuk mencari, menjeda, dan melanjutkan pemutaran. Anda akan melihat perubahan status pemutaran di log.
Mengelola lebih jauh
ExoPlayer menawarkan sejumlah pemroses lain, yang berguna dalam memahami pengalaman pemutaran pengguna. Ada pemroses untuk audio dan video, juga AnalyticsListener
, yang berisi callback dari semua pemroses. Berikut ini beberapa metode yang paling penting:
onRenderedFirstFrame
dipanggil ketika frame pertama video dirender. Dengan ini, Anda dapat menghitung berapa lama pengguna harus menunggu untuk melihat konten yang berarti di layar.onDroppedVideoFrames
dipanggil ketika frame video drop. Frame yang drop menunjukkan bahwa pemutaran tersendat dan pengalaman pengguna cenderung buruk.onAudioUnderrun
dipanggil ketika underrun audio terjadi. Underrun menyebabkan gangguan yang terdengar dalam suara dan lebih kentara daripada frame video yang drop.
AnalyticsListener
dapat ditambahkan ke player
dengan addAnalyticsListener
. Ada metode yang sesuai untuk pemroses audio dan video juga.
Pikirkan tentang peristiwa yang penting bagi aplikasi dan pengguna Anda. Untuk informasi lebih lanjut, lihat Pemroses untuk peristiwa pemutar. Pemroses peristiwa selesai!
7. Menyesuaikan antarmuka pengguna
Sejauh ini, Anda telah menggunakan PlayerControlView
ExoPlayer untuk menampilkan pengontrol pemutaran kepada pengguna.
Screenshot: Pengontrol pemutaran default
Bagaimana jika Anda ingin mengubah fungsionalitas atau tampilan dan nuansa kontrol ini? Untunglah, kontrol ini sangat mudah disesuaikan.
Penyesuaian sederhana pertama adalah tidak menggunakan pengontrol sama sekali. Ini dapat dilakukan dengan mudah menggunakan atribut use_controller
pada elemen PlayerView
di dalam activity_player.xml
.
- Setel
use_controller
kefalse
dan kontrolnya tidak akan muncul lagi:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView
[...]
app:use_controller="false"/>
- Tambahkan namespace berikut ke
FrameLayout
Anda:
activity_player.xml
<FrameLayout
[...]
xmlns:app="http://schemas.android.com/apk/res-auto">
Coba sekarang.
Menyesuaikan perilaku
PlayerControlView
memiliki beberapa atribut yang memengaruhi perilakunya. Misalnya, Anda dapat menggunakan show_timeout
untuk menyesuaikan penundaan dalam milidetik sebelum kontrol disembunyikan setelah pengguna terakhir kali berinteraksi dengannya. Untuk melakukannya:
- Hapus
app:use_controller="false"
. - Ubah tampilan pemutar untuk menggunakan
show_timeout
:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:show_timeout="10000"/>
Atribut PlayerControlView
juga dapat disetel secara terprogram.
Menyesuaikan tampilan
Itu awal yang baik. Tetapi, bagaimana jika Anda ingin PlayerControlView
terlihat berbeda atau mengubah tombol mana yang akan ditampilkan? Implementasi PlayerControlView
tidak mengasumsikan adanya tombol apa pun, jadi mudah untuk menghapusnya dan menambahkan yang baru.
Lihat bagaimana Anda dapat menyesuaikan PlayerControlView
.
- Buat file tata letak
custom_player_control_view.xml
yang baru di folderplayer-lib/res/layout/
. - Dari menu konteks folder tata letak, pilih New - Layout resource file dan beri nama
custom_player_control_view.xml
.
Screenshot: File tata letak untuk tampilan kontrol pemutar telah dibuat.
- Salin file tata letak asli dari sini ke
custom_player_control_view.xml
. - Hapus elemen
ImageButton
dengan ID@id/exo_prev
dan@id/exo_next
.
Untuk menggunakan tata letak kustom, Anda perlu menyetel atribut app:controller_layout_id
dari elemen PlayerView
di file activity_player.xml
.
- Gunakan ID tata letak file kustom Anda seperti pada cuplikan kode berikut:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:controller_layout_id="@layout/custom_player_control_view"/>
- Mulai aplikasi kembali. Tampilan kontrol pemutar tidak lagi memiliki tombol sebelumnya dan berikutnya.
Screenshot: Tampilan kontrol pemutar kustom tanpa tombol sebelumnya atau berikutnya
Anda dapat menerapkan perubahan apa pun yang Anda suka di file tata letak. Secara default, warna tema Android dipilih. Anda dapat menggantinya agar sesuai dengan desain aplikasi Anda.
- Tambahkan atribut
android:tint
ke setiap elemenImageButton
:
custom_player_control_view.xml
<ImageButton android:id="@id/exo_rew"
android:tint="#FF00A6FF"
style="@style/ExoMediaButton.Rewind"/>
- Tambahkan semua atribut
android:textColor
yang Anda temukan dalam file kustom Anda ke warna yang sama:#FF00A6FF
.
custom_player_control_view.xml
<TextView android:id="@id/exo_position"
[...]
android:textColor="#FF00A6FF"/>
<TextView android:id="@id/exo_duration"
[...]
android:textColor="#FF00A6FF"/>
- Jalankan aplikasi. Sekarang Anda memiliki komponen UI yang indah dan berwarna!
Screenshot: Tombol berwarna dan tampilan teks
Mengganti gaya default
Anda baru saja membuat file tata letak kustom dan mereferensikannya menggunakan controller_layout_id
di activity_player.xml
.
Pendekatan lain adalah mengganti file tata letak default yang digunakan PlayerControlView
. Kode sumber PlayerControlView
memberitahu kita bahwa kode itu menggunakan R.layout.exo_player_control_view
untuk tata letak. Jika Anda membuat file tata letak sendiri dengan nama file yang sama, PlayerControlView
akan menggunakan file Anda sebagai gantinya.
- Hapus atribut
controller_layout_id
yang baru saja Anda tambahkan. - Hapus file
custom_player_control_view.xml
.
PlayerView
dalam activity_player.xml
kini akan terlihat seperti ini:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
- Buat file bernama
exo_player_control_view.xml
dalam folderres/layout
di modul libraryplayer-lib
Anda. - Masukkan kode berikut ke dalam
exo_player_control_view.xml
untuk menambahkan tombol putar, tombol jeda, danImageView
dengan logo:
exo_player**_control_view.xml**
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layoutDirection="ltr"
android:background="#CC000000"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingTop="4dp"
android:orientation="horizontal">
<ImageButton android:id="@id/exo_play"
style="@style/ExoMediaButton.Play"/>
<ImageButton android:id="@id/exo_pause"
style="@style/ExoMediaButton.Pause"/>
</LinearLayout>
<ImageView
android:contentDescription="@string/logo"
android:src="@drawable/google_logo"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Ini menunjukkan cara Anda dapat menambahkan elemen Anda sendiri di sini dan mencampurnya dengan elemen kontrol standar. ExoPlayerView
sekarang menggunakan kontrol kustom Anda dan semua logika untuk bersembunyi dan tampil saat interaksi dengan kontrol dipertahankan.
8 Selamat
Selamat! Anda telah belajar banyak tentang mengintegrasikan ExoPlayer dengan aplikasi Anda.
Pelajari lebih lanjut
Untuk mempelajari ExoPlayer lebih lanjut, lihat panduan developer dan kode sumber, serta berlangganan blog ExoPlayer.