ExoPlayer biasanya digunakan untuk streaming media melalui internet. Aplikasi ini mendukung beberapa stack jaringan untuk membuat permintaan jaringan yang mendasarinya. Pilihan stack jaringan Anda dapat memiliki dampak yang signifikan terhadap performa streaming.
Halaman ini menguraikan cara mengonfigurasi ExoPlayer agar menggunakan stack pilihan jaringan Anda, mencantumkan opsi yang tersedia, memberikan beberapa panduan tentang cara memilih stack jaringan untuk aplikasi Anda, dan menjelaskan cara mengaktifkan caching untuk media yang di-streaming.
Mengonfigurasi ExoPlayer untuk menggunakan stack jaringan tertentu
ExoPlayer memuat data melalui komponen DataSource
, yang diperoleh dari
instance DataSource.Factory
yang dimasukkan dari kode aplikasi.
Jika aplikasi Anda hanya perlu memutar konten http, memilih stack
jaringan semudah memperbarui instance DataSource.Factory
yang
dimasukkan aplikasi Anda menjadi instance HttpDataSource.Factory
yang sesuai dengan stack jaringan yang ingin Anda gunakan. Jika aplikasi Anda juga
perlu memutar konten non-http, seperti file lokal, gunakan
DefaultDataSource.Factory
:
Kotlin
DefaultDataSource.Factory( ... /* baseDataSourceFactory= */ PreferredHttpDataSource.Factory(...))
Java
new DefaultDataSource.Factory( ... /* baseDataSourceFactory= */ new PreferredHttpDataSource.Factory(...));
Dalam contoh ini, PreferredHttpDataSource.Factory
adalah factory yang sesuai dengan stack jaringan
pilihan Anda. Lapisan DefaultDataSource.Factory
menambahkan dukungan untuk sumber non-http seperti file lokal.
Contoh berikut menunjukkan cara membuat ExoPlayer
yang akan menggunakan stack
jaringan Cronet dan juga mendukung pemutaran konten non-http.
Kotlin
// Given a CronetEngine and Executor, build a CronetDataSource.Factory. val cronetDataSourceFactory = CronetDataSource.Factory(cronetEngine, executor) // Wrap the CronetDataSource.Factory in a DefaultDataSource.Factory, which adds // in support for requesting data from other sources (such as files, resources, // etc). val dataSourceFactory = DefaultDataSource.Factory(context, /* baseDataSourceFactory= */ cronetDataSourceFactory) // Inject the DefaultDataSource.Factory when creating the player. val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory) ) .build()
Java
// Given a CronetEngine and Executor, build a CronetDataSource.Factory. CronetDataSource.Factory cronetDataSourceFactory = new CronetDataSource.Factory(cronetEngine, executor); // Wrap the CronetDataSource.Factory in a DefaultDataSource.Factory, which adds // in support for requesting data from other sources (such as files, resources, // etc). DefaultDataSource.Factory dataSourceFactory = new DefaultDataSource.Factory( context, /* baseDataSourceFactory= */ cronetDataSourceFactory); // Inject the DefaultDataSource.Factory when creating the player. ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory)) .build();
Stack jaringan yang didukung
ExoPlayer memberikan dukungan langsung untuk stack jaringan bawaan Cronet, OkHttp, dan Android. ExoPlayer juga dapat diperluas untuk mendukung stack jaringan lainnya yang berfungsi di Android.
Cronet
Cronet adalah stack jaringan Chromium yang disediakan untuk aplikasi Android sebagai library. Cronet memanfaatkan beberapa teknologi yang mengurangi latensi dan meningkatkan throughput permintaan jaringan yang diperlukan aplikasi Anda untuk berfungsi, termasuk yang dibuat oleh ExoPlayer. Secara native mendukung protokol HTTP, HTTP/2, dan HTTP/3 melalui protokol QUIC. Cronet digunakan oleh beberapa aplikasi streaming terbesar di dunia, termasuk YouTube.
ExoPlayer mendukung Cronet melalui
library Cronet.
Lihat README.md
library untuk petunjuk mendetail tentang cara menggunakannya. Perhatikan bahwa library Cronet dapat menggunakan tiga implementasi
Cronet yang mendasarinya:
- Layanan Google Play: Sebaiknya gunakan implementasi ini dalam banyak
kasus, dan kembali ke stack jaringan bawaan Android
(
DefaultHttpDataSource
) jika Layanan Google Play tidak tersedia. - Cronet Disematkan: Mungkin menjadi pilihan bagus jika sebagian besar pengguna Anda berada di pasar yang tidak menyediakan Layanan Google Play secara luas, atau jika Anda ingin mengontrol versi implementasi Cronet yang tepat yang digunakan. Kekurangan utama Cronet Embedded adalah penambahan sekitar 8 MB ke aplikasi Anda.
- Penggantian Cronet: Implementasi penggantian Cronet mengimplementasikan
API Cronet sebagai wrapper di sekitar stack jaringan bawaan Android. Ini tidak boleh
digunakan dengan ExoPlayer, karena menggunakan stack jaringan bawaan Android
secara langsung (dengan menggunakan
DefaultHttpDataSource
) akan lebih efisien.
OkHttp
OkHttp adalah stack jaringan modern lain yang banyak digunakan oleh banyak aplikasi Android populer. API ini mendukung HTTP dan HTTP/2, tetapi belum mendukung HTTP/3 melalui QUIC.
ExoPlayer mendukung OkHttp melalui
library OkHttp-nya.
Lihat README.md
library untuk petunjuk mendetail tentang cara menggunakannya. Saat menggunakan library OkHttp, stack jaringan akan disematkan di dalam
aplikasi. Hal ini mirip dengan Cronet Embedded, tetapi OkHttp jauh lebih kecil, sehingga menambahkan kurang dari 1 MB ke aplikasi Anda.
Stack jaringan bawaan Android
ExoPlayer mendukung penggunaan stack jaringan bawaan Android dengan
DefaultHttpDataSource
dan DefaultHttpDataSource.Factory
, yang merupakan bagian dari
library ExoPlayer inti.
Implementasi stack jaringan yang tepat bergantung pada software yang berjalan di perangkat dasar. Di sebagian besar perangkat (mulai tahun 2021), hanya HTTP yang didukung (yaitu, HTTP/2 dan HTTP/3 melalui QUIC tidak didukung).
Stack jaringan lainnya
Aplikasi juga dapat mengintegrasikan stack jaringan lainnya dengan ExoPlayer.
Untuk melakukannya, implementasikan HttpDataSource
yang menggabungkan stack jaringan,
bersama dengan HttpDataSource.Factory
yang sesuai. Library Cronet dan OkHttp ExoPlayer adalah
contoh yang baik tentang cara melakukan ini.
Saat berintegrasi dengan stack jaringan Java murni, sebaiknya implementasikan
DataSourceContractTest
untuk memeriksa apakah implementasi HttpDataSource
Anda
berperilaku dengan benar. OkHttpDataSourceContractTest
di library OkHttp adalah
contoh yang baik terkait cara melakukannya.
Memilih stack jaringan
Tabel berikut menguraikan kelebihan dan kekurangan stack jaringan yang didukung oleh ExoPlayer.
Stack jaringan | Protokol | Dampak ukuran APK | Catatan |
---|---|---|---|
Cronet (Layanan Google Play) | HTTP HTTP/2 HTTP/3 melalui QUIC |
Kecil (<100 KB) |
Memerlukan Layanan Google Play. Versi Cronet diupdate secara otomatis |
Cronet (Disematkan) | HTTP HTTP/2 HTTP/3 melalui QUIC |
Besar (~8 MB) |
Versi Cronet yang dikontrol oleh developer aplikasi |
Cronet (Penggantian) | HTTP (bervariasi menurut perangkat) |
Kecil (<100 KB) |
Tidak direkomendasikan untuk ExoPlayer |
OkHttp | HTTP HTTP/2 |
Kecil (<1 MB) |
Memerlukan runtime Kotlin |
Stack jaringan bawaan | HTTP (bervariasi menurut perangkat) |
Tidak ada | Penerapan bervariasi menurut perangkat |
Protokol HTTP/2 dan HTTP/3 melalui QUIC dapat meningkatkan performa streaming media secara signifikan. Secara khusus, saat melakukan streaming media adaptif yang didistribusikan menggunakan jaringan distribusi konten (CDN), ada kasus di mana penggunaan protokol ini dapat memungkinkan CDN beroperasi jauh lebih efisien. Karena alasan ini, dukungan Cronet untuk HTTP/2 dan HTTP/3 melalui QUIC (dan dukungan OkHttp untuk HTTP/2), adalah manfaat besar dibandingkan dengan menggunakan stack jaringan bawaan Android, asalkan server tempat konten dihosting juga mendukung protokol ini.
Saat mempertimbangkan streaming media secara terpisah, sebaiknya gunakan Cronet
yang disediakan oleh Layanan Google Play, kembali ke DefaultHttpDataSource
jika
Layanan Google Play tidak tersedia. Rekomendasi ini mencapai keseimbangan yang baik antara mengaktifkan penggunaan HTTP/2 dan HTTP/3 melalui QUIC di sebagian besar perangkat, dan
menghindari peningkatan ukuran APK yang signifikan. Ada pengecualian untuk
rekomendasi ini. Untuk kasus saat Layanan Google Play kemungkinan tidak tersedia
pada sebagian besar perangkat yang akan menjalankan aplikasi Anda,
penggunaan Cronet Embedded atau OkHttp mungkin lebih tepat. Penggunaan stack
jaringan bawaan dapat diterima jika ukuran APK menjadi perhatian penting, atau jika streaming
media hanya merupakan bagian kecil dari fungsi aplikasi Anda.
Selain media, sebaiknya pilih satu stack jaringan untuk semua jaringan yang dilakukan oleh aplikasi Anda. Hal ini memungkinkan resource (seperti soket) digabungkan dan dibagikan secara efisien antara ExoPlayer dan komponen aplikasi lainnya.
Karena aplikasi Anda kemungkinan besar harus melakukan jaringan yang tidak terkait dengan pemutaran media, pilihan stack jaringan pada akhirnya harus mempertimbangkan rekomendasi kami di atas untuk streaming media secara terpisah, persyaratan komponen lain yang menjalankan jaringan, dan kepentingan relatifnya terhadap aplikasi Anda.
Menyimpan media ke dalam cache
ExoPlayer mendukung byte yang dimuat dalam cache ke disk untuk mencegah pemuatan berulang byte yang sama dari jaringan. Hal ini berguna saat melakukan pencarian kembali di media saat ini atau mengulangi item yang sama.
Penyimpanan ke cache memerlukan instance SimpleCache
yang mengarah ke direktori cache
khusus dan CacheDataSource.Factory
:
Kotlin
// Note: This should be a singleton in your app. val databaseProvider = StandaloneDatabaseProvider(context) // An on-the-fly cache should evict media when reaching a maximum disk space limit. val cache = SimpleCache( downloadDirectory, LeastRecentlyUsedCacheEvictor(maxBytes), databaseProvider) // Configure the DataSource.Factory with the cache and factory for the desired HTTP stack. val cacheDataSourceFactory = CacheDataSource.Factory() .setCache(cache) .setUpstreamDataSourceFactory(httpDataSourceFactory) // Inject the DefaultDataSource.Factory when creating the player. val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory)) .build()
Java
// Note: This should be a singleton in your app. DatabaseProvider databaseProvider = new StandaloneDatabaseProvider(context); // An on-the-fly cache should evict media when reaching a maximum disk space limit. Cache cache = new SimpleCache( downloadDirectory, new LeastRecentlyUsedCacheEvictor(maxBytes), databaseProvider); // Configure the DataSource.Factory with the cache and factory for the desired HTTP stack. DataSource.Factory cacheDataSourceFactory = new CacheDataSource.Factory() .setCache(cache) .setUpstreamDataSourceFactory(httpDataSourceFactory); // Inject the DefaultDataSource.Factory when creating the player. ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory)) .build();