תמונות

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

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

הפעלת תמונות בפלייליסט

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

Kotlin

// Create a data source factory.
val dataSourceFactory: DataSource.Factory = 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 שנוסף ל-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: 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();