תמונות

‫ExoPlayer תומך בפורמטים הבאים של תמונות. במאמר בנושא ספריות לטעינת תמונות מוסבר איך לשלב ספריות חיצוניות שיכולות לספק תמיכה בקבוצה שונה של פורמטים.

פורמט תמונה נתמך פתקים
BMP כן
GIF לא אין תמיכה ב-Extractor
JPEG כן
תמונה בתנועה בפורמט JPEG כן תמונת סטילס וסרטון נתמכים
JPEG Ultra HDR כן ההמרה חוזרת ל-SDR בגרסאות קודמות ל-Android 14 או במסכים ללא HDR
PNG כן
WebP כן
HEIF/HEIC כן
תמונה עם תנועה בפורמט HEIC באופן חלקי יש תמיכה רק בתמונות סטילס*
AVIF (ערך בסיס) כן הפענוח מתבצע רק ב-Android מגרסה 14 ואילך

* אפשר להשיג את חלק הווידאו של תמונות-תנועה בפורמט HEIC באמצעות MetadataRetriever ולהפעיל אותו כקובץ עצמאי.

שימוש ב-MediaItem

כדי להפעיל תמונה כחלק מפליליסט, יוצרים MediaItem עם ה-URI של התמונה ומעבירים אותו לנגן. לתג MediaItem צריך להיות מאפיין imageDurationMs כדי לציין כמה זמן התמונה תוצג.

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

תמונות עם תנועה

תמונות עם תנועה הן קבצים שמשלבים תמונת סטילס עם סרטון קצר.

  • אם משך התמונה מוגדר באמצעות setImageDuration, התמונה עם התנועה מוצגת כסטילס למשך הזמן שהוגדר.
  • אם משך התמונה לא מוגדר, התמונה עם התנועה תופעל כסרטון.

שימוש ב-ProgressiveMediaSource

כדי לקבל אפשרויות נוספות להתאמה אישית, אפשר ליצור ProgressiveMediaSource ולהעביר אותו ישירות לנגן במקום 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();

התאמה אישית של ההפעלה

‫ExoPlayer מספק מספר דרכים להתאמת חוויית ההפעלה לצרכים של האפליקציה. דוגמאות אפשר למצוא בדף ההתאמה האישית.

ספריות לטעינת תמונות

לרוב, התמונות מנוהלות על ידי ספריות חיצוניות לטעינת תמונות, למשל Glide או Coil.

כדי לשלב את הספריות האלה בצינור ההפקה של הפעלת התוכן, צריך לבצע 3 שלבים:

  1. מגדירים MediaItem עם סוג MIME ‏APPLICATION_EXTERNALLY_LOADED_IMAGE.
  2. מספקים מפענח תמונות כדי לאחזר Bitmap מספריית טעינת התמונות.
  3. מספקים טוען חיצוני כדי להפעיל שמירה במטמון וטעינה מראש.

MediaItem עם סוג MIME של תמונה שנטענה חיצונית

ה-MediaItem שנוסף ל-Player צריך להגדיר את סוג ה-MIME ‏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();

פענוח תמונה באמצעות ספרייה לטעינת תמונות

מעבד התמונות צריך ExternallyLoadedImageDecoder כדי לאחזר את Bitmap מ-Uri. אפשר לספק את המפענח הזה על ידי החלפת DefaultRenderersFactory.getImageDecoderFactory.

בדוגמה הבאה נעשה שימוש ב-Glide כדי לטעון תמונה, והפלט מוגבל לגודל התצוגה כדי למנוע יצירה של אובייקטים גדולים מאוד של 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();

טעינה מראש של תמונות באמצעות ספרייה לטעינת תמונות

במהלך ההפעלה, הנגן מבקש לטעון מראש את התמונה הבאה אחרי שהפריט הקודם בפלייליסט נטען במלואו. כשמשתמשים בספרייה חיצונית לטעינת תמונות, צריך לציין ExternalLoader כדי להפעיל את הטעינה מראש. אם לא ניתן לבצע טעינה מראש או אם היא לא נדרשת, עדיין צריך לספק את טוען התוספים הזה, אבל הוא לא צריך לעשות כלום.

בדוגמה הבאה נעשה שימוש ב-Glide כדי לוודא שהתמונה המבוקשת נטענת מראש לדיסק:

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