מקבצים של רשתות

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

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

הגדרת ExoPlayer לשימוש במקבץ רשת ספציפי

ExoPlayer טוען נתונים באמצעות רכיבי DataSource, שאותם הוא מקבל מהם DataSource.Factory מכונות שהוחדרו מקוד האפליקציה.

אם האפליקציה צריכה להפעיל רק תוכן של http(ים), עליך לבחור רשת אתם יכולים פשוט לעדכן את כל המופעים של DataSource.Factory האפליקציה מחדירה למופעים של HttpDataSource.Factory שתואם לסטאק הרשת שבו רוצים להשתמש. אם האפליקציה גם צריך להפעיל תוכן שאינו http(s), כמו קבצים מקומיים, DefaultDataSource.Factory:

Kotlin

DefaultDataSource.Factory(
  ...
  /* baseDataSourceFactory= */ PreferredHttpDataSource.Factory(...))

Java

new DefaultDataSource.Factory(
    ...
    /* baseDataSourceFactory= */ new PreferredHttpDataSource.Factory(...));

בדוגמה הזו, PreferredHttpDataSource.Factory הוא המפעל שתואם מקבץ רשת מועדף. השכבה DefaultDataSource.Factory מוסיפה תמיכה עבור מקורות שאינם http(ים) כמו קבצים מקומיים.

בדוגמה הבאה אפשר לראות איך לפתח ExoPlayer שישתמש ב-Cronet מחסנית רשת ותומכות בהפעלה של תוכן שאינו http(s).

Kotlin

// Given a CronetEngine and Executor, build a CronetDataSource.Factory.
val cronetDataSourceFactory = CronetDataSource.Factory(cronetEngine, executor)

// Wrap the CronetDataSource.Factory in a DefaultDataSource.Factory, which adds
// in support for requesting data from other sources (such as files, resources,
// etc).
val dataSourceFactory =
  DefaultDataSource.Factory(context, /* baseDataSourceFactory= */ cronetDataSourceFactory)

// Inject the DefaultDataSource.Factory when creating the player.
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory)
    )
    .build()

Java

// Given a CronetEngine and Executor, build a CronetDataSource.Factory.
CronetDataSource.Factory cronetDataSourceFactory =
    new CronetDataSource.Factory(cronetEngine, executor);

// Wrap the CronetDataSource.Factory in a DefaultDataSource.Factory, which adds
// in support for requesting data from other sources (such as files, resources,
// etc).
DefaultDataSource.Factory dataSourceFactory =
    new DefaultDataSource.Factory(
        context, /* baseDataSourceFactory= */ cronetDataSourceFactory);

// Inject the DefaultDataSource.Factory when creating the player.
ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory))
        .build();

מחסניות רשת נתמכות

ExoPlayer מספקת תמיכה ישירה עבור HttpEngine , Cronet , OkHttp ו-Android סטאק רשת מובנה בברירת מחדל. אפשר גם להרחיב את ExoPlayer כדי שיתמוך בכל מחסנית רשת אחרת שפועלת ב-Android.

HttpEngine

HttpEngine היא מקבץ הרשת המומלץ כברירת מחדל ב-Android מ-API 34 (או S) תוספים 7). ברוב המקרים, הוא משתמש בסטאק רשת Cronet באופן פנימי, עם תמיכה בפרוטוקולים HTTP, HTTP/2 ו-HTTP/3 עם QUIC.

ExoPlayer תומך ב-HttpEngine עם HttpEngineDataSource.Factory שלו. אפשר להחדיר את המפעל של מקור הנתונים הזה, כפי שמתואר בהגדרת ExoPlayer לשימוש סטאק רשת ספציפי.

קרונט

Cronet הוא מחסנית רשת של Chromium זמינה לאפליקציות ל-Android כספרייה. טייקים ב-Cronet את היתרון של טכנולוגיות מרובות שמפחיתות את זמן האחזור ומגדילות את התפוקה של בקשות הרשת שהאפליקציה צריכה כדי לפעול, כולל שנוצר על ידי ExoPlayer. הוא תומך במקור ב-HTTP, HTTP/2 ו-HTTP/3 ב-QUIC ופרוטוקולים. Cronet משמש כמה מאפליקציות הסטרימינג הגדולות בעולם, כולל YouTube.

