Grafika

ExoPlayer obsługuje te formaty obrazów: Więcej informacji o integracji z bibliotekami zewnętrznymi, które mogą obsługiwać inny zestaw formatów, znajdziesz w artykule Biblioteki wczytywania obrazów.

Format obrazu Obsługiwane Uwagi
BMP TAK
GIF NIE Brak obsługi ekstraktora
JPEG TAK
Zdjęcie w ruchu JPEG TAK Obsługiwane są zdjęcia i filmy
JPEG Ultra HDR TAK W przypadku Androida starszego niż 14 lub wyświetlaczy bez HDR przełącza się na SDR.
PNG TAK
WebP TAK
HEIF/HEIC TAK
Zdjęcie ruchome HEIC Częściowo Obsługiwane są tylko obrazy statyczne*
AVIF (podstawowy) TAK Dekodowanie tylko na Androidzie 14 lub nowszym

* Część wideo zdjęć ruchomych w formacie HEIC można uzyskać za pomocą interfejsu MetadataRetriever i odtwarzać jako osobny plik.

Korzystanie z elementu MediaItem

Aby odtworzyć obraz w ramach playlisty, utwórz MediaItem z URI obrazu i przekaż go do odtwarzacza. Element MediaItem musi zawierać element imageDurationMs, który określa, jak długo obraz ma być wyświetlany.

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

Zdjęcia ruchome

Zdjęcia ruchome to pliki łączące nieruchomy obraz z krótkim filmem.

  • Jeśli czas trwania obrazu jest określony za pomocą setImageDuration, zdjęcie ruchome jest wyświetlane jako zdjęcie nieruchome przez zadeklarowany czas.
  • Jeśli czas trwania obrazu jest nieokreślony, zdjęcie ruchome jest odtwarzane jako film.

Korzystanie z ProgressiveMediaSource

Aby uzyskać więcej opcji dostosowywania, możesz utworzyć obiekt ProgressiveMediaSource i przekazać go bezpośrednio do odtwarzacza zamiast obiektu 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();

Dostosowywanie odtwarzania

ExoPlayer udostępnia wiele sposobów dostosowywania odtwarzania do potrzeb aplikacji. Przykłady znajdziesz na stronie Dostosowywanie.

Biblioteki wczytywania obrazów

Obrazy są często zarządzane przez zewnętrzne biblioteki wczytywania obrazów, np. Glide lub Coil.

Integracja tych bibliotek z potokiem odtwarzania wymaga wykonania 3 kroków:

  1. Zdefiniuj MediaItem z typem MIME APPLICATION_EXTERNALLY_LOADED_IMAGE.
  2. Podaj dekoder obrazu, aby pobrać Bitmap z biblioteki wczytywania obrazów.
  3. Udostępnij zewnętrzny moduł wczytujący, aby wywołać buforowanie i wstępne wczytywanie.

MediaItem z zewnętrznie załadowanym typem MIME obrazu

Element MediaItem dodany do elementu Player musi jawnie definiować typ MIME, aby używać ścieżek kodu biblioteki wczytywania obrazów:APPLICATION_EXTERNALLY_LOADED_IMAGE

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

Dekoder obrazu korzystający z biblioteki wczytywania obrazów

Renderowanie obrazu wymaga ExternallyLoadedImageDecoder, aby pobrać Bitmap z Uri. Ten dekoder można udostępnić, zastępując funkcję DefaultRenderersFactory.getImageDecoderFactory.

W tym przykładzie używamy biblioteki Glide do wczytywania obrazu, ograniczając rozmiar wyjściowy do rozmiaru wyświetlacza, aby uniknąć tworzenia bardzo dużych obiektów Bitmap:

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

Wstępne wczytywanie obrazów za pomocą biblioteki wczytywania obrazów

Podczas odtwarzania odtwarzacz wysyła żądanie wstępnego wczytania następnego obrazu po pełnym wczytaniu poprzedniego elementu na liście odtwarzania. Jeśli używasz zewnętrznej biblioteki wczytywania obrazów, musisz określić ExternalLoader, aby wywołać wstępne wczytywanie. Jeśli wstępne wczytywanie nie jest możliwe lub wymagane, ten moduł wczytujący nadal musi być dostępny, ale może nie robić nic.

W tym przykładzie używamy Glide, aby mieć pewność, że żądany obraz jest wstępnie wczytywany na dysk:

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