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