ExoPlayer תומך ב-Cronet דרך ספריית Cronet. הוראות מפורטות לשימוש זמינות בREADME.md של הספרייה את זה. שימו לב שספריית Cronet יכולה להשתמש בשלושה שימושים בסיסיים ב-Cronet יישומים:

  1. Google Play Services: מומלץ להשתמש בהטמעה הזו ברוב המקרים ואז לחזור לסטאק הרשת המובנה של Android (DefaultHttpDataSource) אם Google Play Services לא זמין.
  2. Cronet Embedded: יכול להיות אפשרות טובה אם אחוז גדול מהמשתמשים שלכם נמצאים בשווקים שבהם Google Play Services לא זמינה לכולם, או שרוצים לשלוט בגרסה המדויקת של הטמעת Cronet שבה משתמשים. החיסרון העיקרי של Cronet Embedded הוא שהיא מוסיפה כ-8MB באפליקציה שלך.
  3. Cronet Fallback: הטמעה חלופית של הטמעות Cronet. ה-API של Cronet משמש כ-wrapper במסגרת סטאק הרשת המובנה של Android. היא צריכה לא בשימוש עם ExoPlayer, כי נעשה שימוש בסטאק הרשת המובנה של Android באופן ישיר (באמצעות DefaultHttpDataSource) יעיל יותר.

OkHttp

OkHttp היא עוד סטאק רשת מודרני נמצא בשימוש נרחב באפליקציות פופולריות ל-Android. הוא תומך ב-HTTP וב- HTTP/2, אבל עדיין לא תומך ב-HTTP/3 ב-QUIC.

ExoPlayer תומך ב-OkHttp דרך ספריית OkHttp. הוראות מפורטות לשימוש זמינות בREADME.md של הספרייה את זה. כשמשתמשים בספריית OkHttp, מקבץ הרשת מוטמע בתוך אפליקציה. הדבר דומה ל-Cronet Embedded, עם זאת OkHttp משמעותי קטן יותר, ומוסיפים פחות מ-1MB לאפליקציה.

מקבץ הרשת של Android

ExoPlayer תומך בשימוש בסטאק הרשת המובנה של Android עם DefaultHttpDataSource ו-DefaultHttpDataSource.Factory, שהם חלק מ- את ספריית הליבה של ExoPlayer.

ההטמעה של מקבץ הרשת המדויק תלויה בתוכנה שפועלת של המכשיר הבסיסי. ברוב המכשירים יש תמיכה רק ב-HTTP (כלומר, אין תמיכה ב-HTTP/2 וב-HTTP/3 ב-QUIC).

ערימות רשת אחרות

אפליקציות יכולות גם לשלב מקבצים אחרים של רשתות עם ExoPlayer. כדי לעשות את זה, צריך להטמיע HttpDataSource שעוזר את מקבץ הרשת, יחד עם HttpDataSource.Factory תואם. ה-Cronet של ExoPlayer דוגמאות טובות לעשות זאת באמצעות ספריות OkHttp.

בשילוב עם סטאק רשת Java בלבד, כדאי ליישם DataSourceContractTest כדי לבדוק שההטמעה של HttpDataSource פועלת כראוי. OkHttpDataSourceContractTest בספריית OkHttp היא דוגמה טובה לאופן שבו עושים זאת.

בחירת ערימת רשת

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

מקבץ רשת פרוטוקולים ההשפעה של גודל ה-APK הערות
HttpEngine HTTP
HTTP/2
HTTP/3 over QUIC
ללא זמינה רק ב-API 34 או ב-S תוספי 7
Cronet (Google Play Services) HTTP
HTTP/2
HTTP/3 over QUIC
קטן
(<100KB)
נדרשים Google Play Services. גרסת Cronet עודכנה באופן אוטומטי
Cronet (מוטמע) HTTP
HTTP/2
HTTP/3 over QUIC
גדול
(כ-8MB)
גרסת Cronet נשלטת על ידי מפַתח אפליקציות
Cronet (חלופה) HTTP
(משתנה לפי מכשיר)
קטן
(<100KB)
לא מומלץ עבור ExoPlayer
OkHttp HTTP
HTTP/2
קטן
(<1MB)
סטאק רשת מובנה HTTP
(משתנה לפי מכשיר)
ללא ההטמעה משתנה בהתאם למכשיר

