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ợ một nhóm định dạng khác.

Định dạng hình ảnh Được hỗ trợ 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 hỗ trợ 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ỉ được giải mã 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 một tệp độc lập.

Sử dụng MediaItem

Để phát một hình ảnh trong danh sách phát, hãy tạo một MediaItem bằng URI hình ảnh và truyền URI đó đến trình phát. MediaItem phải có imageDurationMs để chỉ định thời gian 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à những tệp kết hợp một ảnh tĩnh với một video ngắn.

  • Nếu thời lượng của hình ảnh được xác định bằng setImageDuration, thì ảnh chuyển độ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 của hình ảnh không xác định, ảnh chuyển động sẽ được phát dưới dạng video.

Sử dụng ProgressiveMediaSource

Để có thêm các lựa chọn tuỳ chỉnh, bạn có thể tạo một ProgressiveMediaSource và truyền trực tiếp đến trình phát 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 cho phù hợp với nhu cầu của ứng dụng. Hãy xem trang Tuỳ chỉnh để tham khảo các 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, chẳng hạn như Glide hoặc Coil.

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

  1. Xác định MediaItem bằng loại MIME APPLICATION_EXTERNALLY_LOADED_IMAGE.
  2. Cung cấp một bộ giải mã hình ảnh để truy xuất Bitmap từ thư viện tải hình ảnh.
  3. Cung cấp một 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 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 các đườ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 bằng thư viện tải hình ảnh

Trình kết xuất hình ảnh cần có một 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 một hình ảnh, giới hạn đầu ra ở kích thước màn hình để tránh tạo các đối tượng Bitmap có kích thước rất lớn:

Kotlin

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

Java

ImageDecoder.Factory glideImageDecoderFactory =
    new ExternallyLoadedImageDecoder.Factory(
        request -> {
          Point displaySize = Util.getCurrentDisplayModeSize(context);
          return GlideFutures.submit(
            Glide.with(context)
                .asBitmap()
                .load(request.uri)
                .override(max(displaySize.x, displaySize.y)));
            });
Player player =
    new ExoPlayer.Builder(context)
        .setRenderersFactory(
            new DefaultRenderersFactory(context) {
              @Override
              protected ImageDecoder.Factory getImageDecoderFactory(Context context) {
                return glideImageDecoderFactory;
              }
            })
        .build();

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

Trong quá trình 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 một thư viện tải hình ảnh bên ngoài, bạn phải chỉ định một ExternalLoader để kích hoạt quá trình 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 cần làm gì cả.

Ví dụ sau đây sử dụng Glide để đảm bảo rằng 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)
  )
}
val player =
    ExoPlayer.Builder(context)
      .setMediaSourceFactory(DefaultMediaSourceFactory(context)
        .setExternalImageLoader(glidePreloader))
      .build()

Java

ExternalLoader glidePreloader =
    request ->
        GlideFutures.submit(
            Glide.with(context)
                .asFile()
                .apply(
                    diskCacheStrategyOf(DiskCacheStrategy.DATA)
                        .priority(Priority.HIGH)
                        .skipMemoryCache(true))
                .load(request.uri));
Player player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(new DefaultMediaSourceFactory(context)
            .setExternalImageLoader(glidePreloader))
        .build();