Netzwerkstacks

ExoPlayer wird häufig zum Streamen von Medien über das Internet verwendet. Unterstützt mehrere Netzwerkstacks zum Senden der zugrunde liegenden Netzwerkanfragen erstellen. Sie haben die Wahl. des Netzwerk-Stacks kann sich erheblich auf die Streamingleistung auswirken.

Auf dieser Seite wird beschrieben, wie Sie ExoPlayer für die Verwendung Ihres Netzwerkstapels von Auswahl, listet die verfügbaren Optionen auf, bietet einige Hinweise zur Auswahl einen Netzwerk-Stack für Ihre App. Außerdem wird erläutert, wie Sie Caching für gestreamte Medien.

ExoPlayer für die Verwendung eines bestimmten Netzwerkstacks konfigurieren

ExoPlayer lädt Daten über DataSource-Komponenten, die sie von DataSource.Factory-Instanzen, die aus dem App-Code eingeschleust werden.

Wenn Ihre App nur HTTP(S)-Inhalte wiedergeben muss, wählen Sie ein Netzwerk aus. Stack ist so einfach wie das Aktualisieren aller DataSource.Factory-Instanzen, App wird als Instanzen von HttpDataSource.Factory eingefügt das dem Netzwerk-Stack entspricht, das Sie verwenden möchten. Wenn Ihre App auch Nicht-HTTP-Inhalte wie lokale Dateien abspielen müssen, verwenden Sie DefaultDataSource.Factory:

Kotlin

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

Java

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

In diesem Beispiel ist PreferredHttpDataSource.Factory die Factory, die Ihrem bevorzugten Netzwerk-Stack an. Die Ebene DefaultDataSource.Factory wird unterstützt für Nicht-HTTP(S)-Quellen wie lokale Dateien.

Das folgende Beispiel zeigt, wie ein ExoPlayer erstellt wird, der das Cronet-Modell verwendet und die Wiedergabe von Nicht-HTTP-Inhalten unterstützen.

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

Unterstützte Netzwerkstacks

ExoPlayer bietet direkte Unterstützung für HttpEngine, Cronet, OkHttp und die Standard-Netzwerk-Stack integriert. ExoPlayer kann auch so erweitert werden, anderen Netzwerk-Stacks unter Android.

HttpEngine

HttpEngine ist der empfohlene Standardnetzwerk-Stack unter Android ab API 34 (oder S Erweiterungen 7). Meistens wird der Cronet-Netzwerkstack intern verwendet, die Protokolle HTTP, HTTP/2 und HTTP/3 über QUIC unterstützen.

ExoPlayer unterstützt HttpEngine mit der zugehörigen HttpEngineDataSource.Factory. Sie können Fügen Sie diese Datenquellen-Factory wie unter ExoPlayer für die Verwendung eines eines bestimmten Netzwerk-Stacks.

Cronett

Cronet ist das Chromium-Netzwerkstack, der Android-Apps als Bibliothek zur Verfügung gestellt wird. Cronet nimmt der Vorteile mehrerer Technologien, die die Latenz reduzieren und Durchsatz der Netzwerkanfragen, die Ihre Anwendung verarbeiten muss, einschließlich derjenigen, von ExoPlayer entwickelt. Nativ unterstützt HTTP, HTTP/2 und HTTP/3 über QUIC Protokolle. Cronet wird von einigen der weltweit größten Streaming-Apps verwendet, einschließlich YouTube.

ExoPlayer unterstützt Cronet über seine Cronet-Bibliothek Eine ausführliche Anleitung zur Verwendung findest du in der README.md der Bibliothek . Beachten Sie, dass die Cronet-Bibliothek drei zugrunde liegende Cronet- Implementierungen:

  1. Google Play-Dienste:Wir empfehlen diese Implementierung in den meisten und auf den integrierten Android-Netzwerkstack zurückgreifen, (DefaultHttpDataSource) wenn die Google Play-Dienste nicht verfügbar sind.
  2. Eingebettetes Cronett:Diese Option eignet sich gut, wenn ein großer Prozentsatz Ihrer Nutzer sich in Märkten befinden, in denen die Google Play-Dienste nicht allgemein verfügbar sind, oder wenn Sie die genaue Version der verwendeten Cronet-Implementierung steuern möchten. Die Der große Nachteil von Cronet Embedded besteht darin, dass es für Ihre App.
  3. Cronet-Fallback:Die Fallback-Implementierung von Cronet implementiert Cronet-API als Wrapper für den integrierten Android-Netzwerkstack Er sollte nicht mit ExoPlayer verwendet werden, da der integrierte Android-Netzwerkstack verwendet wird direkt (über DefaultHttpDataSource) ist effizienter.

OkHttp

OkHttp ist ein weiterer moderner Netzwerk-Stack, wird von vielen beliebten Android-Apps verwendet. Es unterstützt HTTP- und HTTP/2, unterstützt jedoch noch kein HTTP/3 über QUIC.

ExoPlayer unterstützt OkHttp über OkHttp-Bibliothek. Eine ausführliche Anleitung zur Verwendung findest du in der README.md der Bibliothek . Bei Verwendung der OkHttp-Bibliothek wird der Netzwerkstack in die Dies ähnelt Cronet Embedded, OkHttp ist jedoch erheblich kleiner als 1 MB zu Ihrer App hinzufügen.

