Stosy sieciowe

ExoPlayer jest często używany do strumieniowego przesyłania multimediów przez Internet. Obsługuje wiele stosów sieciowych do wykonywania podstawowych żądań sieciowych. Wybrany przez Ciebie pakiet sieciowy może mieć znaczący wpływ na wydajność strumieniowania.

Na tej stronie opisano, jak skonfigurować ExoPlayera, aby używał wybranego przez Ciebie pakietu sieciowego, podano listę dostępnych opcji, przedstawiono wskazówki dotyczące wyboru pakietu sieciowego dla aplikacji oraz wyjaśniono, jak włączyć buforowanie strumieniowanych multimediów.

Konfigurowanie ExoPlayera pod kątem korzystania z określonego stosu sieciowego

ExoPlayer wczytuje dane za pomocą komponentów DataSource, które uzyskuje z instancji DataSource.Factory wstrzykiwanych z kodu aplikacji.

Jeśli Twoja aplikacja ma odtwarzać tylko treści http(s), możesz wybrać zestaw protokołów sieciowych, aktualizując instancje DataSource.Factory, które aplikacja wstrzykuje, tak aby były instancjami HttpDataSource.Factory odpowiadającymi zestawowi protokołów sieciowych, którego chcesz użyć. Jeśli Twoja aplikacja musi też odtwarzać treści inne niż http(s), np. pliki lokalne, użyj:DefaultDataSource.Factory

Kotlin

DefaultDataSource.Factory(
  ...
  /* baseDataSourceFactory= */ PreferredHttpDataSource.Factory(...))

Java

new DefaultDataSource.Factory(
    ...
    /* baseDataSourceFactory= */ new PreferredHttpDataSource.Factory(...));

W tym przykładzie PreferredHttpDataSource.Factory to fabryka odpowiadająca Twojemu preferowanym stosem sieciowym. Warstwa DefaultDataSource.Factory udostępnia dodatkowe funkcje dla źródeł innych niż HTTP, takich jak pliki lokalne.

Ten przykład pokazuje, jak utworzyć obiekt ExoPlayer, który będzie używał Cronet stosunkowo dużo czasu, a także obsługiwać odtwarzanie treści innych niż 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();

Obsługiwane stosy sieci

ExoPlayer zapewnia bezpośrednią obsługę HttpEngine, Cronet, OkHttp i z wbudowanym, domyślnym stosem sieciowym. ExoPlayer może też obsługiwać dowolny inny moduł sieciowy działający na Androidzie.

silnik HTTp

HttpEngine to zalecany domyślny moduł sieci na Androidzie od API 34 (lub rozszerzeń 7). W większości przypadków korzysta on z wewnętrznego stosu sieci Cronet, obsługujące HTTP, HTTP/2 i HTTP/3 za pomocą protokołów QUIC.

ExoPlayer obsługuje HttpEngine za pomocą HttpEngineDataSource.Factory. Możesz wstrzyknąć tę fabrykę źródeł danych w sposób opisany w artykule Konfigurowanie ExoPlayera do używania określonego pakietu sieciowego.

Cronet

Cronet to stos sieciowy Chromium udostępniony aplikacjom na Androida jako biblioteka. Cronet korzysta z wielu technologii, które zmniejszają opóźnienia i zwiększają przepustowość żądań sieciowych, których potrzebuje Twoja aplikacja do działania, w tym tych wysyłanych przez ExoPlayera. Natywnie obsługuje protokół HTTP, HTTP/2 i HTTP/3 przez QUIC protokoły API. Z Cronetu korzystają największe aplikacje do odtwarzania strumieniowego na świecie. w tym również z YouTube.

ExoPlayer obsługuje Cronet za pomocą biblioteki Cronet. Szczegółowe instrukcje korzystania z biblioteki znajdziesz w README.md. Pamiętaj, że biblioteka Cronet może korzystać z 3 podstawowych funkcji Cronet implementacji:

  1. Usługi Google Play: w większości przypadków zalecamy używanie tej implementacji, a w razie niedostępności Usług Google Play – korzystania z wbudowanego modułu sieciowego Androida (DefaultHttpDataSource).
  2. Wbudowany Cronet: może być dobrym rozwiązaniem, jeśli duży odsetek użytkowników znajdują się na rynkach, na których Usługi Google Play nie są powszechnie dostępne, lub jeśli chcesz kontrolować dokładną wersję używanej implementacji Cronet. Główną wadą Cronet Embedded jest to, że zwiększa rozmiar aplikacji o około 8 MB.
  3. Kreacja zastępcza Cronet: implementacja kreacji zastępczej zaimplementowanej przez Cronet Interfejs API Cronet jako otoka wbudowanego stosu sieciowego Androida. Nie należy go używać z ExoPlayerem, ponieważ bezpośrednie korzystanie z wbudowanego w Androidzie modułu sieciowego (za pomocą DefaultHttpDataSource) jest bardziej wydajne.

OkHttp

OkHttp to kolejny nowoczesny stos sieciowy, jest powszechnie stosowany w wielu popularnych aplikacjach na Androida. Obsługuje protokoły HTTP i HTTP/2, ale nie obsługuje jeszcze HTTP/3 przez QUIC.

ExoPlayer obsługuje OkHttp za pomocą biblioteki OkHttp. Szczegółowe instrukcje korzystania z usługi znajdziesz w dokumencie README.md biblioteki. . Podczas korzystania z biblioteki OkHttp pakiet sieciowy jest umieszczany w aplikacji. Jest to podobne do wbudowanej biblioteki Cronet, ale OkHttp jest znacznie mniejszy i dodaje do aplikacji mniej niż 1 MB.

