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:
- Zdefiniuj
MediaItemz typem MIMEAPPLICATION_EXTERNALLY_LOADED_IMAGE. - Podaj dekoder obrazu, aby pobrać
Bitmapz biblioteki wczytywania obrazów. - 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();