Ngăn xếp mạng

ExoPlayer thường được sử dụng để phát trực tuyến nội dung đa phương tiện qua Internet. Chiến dịch này hỗ trợ nhiều ngăn xếp mạng để tạo các yêu cầu mạng cơ bản. Lựa chọn của bạn bộ phần cứng và phần mềm mạng có thể có tác động đáng kể đến hiệu suất truyền trực tuyến.

Trang này trình bày cách định cấu hình ExoPlayer để sử dụng ngăn xếp mạng của lựa chọn, liệt kê các tuỳ chọn có sẵn, cung cấp một số hướng dẫn về cách chọn ngăn xếp mạng cho ứng dụng và giải thích cách bật chức năng lưu vào bộ nhớ đệm cho lượt phát trực tuyến nội dung đa phương tiện.

Định cấu hình ExoPlayer để sử dụng ngăn xếp mạng cụ thể

ExoPlayer tải dữ liệu thông qua các thành phần DataSource mà lấy từ các thành phần này Các thực thể DataSource.Factory được chèn từ mã ứng dụng.

Nếu ứng dụng của bạn chỉ cần phát nội dung http, hãy chọn một mạng ngăn xếp chỉ đơn giản như việc cập nhật bất kỳ thực thể DataSource.Factory nào mà ứng dụng chèn làm thực thể của HttpDataSource.Factory tương ứng với ngăn xếp mạng mà bạn muốn sử dụng. Nếu ứng dụng của bạn cũng cần phát nội dung không phải http, chẳng hạn như các tệp cục bộ, sử dụng DefaultDataSource.Factory:

Kotlin

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

Java

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

Trong ví dụ này, PreferredHttpDataSource.Factory là trạng thái ban đầu tương ứng với ngăn xếp mạng ưu tiên. Lớp DefaultDataSource.Factory bổ sung chức năng hỗ trợ cho(các) nguồn không phải http, chẳng hạn như tệp cục bộ.

Ví dụ sau cho thấy cách tạo ExoPlayer sẽ sử dụng Cronet ngăn xếp mạng và cũng hỗ trợ phát nội dung không phải 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();

Ngăn xếp mạng được hỗ trợ

ExoPlayer cung cấp tính năng hỗ trợ trực tiếp cho HttpEngine, Cronet, OkHttp và Android ngăn xếp mạng mặc định tích hợp sẵn. ExoPlayer cũng có thể được mở rộng để hỗ trợ bất kỳ ngăn xếp mạng khác hoạt động trên Android.

HttpEngine

HttpEngine là ngăn xếp mạng mặc định được đề xuất cho Android từ API 34 (hoặc S) tiện ích 7). Trong hầu hết các trường hợp, nó sử dụng ngăn xếp mạng Cronet nội bộ, hỗ trợ HTTP, HTTP/2 và HTTP/3 qua giao thức QUIC.

ExoPlayer hỗ trợ HttpEngine bằng HttpEngineDataSource.Factory. Bạn có thể chèn nguồn dữ liệu này như mô tả trong Định cấu hình ExoPlayer để sử dụng ngăn xếp mạng cụ thể.

Cronet

Cronet là Ngăn xếp mạng Chromium được cung cấp cho ứng dụng Android dưới dạng thư viện. Cronet sử dụng tận dụng nhiều công nghệ để giảm độ trễ và tăng thời gian thông lượng yêu cầu mạng mà ứng dụng của bạn cần để hoạt động, bao gồm cả những yêu cầu đó do ExoPlayer tạo. Nó vốn hỗ trợ HTTP, HTTP/2 và HTTP/3 qua QUIC giao thức. Một số ứng dụng truyền trực tuyến lớn nhất trên thế giới sử dụng Cronet. bao gồm cả YouTube.