Wbudowany stos sieciowy Androida

ExoPlayer obsługuje wbudowany stos sieciowy Androida z DefaultHttpDataSource i DefaultHttpDataSource.Factory, które są częścią w głównej bibliotece ExoPlayer.

Dokładna implementacja warstwy sieciowej zależy od oprogramowania działającego na urządzeniu. Na większości urządzeń obsługiwany jest tylko protokół HTTP (czyli HTTP/2 i HTTP/3 przez QUIC nie są obsługiwane).

Inne stosy sieciowe

Z platformą ExoPlayer aplikacje mogą też integrować inne stosy sieciowe. Aby to zrobić, zaimplementuj obiekt HttpDataSource, który opakowuje stos sieciowy. razem z odpowiednimi wartościami HttpDataSource.Factory. Przykładem tego są biblioteki Cronet i OkHttp ExoPlayera.

Przy integracji ze stosem sieciowym opartym na Javie warto zastosować DataSourceContractTest, aby sprawdzić, czy implementacja HttpDataSource będzie działać prawidłowo. OkHttpDataSourceContractTest w bibliotece OkHttp to dobry przykład tego, jak to zrobić.

Wybieranie stosu sieci

W tej tabeli opisujemy zalety i wady stosów sieciowych obsługiwanych przez ExoPlayer,

Stos sieci Protokoły Wpływ rozmiaru pliku APK Uwagi
silnik HTTp HTTP
HTTP/2
HTTP/3 przez QUIC
Brak Dostępne tylko w interfejsie API 34 lub rozszerzeniach S 7
Cronet (Usługi Google Play) HTTP
HTTP/2
HTTP/3 przez QUIC
Mały
(< 100 KB)
Wymaga Usług Google Play. Wersja Cronet aktualizowana automatycznie
Cronet (wbudowany) HTTP
HTTP/2
HTTP/3 przez QUIC
Duży
(ok. 8 MB)
Wersja Cronet kontrolowana przez dewelopera aplikacji
Cronet (wartość zastępcza) HTTP
(zależy od urządzenia)
Mały
(<100 KB)
Nie zalecane w przypadku ExoPlayer
OkHttp HTTP
HTTP/2
Mały
(<1 MB)
Wbudowany stos sieciowy HTTP
(zależy od urządzenia)
Brak Implementacja różni się w zależności od urządzenia

Protokoły HTTP/2 i HTTP/3 z protokołami QUIC mogą znacznie poprawić jakość multimediów wydajność strumieniowania. W szczególności w przypadku strumieniowego przesyłania multimediów adaptacyjnych, które są rozpowszechnianych za pomocą sieci dystrybucji treści (CDN), zdarzają się przypadki Dzięki tym protokołom sieci CDN mogą działać znacznie efektywniej. Z tego powodu obsługa przez HttpEngine i Cronet protokołów HTTP/2 i HTTP/3 w ramach QUIC (oraz obsługa HTTP/2 przez OkHttp) jest dużą zaletą w porównaniu z korzystaniem z wbudowanego modułu sieciowego Androida, pod warunkiem że serwery, na których hostowane są treści, również obsługują te protokoły.

Jeśli rozważasz oddzielne strumieniowanie multimediów, zalecamy użycie biblioteki HttpEngine lub Cronet świadczony przez Usługi Google Play (od DefaultHttpDataSource) jeśli Usługi Google Play są niedostępne. Ta rekomendacja jest bardzo dobra równowagi między włączeniem obsługi HTTP/2 i HTTP/3 przez QUIC na większości urządzeń oraz aby uniknąć znacznego zwiększenia rozmiaru pliku APK. Istnieją wyjątki od tej reguły. zalecenie. Gdy Usługi Google Play mogą być niedostępne na znacznej części urządzeń, na których będzie działać Twoja aplikacja, bardziej odpowiednie może być użycie aplikacji Cronet Embedded lub OkHttp. Korzystanie z wbudowanego modułu sieciowego może być dopuszczalne, jeśli rozmiar pliku APK jest kluczową kwestią lub jeśli przesyłanie strumieniowe multimediów stanowi tylko niewielką część funkcjonalności aplikacji.

Oprócz multimediów warto wybrać jeden zestaw funkcji sieciowych do wszystkich operacji sieciowych wykonywanych przez aplikację. Dzięki temu zasoby (np. gniazda) mogą być efektywnie łączone i udostępniane przez ExoPlayera i inne komponenty aplikacji.

Ponieważ aplikacja najprawdopodobniej będzie musiała wykonywać czynności sieciowe niezwiązane z siecią. podczas odtwarzania multimediów, wybrany stos sieciowy powinien wziąć pod uwagę powyżej zaleceń dotyczących niezależnego strumieniowania multimediów, inne elementy obsługujące sieci oraz ich znaczenie w stosunku do Twojej .

Buforowanie multimediów

ExoPlayer obsługuje buforowanie załadowanych bajtów na dysku, aby zapobiec wielokrotnemu wczytywaniu tych samych bajtów z sieci. Jest to przydatne, gdy chcesz cofnąć się w bieżących mediach lub powtórzyć dany element.

Buforowanie wymaga, aby instancja SimpleCache wskazywała dedykowaną pamięć podręczną i 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();