יצירה והגדרה של DefaultPreloadManager

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

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

יש שלושה שלבים ליצירת מופע של DefaultPreloadManager:

  • מגדירים TargetPreloadStatusControl שמנהל הטעינה מראש יכול לשלוח אליו שאילתה כדי לבדוק אם קובץ המדיה מוכן לטעינה וכמה ממנו צריך לטעון.
  • יוצרים את ה-builder שבאמצעותו יוצרים את מנהל הטעינה מראש ואת האובייקטים של ExoPlayer באפליקציה.
  • משתמשים ב-builder כדי ליצור את מנהל הטעינה מראש על ידי קריאה ל-method‏ build() של ה-builder.

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

כשיוצרים את DefaultPreloadManager.Builder, מעבירים אליו אובייקט target preload status control שאתם מגדירים. האובייקט הזה מטמיע את הממשק TargetPreloadStatusControl. כשהמנהל של הטעינה מראש מתכונן לטעון מראש מדיה, הוא קורא ל-method‏ getTargetPreloadStatus() של בקרת הסטטוס כדי לקבוע אם להכין, לטעון או לשמור במטמון תוכן של פריט מדיה. טעינה מראש טוענת את נתוני המדיה ישירות למאגר הנתונים הזמני בזיכרון של הנגן, כך שהם מוכנים להפעלה מיידית. לעומת זאת, שמירה במטמון שומרת את נתוני המדיה במטמון דיסק קבוע כדי לחסוך בזיכרון של הנגן. פקד הסטטוס יכול להשיב עם אחד מקודי הסטטוס הבאים:

  • ‫STAGE_SPECIFIED_RANGE_LOADED: מנהל הטעינה מראש צריך לטעון את התוכן ממיקום ההתחלה שצוין ולמשך הזמן שצוין (באלפיות השנייה) למאגר הנתונים הזמני בזיכרון של הנגן.
  • ‫STAGE_SPECIFIED_RANGE_CACHED: מנהל הטעינה מראש צריך לשמור במטמון הדיסק את התוכן ממיקום ההתחלה שצוין ולמשך הזמן שצוין (באלפיות השנייה).
  • ‫STAGE_TRACKS_SELECTED: מנהל הטעינה מראש צריך לטעון ולעבד את המידע של טראק התוכן, ולבחור את הטראקים. מנהל הטעינה מראש לא אמור להתחיל לטעון את התוכן עדיין.
  • ‫STAGE_SOURCE_PREPARED: מנהל הטעינה מראש צריך להכין את מקור התוכן. לדוגמה, אם המטא-נתונים של התוכן נמצאים בקובץ מניפסט נפרד, מנהל הטעינה מראש יכול לאחזר ולנתח את המניפסט הזה.
  • ‫null: מנהל הטעינה מראש לא אמור לטעון תוכן או מטא-נתונים של קובץ המדיה הזה.

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

  • אינדקס n+1 (קובץ המדיה הבא): טעינה של 3,000 אלפיות השנייה (3 שניות) ממיקום ברירת המחדל של ההתחלה
  • אינדקס n-1 (קובץ המדיה הקודם): טעינה של 1,000 אלפיות השנייה (שנייה אחת) ממיקום ההתחלה שמוגדר כברירת מחדל
  • קובצי מדיה אחרים בטווח n-2 עד n+2: החזרה PreloadStatus.TRACKS_SELECTED
  • קובצי מדיה אחרים בטווח n-4 עד n+4: החזרה PreloadStatus.SOURCE_PREPARED
  • לגבי כל שאר קובצי המדיה, מחזירים את הערך null