ExoPlayer hỗ trợ Cronet qua Thư việnCronet. Hãy xem README.md của thư viện để biết hướng dẫn chi tiết về cách sử dụng nó. Lưu ý rằng thư viện Cronet có thể sử dụng ba Cronet cơ bản cách triển khai:

  1. Dịch vụ Google Play: Bạn nên sử dụng cách triển khai này trong hầu hết trường hợp và quay lại ngăn xếp mạng tích hợp sẵn của Android (DefaultHttpDataSource) nếu không có Dịch vụ Google Play.
  2. Cronet Embedded: Có thể là lựa chọn phù hợp nếu phần lớn người dùng của bạn ở những thị trường nơi Dịch vụ Google Play không được cung cấp rộng rãi hoặc nếu bạn muốn kiểm soát phiên bản chính xác của việc triển khai Cronet đang được sử dụng. Chiến lược phát hành đĩa đơn Nhược điểm lớn của Cronet Embedded là nó sẽ thêm khoảng 8 MB vào ứng dụng của bạn.
  3. Tính năng dự phòng của Chromium: Hoạt động triển khai dự phòng của Cronet sẽ thực hiện API của Cronet đóng vai trò là một trình bao bọc xung quanh ngăn xếp mạng tích hợp sẵn của Android. Phải không được sử dụng với ExoPlayer, vì việc sử dụng ngăn xếp mạng tích hợp sẵn của Android trực tiếp (bằng cách sử dụng DefaultHttpDataSource) sẽ hiệu quả hơn.

OkHttp

OkHttp là một hệ thống mạng hiện đại khác được nhiều ứng dụng Android phổ biến sử dụng. Giao thức này hỗ trợ HTTP và HTTP/2, nhưng chưa hỗ trợ HTTP/3 qua QUIC.

ExoPlayer hỗ trợ OkHttp thông qua Thư viện OkHttp. Hãy xem README.md của thư viện để biết hướng dẫn chi tiết về cách sử dụng nó. Khi dùng thư viện OkHttp, ngăn xếp mạng được nhúng trong . Điều này tương tự như Cronet Embedded, tuy nhiên OkHttp rất đáng kể nhỏ hơn, thêm dưới 1MB vào ứng dụng của bạn.

Ngăn xếp mạng tích hợp sẵn của Android

ExoPlayer hỗ trợ việc sử dụng ngăn xếp mạng tích hợp sẵn của Android với DefaultHttpDataSourceDefaultHttpDataSource.Factory, đều thuộc thư viện ExoPlayer chính.

Việc triển khai ngăn xếp mạng chính xác phụ thuộc vào phần mềm chạy trên thiết bị cơ bản. Trên hầu hết các thiết bị, chỉ HTTP được hỗ trợ (tức là HTTP/2 và HTTP/3 qua QUIC không được hỗ trợ).

Ngăn xếp mạng khác

Ứng dụng cũng có thể tích hợp các ngăn xếp mạng khác với ExoPlayer. Để thực hiện việc này, hãy triển khai HttpDataSource bao bọc ngăn xếp mạng, cùng với HttpDataSource.Factory tương ứng. Cronet của ExoPlayer và Thư viện OkHttp là những ví dụ hay về cách thực hiện việc này.

Khi tích hợp với ngăn xếp mạng Java thuần tuý, bạn nên triển khai một DataSourceContractTest để kiểm tra nhằm đảm bảo rằng việc triển khai HttpDataSource của bạn hoạt động chính xác. OkHttpDataSourceContractTest trong thư viện OkHttp là một ví dụ điển hình về cách làm việc này.

Chọn ngăn xếp mạng

Bảng sau đây trình bày các ưu và nhược điểm của các ngăn xếp mạng được hỗ trợ bởi ExoPlayer.

