תמונות

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

הגדרת קובצי מדיה לטעינה חיצונית

כדי להשתמש בנתיבי הקוד של ספריית טעינת התמונות, צריך להגדיר במפורש את סוג ה-MIME של APPLICATION_EXTERNALLY_LOADED_IMAGE ב-MediaItem שנוסף ל-Player:

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

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

כדי לאחזר את ה-Bitmap מה-Uri, כלי הרינדור של התמונות צריך ExternallyLoadedImageDecoder. אפשר לספק את המפענח הזה על ידי שינוי של 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 כדי להפעיל את הטעינה מראש. אם לא ניתן או לא נדרש טעינה מראש, עדיין צריך לספק את ה-loader הזה, אבל הוא לא יכול לעשות כלום.

בדוגמה הבאה נעשה שימוש ב-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();