Stack jaringan

ExoPlayer biasanya digunakan untuk streaming media melalui internet. Aplikasi ini mendukung beberapa stack jaringan untuk membuat permintaan jaringan yang mendasarinya. Pilihan stack jaringan dapat berdampak signifikan pada performa streaming.

Halaman ini menguraikan cara mengonfigurasi ExoPlayer untuk menggunakan stack jaringan pilihan Anda, mencantumkan opsi yang tersedia, memberikan beberapa panduan tentang cara memilih stack jaringan untuk aplikasi Anda, dan menjelaskan cara mengaktifkan penyimpanan dalam cache 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 disuntikkan dari kode aplikasi.

Jika aplikasi Anda hanya perlu memutar konten http(s), memilih stack jaringan sama sederhananya dengan memperbarui semua instance DataSource.Factory yang disisipkan aplikasi Anda menjadi instance HttpDataSource.Factory yang sesuai dengan stack jaringan yang ingin Anda gunakan. Jika aplikasi Anda juga perlu memutar konten non-http(s), 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(s) seperti file lokal.

Contoh berikut menunjukkan cara membuat ExoPlayer yang akan menggunakan stack jaringan Cronet dan juga mendukung pemutaran konten non-http(s).

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 HttpEngine, Cronet, OkHttp, dan stack jaringan default bawaan Android. ExoPlayer juga dapat diperluas untuk mendukung stack jaringan lain yang berfungsi di Android.

HttpEngine

HttpEngine adalah stack jaringan default yang direkomendasikan di Android dari API 34 (atau ekstensi S 7). Dalam sebagian besar kasus, aplikasi ini menggunakan stack jaringan Cronet secara internal, yang mendukung protokol HTTP, HTTP/2, dan HTTP/3 melalui QUIC.

ExoPlayer mendukung HttpEngine dengan HttpEngineDataSource.Factory-nya. Anda dapat menyuntikkan factory sumber data ini seperti yang dijelaskan dalam Mengonfigurasi ExoPlayer untuk menggunakan stack jaringan tertentu.

Cronet

Cronet adalah stack jaringan Chromium yang disediakan untuk aplikasi Android sebagai library. Cronet memanfaatkan beberapa teknologi yang mampu mengurangi latensi dan meningkatkan throughput permintaan jaringan yang diperlukan aplikasi agar dapat berfungsi, termasuk yang dibuat oleh ExoPlayer. Secara native, library ini mendukung protokol HTTP, HTTP/2, dan HTTP/3 melalui QUIC. Cronet digunakan oleh beberapa aplikasi streaming terbesar di dunia, termasuk YouTube.

ExoPlayer mendukung Cronet melalui library Cronet. Lihat README.md library untuk mengetahui petunjuk mendetail tentang cara menggunakannya. Perhatikan bahwa library Cronet dapat menggunakan tiga penerapan Cronet yang mendasarinya:

  1. Layanan Google Play: Sebaiknya gunakan penerapan ini dalam sebagian besar kasus, dan kembali ke stack jaringan bawaan Android (DefaultHttpDataSource) jika Layanan Google Play tidak tersedia.
  2. Cronet Tersemat: Mungkin merupakan pilihan yang baik jika sebagian besar pengguna Anda berada di pasar yang Layanan Google Play-nya tidak tersedia secara luas, atau jika Anda ingin mengontrol versi pasti dari penerapan Cronet yang digunakan. Kelemahan utama Cronet Embedded adalah penambahan sekitar 8 MB ke aplikasi Anda.
  3. Penggantian Cronet: Implementasi penggantian Cronet menerapkan API Cronet sebagai wrapper di sekitar stack jaringan bawaan Android. Class ini tidak boleh digunakan dengan ExoPlayer, karena menggunakan stack jaringan bawaan Android secara langsung (dengan menggunakan DefaultHttpDataSource) lebih efisien.

OkHttp

OkHttp adalah stack jaringan modern lainnya yang banyak digunakan oleh banyak aplikasi Android populer. Server ini mendukung HTTP dan HTTP/2, tetapi belum mendukung HTTP/3 melalui QUIC.