Integrierter Android-Netzwerkstack

ExoPlayer unterstützt die Verwendung des integrierten Android-Netzwerkstacks mit DefaultHttpDataSource und DefaultHttpDataSource.Factory, die Teil von der ExoPlayer-Kernbibliothek.

Die genaue Implementierung des Netzwerk-Stacks hängt von der Software ab, die auf dem zugrunde liegendes Gerät. Auf den meisten Geräten wird nur HTTP unterstützt, d. h. HTTP/2 und HTTP/3 über QUIC werden nicht unterstützt.

Andere Netzwerkstapel

Apps können auch andere Netzwerkstacks in ExoPlayer einbinden. Implementieren Sie dazu einen HttpDataSource, der den Netzwerkstack umschließt, zusammen mit einem entsprechenden HttpDataSource.Factory-Wert. Cronet und Cronet von ExoPlayer OkHttp-Bibliotheken sind gute Beispiele dafür.

Bei der Integration in einen reinen Java-Netzwerk-Stack empfiehlt es sich, eine DataSourceContractTest, um zu prüfen, ob Ihre HttpDataSource-Implementierung nicht ordnungsgemäß funktioniert. OkHttpDataSourceContractTest in der OkHttp-Bibliothek ist ein ein gutes Beispiel dafür.

Netzwerkstack auswählen

In der folgenden Tabelle sind die Vor- und Nachteile der von den ExoPlayer

Netzwerkstapel Protokolle Auswirkungen auf die APK-Größe Hinweise
HttpEngine HTTP
HTTP/2
HTTP/3 über QUIC
Keine Nur verfügbar für API 34 oder S Extensions 7
Cronet (Google Play-Dienste) HTTP
HTTP/2
HTTP/3 über QUIC
Klein
(< 100 KB)
Google Play-Dienste erforderlich. Cronet-Version wird automatisch aktualisiert
Cronet (eingebettet) HTTP
HTTP/2
HTTP/3 über QUIC
Groß
(~8 MB)
Vom App-Entwickler kontrollierte Cronet-Version
Cronet (Fallback) HTTP
(je nach Gerät)
Klein
(< 100 KB)
Nicht empfohlen für ExoPlayer
OkHttp HTTP
HTTP/2
Klein
(< 1 MB)
Integrierter Netzwerk-Stack HTTP
(je nach Gerät)
Keine Die Implementierung variiert je nach Gerät

Die Protokolle HTTP/2 und HTTP/3 im Vergleich zu QUIC können Medien erheblich verbessern. und Streaming-Leistung zu verbessern. Das gilt insbesondere beim Streamen adaptiver Medien, die über ein Content Distribution Network (CDN) verbreitet werden, mit denen CDNs viel effizienter arbeiten können. Aus diesem Grund unterstützen HttpEngine und Cronet sowohl HTTP/2 als auch HTTP/3 gegenüber QUIC (und der HTTP/2-Unterstützung von OkHttp) unter Verwendung des integrierten Android-Netzwerkstapels, vorausgesetzt, die Server, auf denen der gehosteten Content auch diese Protokolle unterstützen.

Wenn Sie Medien-Streaming isoliert betrachten, empfehlen wir die Verwendung von HttpEngine oder Von Google Play-Diensten bereitgestelltes Cronet verwendet DefaultHttpDataSource wenn die Google Play-Dienste nicht verfügbar sind. Diese Empfehlung ist gut zwischen der Aktivierung von HTTP/2 und HTTP/3 über QUIC auf den meisten Geräten wodurch eine deutliche Vergrößerung des APK vermieden wird. Hiervon ausgenommen sind Empfehlung. Wenn die Google Play-Dienste wahrscheinlich nicht verfügbar sind auf einem erheblichen Teil der Geräte, auf denen Ihre App ausgeführt wird, Cronet Embedded oder OkHttp kann geeigneter sein. Mit der integrierten Der Netzwerk-Stack kann akzeptabel sein, wenn die APK-Größe wichtig ist Streaming ist nur ein kleiner Teil der Funktionalität Ihrer App.

Neben den Medien empfiehlt es sich normalerweise, einen einzelnen Netzwerk-Stack zu wählen für das gesamte Netzwerk durch Ihre App. Dadurch können Ressourcen (z. B. Sockets) für ein effizientes Pooling und gemeinsame Nutzung zwischen ExoPlayer und anderen App-Komponenten.

Da Ihre App höchstwahrscheinlich ein Netzwerk ausführen muss, bei der Medienwiedergabe, sollte Ihre Wahl des Netzwerk-Stacks letztendlich unsere die oben genannten Empfehlungen für Medien-Streaming, die Anforderungen jedes einzelnen andere Komponenten, die Netzwerke nutzen, und deren relative Bedeutung für Ihre

Medien im Cache speichern

ExoPlayer unterstützt das Caching geladener Byte auf dem Laufwerk, um ein wiederholtes Laden zu verhindern dieselben Bytes aus dem Netzwerk entfernt. Dies ist nützlich, wenn Sie im aktuellen oder dasselbe Element wiederholen.

Für das Caching ist eine SimpleCache-Instanz erforderlich, die auf einen dedizierten Cache verweist Verzeichnis und ein 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();