Bộ phần cứng và phần mềm mạng Giao thức Tác động đối với kích thước tệp APK Ghi chú
HttpEngine HTTP
HTTP/2
HTTP/3 qua QUIC
Không có Chỉ có trên API 34 hoặc Tiện ích S 7
Cronet (Dịch vụ Google Play) HTTP
HTTP/2
HTTP/3 qua QUIC
Nhỏ
(<100KB)
Cần có Dịch vụ Google Play. Phiên bản Cronet đã tự động được cập nhật
Cronet (Được nhúng) HTTP
HTTP/2
HTTP/3 qua QUIC
Lớn
(~8MB)
Phiên bản Cronet do nhà phát triển ứng dụng kiểm soát
Cronet (Dự phòng) HTTP
(khác nhau tuỳ theo thiết bị)
Nhỏ
(<100KB)
Không nên dùng cho ExoPlayer
OkHttp HTTP
HTTP/2
Nhỏ
(<1MB)
Ngăn xếp mạng tích hợp HTTP
(khác nhau tuỳ theo thiết bị)
Không có Cách triển khai sẽ khác nhau tuỳ theo thiết bị

Các giao thức HTTP/2 và HTTP/3 qua QUIC có thể cải thiện đáng kể hoạt động truyền thông hiệu suất phát trực tuyến. Đặc biệt, khi truyền trực tuyến nội dung nghe nhìn thích ứng được phân phối bằng mạng phân phối nội dung (CDN), có trường hợp việc sử dụng các giao thức này có thể cho phép CDN hoạt động hiệu quả hơn nhiều. Vì lý do này, sự hỗ trợ của HttpEngine và Cronet cho cả HTTP/2 và HTTP/3 qua QUIC (và hỗ trợ của OkHttp cho HTTP/2), là một lợi ích lớn so với sử dụng ngăn xếp mạng tích hợp sẵn của Android, miễn là các máy chủ mà nội dung được lưu trữ cũng hỗ trợ các giao thức này.

Khi cân nhắc việc phát trực tuyến nội dung nghe nhìn một cách riêng biệt, bạn nên sử dụng HttpEngine hoặc Cronet do Dịch vụ Google Play cung cấp trở lại DefaultHttpDataSource nếu Dịch vụ Google Play không hoạt động. Đề xuất này tạo ra trải nghiệm tốt cân bằng giữa việc bật HTTP/2 và HTTP/3 qua QUIC trên hầu hết các thiết bị và tránh việc tăng đáng kể kích thước APK. Có những ngoại lệ đối với quy trình này đề xuất. Đối với các trường hợp mà Dịch vụ Google Play có khả năng không dùng được trên một phần đáng kể các thiết bị sẽ chạy ứng dụng của bạn, việc sử dụng Cronet Embedded hoặc OkHttp có thể phù hợp hơn. Việc sử dụng tính năng tích hợp sẵn bộ phần cứng và phần mềm mạng có thể được chấp nhận nếu kích thước APK là một vấn đề quan trọng, hoặc nếu nội dung đa phương tiện truyền trực tuyến chỉ là một phần nhỏ trong chức năng của ứng dụng.

Ngoài phương tiện truyền thông, thông thường bạn nên chọn một ngăn xếp mạng duy nhất cho toàn bộ hoạt động kết nối mạng do ứng dụng của bạn thực hiện. Việc này cho phép các tài nguyên (chẳng hạn như cổng) được gộp lại và chia sẻ một cách hiệu quả giữa ExoPlayer và các thành phần ứng dụng.

Vì ứng dụng của bạn rất có thể cần thực hiện các hoạt động kết nối mạng không liên quan đối với phát lại nội dung đa phương tiện, lựa chọn ngăn xếp mạng của bạn cuối cùng sẽ ảnh hưởng đến đề xuất nêu trên để phát trực tuyến nội dung đa phương tiện một cách riêng biệt, đáp ứng yêu cầu của bất kỳ các thành phần khác thực hiện nhiệm vụ kết nối mạng và tầm quan trọng tương đối của chúng đối với .

Lưu nội dung nghe nhìn vào bộ nhớ đệm

ExoPlayer hỗ trợ lưu các byte đã tải vào bộ nhớ đệm vào đĩa để ngăn việc tải nhiều lần cùng một byte từ mạng. Điều này rất hữu ích khi tua lại trong dòng thời gian nội dung nghe nhìn hoặc lặp lại cùng một mục.

Việc lưu vào bộ nhớ đệm cần có một thực thể SimpleCache trỏ đến một bộ nhớ đệm chuyên dụng và một 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();