ExoPlayer mendukung OkHttp melalui library OkHttp. Lihat README.md library untuk mengetahui petunjuk mendetail tentang cara menggunakannya. Saat menggunakan library OkHttp, stack jaringan disematkan dalam aplikasi. Hal ini mirip dengan Cronet Embedded, tetapi OkHttp jauh lebih kecil, dengan penambahan 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 yang mendasarinya. Di sebagian besar perangkat, hanya HTTP yang didukung (yaitu, HTTP/2 dan HTTP/3 melalui QUIC tidak didukung).

Stack jaringan lainnya

Aplikasi juga dapat mengintegrasikan stack jaringan lain dengan ExoPlayer. Untuk melakukannya, terapkan HttpDataSource yang membungkus stack jaringan, bersama dengan HttpDataSource.Factory yang sesuai. Library Cronet dan OkHttp ExoPlayer adalah contoh yang baik tentang cara melakukannya.

Saat berintegrasi dengan stack jaringan Java murni, sebaiknya terapkan DataSourceContractTest untuk memeriksa apakah penerapan HttpDataSource Anda berperilaku dengan benar. OkHttpDataSourceContractTest di library OkHttp adalah contoh yang baik tentang cara melakukannya.

Memilih stack jaringan

Tabel berikut menguraikan kelebihan dan kekurangan stack jaringan yang didukung oleh ExoPlayer.

Stack jaringan Protokol Dampak ukuran APK Catatan
HttpEngine HTTP
HTTP/2
HTTP/3 melalui QUIC
Tidak ada Hanya tersedia di API 34, atau Ekstensi S 7
Cronet (Layanan Google Play) HTTP
HTTP/2
HTTP/3 melalui QUIC
Kecil
(<100 KB)
Memerlukan Layanan Google Play. Versi Cronet diperbarui secara otomatis
Cronet (Disematkan) HTTP
HTTP/2
HTTP/3 melalui QUIC
Besar
(~8MB)
Versi Cronet yang dikontrol oleh developer aplikasi
Cronet (Pengganti) HTTP
(berbeda-beda menurut perangkat)
Kecil
(<100 KB)
Tidak direkomendasikan untuk ExoPlayer
OkHttp HTTP
HTTP/2
Kecil
(<1MB)
Stack jaringan bawaan HTTP
(berbeda-beda 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 yang memungkinkan penggunaan protokol ini membuat CDN beroperasi secara lebih efisien. Oleh karena itu, dukungan HttpEngine dan Cronet untuk HTTP/2 dan HTTP/3 melalui QUIC (serta dukungan OkHttp untuk HTTP/2) adalah manfaat utama dibandingkan dengan menggunakan stack jaringan bawaan Android, asalkan server tempat konten dihosting juga mendukung protokol ini.

Saat mempertimbangkan streaming media secara terpisah, sebaiknya gunakan HttpEngine atau Cronet yang disediakan oleh Layanan Google Play yang di-fallback ke DefaultHttpDataSource jika Layanan Google Play tidak tersedia. Rekomendasi ini menyeimbangkan 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 ketika Layanan Google Play kemungkinan tidak tersedia di sebagian besar perangkat yang akan menjalankan aplikasi Anda, menggunakan Cronet Embedded atau OkHttp mungkin lebih tepat. Penggunaan stack jaringan bawaan dapat diterima jika ukuran APK menjadi perhatian utama, atau jika streaming media hanya merupakan bagian kecil dari fungsi aplikasi Anda.

Selain media, biasanya sebaiknya pilih satu stack jaringan untuk semua jaringan yang dilakukan oleh aplikasi Anda. Hal ini memungkinkan resource (seperti soket) dikelompokkan dan dibagikan secara efisien antara ExoPlayer dan komponen aplikasi lainnya.

Karena aplikasi Anda kemungkinan besar perlu melakukan jaringan yang tidak terkait dengan pemutaran media, pilihan stack jaringan Anda pada akhirnya harus mempertimbangkan rekomendasi kami di atas untuk streaming media secara terpisah, persyaratan komponen lain yang melakukan jaringan, dan kepentingan relatifnya terhadap aplikasi Anda.

Menyimpan media ke dalam cache

ExoPlayer mendukung penyimpanan byte yang dimuat ke disk untuk mencegah pemuatan byte yang sama dari jaringan berulang kali. Hal ini berguna saat mencari kembali di media saat ini atau mengulangi item yang sama.

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