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:
- 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
). - 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.
- 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();