Images

ExoPlayer hỗ trợ các định dạng hình ảnh sau. Hãy xem phần Thư viện tải hình ảnh để biết cách tích hợp với các thư viện bên ngoài có thể hỗ trợ nhiều định dạng.

Định dạng hình ảnh Có thể làm Ghi chú
BMP
GIF KHÔNG Không hỗ trợ Trình trích xuất
JPEG
Ảnh động JPEG Hỗ trợ ảnh tĩnh và video
JPEG Ultra HDR Quay lại SDR trước Android 14 hoặc trên màn hình không phải HDR
PNG
WebP
HEIF/HEIC
Ảnh chuyển động HEIC Một phần Chỉ hỗ trợ hình ảnh tĩnh*
AVIF (cơ sở) Chỉ giải mã được trên Android 14 trở lên

* Bạn có thể lấy phần video của ảnh động HEIC bằng MetadataRetriever và phát dưới dạng tệp độc lập.

Sử dụng MediaItem

Để phát hình ảnh trong danh sách phát, hãy tạo MediaItem bằng URI hình ảnh rồi truyền URI đó đến trình phát. MediaItem phải có imageDurationMs để chỉ định thời lượng hiển thị hình ảnh.

Kotlin

// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media item to be played with the desired duration.
player.setMediaItem(
    MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build())
// Prepare the player.
player.prepare()

Java

// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the media item to be played with the desired duration.
player.setMediaItem(
    new MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build());
// Prepare the player.
player.prepare();

Ảnh chuyển động

Ảnh chuyển động là tệp kết hợp ảnh tĩnh với video ngắn.

  • Nếu thời lượng hình ảnh được xác định bằng setImageDuration, thì ảnh động sẽ hiển thị dưới dạng ảnh tĩnh trong thời lượng đã khai báo.
  • Nếu thời lượng hình ảnh không được xác định, ảnh động sẽ được phát dưới dạng video.

Sử dụng ProgressiveMediaSource

Để có thêm các tuỳ chọn tuỳ chỉnh, bạn có thể tạo ProgressiveMediaSource và truyền trực tiếp ProgressiveMediaSource đó đến người chơi thay vì MediaItem.

Kotlin

// Create a data source factory.
val dataSourceFactory = DefaultHttpDataSource.Factory()
// Create a media item with the image URI and the desired duration.
val mediaItem =
    MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build()
// Create a progressive media source for this media item.
val mediaSource =
    ProgressiveMediaSource.Factory(dataSourceFactory)
        .createMediaSource(mediaItem)
// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media source to be played.
player.setMediaSource(mediaSource)
// Prepare the player.
player.prepare()

Java

// Create a data source factory.
DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory();
// Create a media item with the image URI and the desired duration.
MediaItem mediaItem =
    new MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build();
// Create a progressive media source for this media item.
MediaSource mediaSource =
    new ProgressiveMediaSource.Factory(dataSourceFactory)
        .createMediaSource(mediaItem);
// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the media source to be played.
player.setMediaSource(mediaSource);
// Prepare the player.
player.prepare();

Tuỳ chỉnh chế độ phát

ExoPlayer cung cấp nhiều cách để bạn điều chỉnh trải nghiệm phát sao cho phù hợp với nhu cầu của ứng dụng. Hãy xem trang Tuỳ chỉnh để tham khảo ví dụ.

Thư viện tải hình ảnh

Hình ảnh thường được quản lý bằng các thư viện tải hình ảnh bên ngoài, ví dụ: Glide hoặc Coil.

Bạn cần thực hiện 3 bước để tích hợp các thư viện này vào quy trình phát:

  1. Xác định MediaItem bằng loại MIME APPLICATION_EXTERNALLY_LOADED_IMAGE.
  2. Cung cấp bộ giải mã hình ảnh để truy xuất Bitmap từ thư viện tải hình ảnh.
  3. Cung cấp trình tải bên ngoài để kích hoạt tính năng lưu vào bộ nhớ đệm và tải trước.

MediaItem có loại MIME hình ảnh được tải từ bên ngoài

MediaItem được thêm vào Player phải xác định rõ loại MIME APPLICATION_EXTERNALLY_LOADED_IMAGE để sử dụng đường dẫn mã thư viện tải hình ảnh:

Kotlin

val mediaItem =
  MediaItem.Builder()
    .setUri(imageUri)
    .setMimeType(MimeTypes.APPLICATION_EXTERNALLY_LOADED_IMAGE)
    .build()

Java

MediaItem mediaItem =
    new MediaItem.Builder()
        .setUri(imageUri)
        .setMimeType(MimeTypes.APPLICATION_EXTERNALLY_LOADED_IMAGE)
        .build();

Trình giải mã hình ảnh sử dụng thư viện tải hình ảnh

Trình kết xuất hình ảnh cần có ExternallyLoadedImageDecoder để truy xuất Bitmap từ Uri. Bạn có thể cung cấp bộ giải mã này bằng cách ghi đè DefaultRenderersFactory.getImageDecoderFactory.

Ví dụ sau đây sử dụng Glide để tải hình ảnh:

Kotlin

val glideImageDecoderFactory: ImageDecoder.Factory =
  ExternallyLoadedImageDecoder.Factory { request: ExternalImageRequest ->
    GlideFutures.submit(Glide.with(context).asBitmap().load(request.uri))
  }
val player: Player =
  ExoPlayer.Builder(context)
    .setRenderersFactory(
      object : DefaultRenderersFactory(context) {
        override fun getImageDecoderFactory(): ImageDecoder.Factory {
          return glideImageDecoderFactory
        }
      }
    )
    .build()

Java

ImageDecoder.Factory glideImageDecoderFactory =
    new ExternallyLoadedImageDecoder.Factory(
        request -> GlideFutures.submit(
            Glide.with(context).asBitmap().load(request.uri)));
Player player =
    new ExoPlayer.Builder(context)
        .setRenderersFactory(
            new DefaultRenderersFactory(context) {
              @Override
              protected ImageDecoder.Factory getImageDecoderFactory() {
                return glideImageDecoderFactory;
              }
            })
        .build();

Tải trước hình ảnh bằng thư viện tải hình ảnh

Trong khi phát, trình phát sẽ yêu cầu tải trước hình ảnh tiếp theo sau khi mục trước đó trong danh sách phát đã tải xong. Khi sử dụng thư viện tải hình ảnh bên ngoài, bạn phải chỉ định ExternalLoader để kích hoạt tính năng tải trước này. Nếu không thể hoặc không cần tải trước, bạn vẫn cần cung cấp trình tải này nhưng không thể làm gì cả.

Ví dụ sau đây sử dụng Glide để đảm bảo hình ảnh được yêu cầu được tải trước vào ổ đĩa:

Kotlin

val glidePreloader = ExternalLoader { request: LoadRequest ->
  GlideFutures.submit(
    Glide.with(context)
      .asFile()
      .apply(
        RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.DATA)
          .priority(Priority.HIGH)
          .skipMemoryCache(true)
      )
      .load(request.uri)
  )
}

Java

ExternalLoader glidePreloader =
    request ->
        GlideFutures.submit(
            Glide.with(context)
                .asFile()
                .apply(
                    diskCacheStrategyOf(DiskCacheStrategy.DATA)
                        .priority(Priority.HIGH)
                        .skipMemoryCache(true))
                .load(request.uri));