class MyTargetPreloadStatusControl(var currentPlayingIndex: Int = 0) :
  TargetPreloadStatusControl<Int, DefaultPreloadManager.PreloadStatus> {

  override fun getTargetPreloadStatus(index: Int): DefaultPreloadManager.PreloadStatus {
    if (index - currentPlayingIndex == 1) { // next track
      // return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and
      // suggest loading 3000ms from the default start position
      return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L)
    } else if (index - currentPlayingIndex == -1) { // previous track
      // return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and
      // suggest loading 3000ms from the default start position
      return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L)
    } else if (abs(index - currentPlayingIndex) == 2) {
      // return a PreloadStatus that is labelled by STAGE_TRACKS_SELECTED
      return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_TRACKS_SELECTED
    } else if (abs(index - currentPlayingIndex) <= 4) {
      // return a PreloadStatus that is labelled by STAGE_SOURCE_PREPARED
      return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_SOURCE_PREPARED
    }
    return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_NOT_PRELOADED
  }
}

מידע חשוב על הקוד

  • כשיוצרים את ה-preload manager builder, צריך להעביר אליו מופע של MyTargetPreloadStatusControl.
  • המשתנה currentPlayingIndex מכיל את האינדקס של קובץ המדיה שמופעל כרגע. האפליקציה צריכה לעדכן את הערך הזה.
  • כשהמנהל של הטעינה מראש מוכן לטעון תוכן, הוא קורא ל-getTargetPreloadStatus ומעביר את פרטי הדירוג שציינתם לגבי קובץ המדיה המתאים. במקרה של DefaultPreloadManager, פרטי הדירוג הם מספר שלם שמציין את מיקום הפריט בקרוסלה. השיטה בוחרת איזה קוד להחזיר על ידי השוואה בין האינדקס הזה לבין האינדקס של הפריט שנבחר כרגע.

יצירת מנהל הטעינה מראש

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

val targetPreloadStatusControl = MyTargetPreloadStatusControl()
val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
val preloadManager = preloadManagerBuilder.build()

ה-builder גם מספק שיטות setter שבהן אפשר להשתמש כדי להגדיר את הרכיבים בהתאמה אישית של מנהל הטעינה מראש.

לדוגמה, אתם יכולים להתאים אישית את היעד של סך כל בייטים במאגר הנתונים הזמני לכל מקורות המדיה שנטענים מראש ב-DefaultPreloadManager, כדי שהנתונים שנטענים מראש לא יחרגו מהמגבלה הזו. אפשר להגדיר את המגבלה הזו באמצעות setPlayerTargetBufferBytes(String, int) ב-DefaultLoadControl.Builder בהתאמה אישית עם שם הנגן "preload", ולהעביר את המכונה הזו ל-preload manager builder:

val targetPreloadStatusControl = MyTargetPreloadStatusControl()
val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl)

preloadManagerBuilder.setLoadControl(
  DefaultLoadControl.Builder()
    .setPlayerTargetBufferBytes("preload", 128 * 1024 * 1024) // 128 MiB
    .build()
)
val preloadManager = preloadManagerBuilder.build()

ה-setter methods של ה-builder הן אופציונליות להתאמה אישית, אבל אם רוצים לשמור במטמון פריטי מדיה בדיסק, צריך להגדיר את ה-builder עם Cache באמצעות קריאה ל-setCache(). אם לא מוגדר מטמון, ניסיון לשמור במטמון את קובצי המדיה יוביל לשגיאה IllegalStateException.

יוצרים את ExoPlayer כדי להפעיל את קובץ המדיה שנטען מראש

בנוסף לשימוש בכלי ליצירת מנהל הטעינה מראש, תשתמשו בו גם כדי ליצור את האובייקטים מסוג ExoPlayer שבהם האפליקציה משתמשת כדי להפעיל את התוכן, כך שה-ExoPlayer ישתף רכיבים בצורה נכונה עם מנהל הטעינה מראש. עדיין אפשר לקבוע את ההגדרות הספציפיות להפעלה של ExoPlayer על ידי העברת מופע של ExoPlayer.Builder עם ההגדרות האלה.

// Direct creation
val exoPlayer = preloadManagerBuilder.buildExoPlayer()

// Creation with custom playback specific configurations
val skipSilenceExoPlayerBuilder = ExoPlayer.Builder(context).setSkipSilenceEnabled(true)
val skipSilenceExoPlayer = preloadManagerBuilder.buildExoPlayer(skipSilenceExoPlayerBuilder)