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

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

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

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

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

אם האפליקציה צריכה רק להפעיל תוכן http(s), בחירת סטאק רשת היא פשוט עדכון של כל המופעים של 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's built-in default network stack. אפשר גם להרחיב את ExoPlayer כדי שיתמוך בכל מחסנית רשת אחרת שפועלת ב-Android.

HttpEngine

HttpEngine היא מקבץ הרשת המומלץ כברירת מחדל ב-Android מ-API 34 (או S) תוספים 7). ברוב המקרים, הוא משתמש ב-Cronet stack ברמת הרשת באופן פנימי, ותומך בפרוטוקולים 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: מומלץ להשתמש בהטמעה הזו ברוב המקרים, ולהשתמש ב-stack הרשת המובנה של Android‏ (DefaultHttpDataSource) אם Google Play Services לא זמין.
  2. Cronet מוטמע: יכול להיות בחירה טובה אם אחוז גדול מהמשתמשים שלכם נמצאים בשווקים שבהם Google Play Services לא זמין באופן נרחב, או אם אתם רוצים לשלוט בגרסה המדויקת של הטמעת Cronet שבה נעשה שימוש. החיסרון העיקרי של Cronet Embedded הוא שהוא מוסיף לאפליקציה כ-8MB.
  3. חלופה ל-Cronet: בהטמעת החלופה ל-Cronet, ה-API של Cronet מוטמע כעטיפה סביב סטאק הרשת המובנה של Android. לא מומלץ להשתמש בו עם ExoPlayer, כי יעיל יותר להשתמש ישירות ב-stack הרשת המובנה של Android (באמצעות DefaultHttpDataSource).

OkHttp

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

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

סטאק הרשת המובנה של Android

ExoPlayer תומך בשימוש ב-stack הרשת המובנה של 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 Extensions 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. מותר להשתמש ב-stack המובנה של הרשת אם גודל ה-APK הוא גורם קריטי, או אם סטרימינג של מדיה הוא רק חלק קטן מהפונקציונליות של האפליקציה.

מעבר לשימוש במדיה, בדרך כלל מומלץ לבחור סטאק רשת אחד לכל פעולות הרשת שבוצעו על ידי האפליקציה. כך אפשר לקבץ משאבים (כמו שקעים) ולשתף אותם ביעילות בין 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();