פרוטוקולים HTTP/2 ו-HTTP/3 ב-QUIC יכולים לשפר משמעותית את המדיה ביצועים בסטרימינג. בפרט, כאשר סטרימינג של מדיה דינמית מופצים באמצעות רשת להפצת תוכן (CDN), יש מקרים איזה שימוש בפרוטוקולים האלה יכול לאפשר לרשתות CDN לפעול ביעילות רבה יותר. לכן התמיכה של Httpengine ו-Cronet ב-HTTP/2 וב-HTTP/3 ב-QUIC (והתמיכה של OkHttp ב-HTTP/2), היא יתרון משמעותי בהשוואה באמצעות מחסנית הרשת המובנית של Android, שמספקת את השרתים שבהם תוכן מתארח גם תומך בפרוטוקולים אלה.

כאשר שוקלים להפעיל סטרימינג של מדיה באופן מבודד, מומלץ להשתמש ב-HttpEngine או Cronet סופק על ידי Google Play Services החל מ-DefaultHttpDataSource אם Google Play Services לא זמין. ההמלצה הזו נחשבת לטובה איזון בין הפעלת שימוש ב-HTTP/2 וב-HTTP/3 ב-QUIC ברוב המכשירים, וגם הימנעות מעלייה משמעותית בגודל ה-APK. יש חריגים לכלל הזה המלצה. במקרים שבהם כנראה ש-Google Play Services לא זמין בחלק משמעותי מהמכשירים שבהם תוצג האפליקציה, יכול להיות שעדיף להשתמש ב-Cronet Embedded או ב-OkHttp. שימוש בפיצ'רים המובנים יכול להיות שיתקבל מחסנית רשת אם גודל ה-APK הוא בעיה קריטית, או אם מדיה סטרימינג הוא רק חלק קטן מהפונקציונליות של האפליקציה.

מעבר למדיה, בדרך כלל כדאי לבחור מקבץ רשת אחד לכל הרשתות שהאפליקציה מבצעת. כך אפשר להפעיל משאבים (כמו sockets) כדי שיהיה מאגר יעיל ושיתוף בין ExoPlayer רכיבי האפליקציה.

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

שמירת מדיה במטמון

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

כדי לשמור במטמון נדרשת מופע SimpleCache שמפנה למטמון ייעודי ו-CacheDataSource.Factory:

Kotlin

// Note: This should be a singleton in your app.
val databaseProvider = StandaloneDatabaseProvider(context)

// An on-the-fly cache should evict media when reaching a maximum disk space limit.
val cache =
    SimpleCache(
        downloadDirectory, LeastRecentlyUsedCacheEvictor(maxBytes), databaseProvider)

// Configure the DataSource.Factory with the cache and factory for the desired HTTP stack.
val cacheDataSourceFactory =
    CacheDataSource.Factory()
        .setCache(cache)
        .setUpstreamDataSourceFactory(httpDataSourceFactory)

// Inject the DefaultDataSource.Factory when creating the player.
val player =
    ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory))
        .build()

Java

// Note: This should be a singleton in your app.
DatabaseProvider databaseProvider = new StandaloneDatabaseProvider(context);

// An on-the-fly cache should evict media when reaching a maximum disk space limit.
Cache cache =
    new SimpleCache(
        downloadDirectory, new LeastRecentlyUsedCacheEvictor(maxBytes), databaseProvider);

// Configure the DataSource.Factory with the cache and factory for the desired HTTP stack.
DataSource.Factory cacheDataSourceFactory =
    new CacheDataSource.Factory()
        .setCache(cache)
        .setUpstreamDataSourceFactory(httpDataSourceFactory);

// Inject the DefaultDataSource.Factory when creating the player.
ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory))
        .build();