כיווץ APK

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

שימוש רק ביחסי תלות נדרשים

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

Kotlin

implementation("androidx.media3:media3-exoplayer:1.6.0")
implementation("androidx.media3:media3-exoplayer-dash:1.6.0")
implementation("androidx.media3:media3-ui:1.6.0")

Groovy

implementation "androidx.media3:media3-exoplayer:1.6.0"
implementation "androidx.media3:media3-exoplayer-dash:1.6.0"
implementation "androidx.media3:media3-ui:1.6.0"

הפעלה של כיווץ קוד ומשאבים

מומלץ להפעיל כיווץ קוד ומשאבים ב-builds של הגרסה של האפליקציה. ExoPlayer מובנה כך שאפשר לבצע בו כיווץ קוד כדי להסיר ביעילות פונקציונליות שלא בשימוש. לדוגמה, באפליקציה שמפעילה תוכן DASH, אפשר להקטין את התרומה של ExoPlayer לגודל ה-APK בכ-40% על ידי הפעלת צמצום הקוד.

במאמר כיווץ, ערפול קוד ואופטימיזציה של האפליקציה מוסבר איך מפעילים כיווץ של קוד ומשאבים.

ציון הרסטוררים הנדרשים לאפליקציה

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

Kotlin

val audioOnlyRenderersFactory =
  RenderersFactory {
    handler: Handler,
    videoListener: VideoRendererEventListener,
    audioListener: AudioRendererEventListener,
    textOutput: TextOutput,
    metadataOutput: MetadataOutput,
    ->
    arrayOf<Renderer>(
      MediaCodecAudioRenderer(context, MediaCodecSelector.DEFAULT, handler, audioListener)
    )
}
val player = ExoPlayer.Builder(context, audioOnlyRenderersFactory).build()

Java

RenderersFactory audioOnlyRenderersFactory =
    (handler, videoListener, audioListener, textOutput, metadataOutput) ->
        new Renderer[] {
            new MediaCodecAudioRenderer(
                context, MediaCodecSelector.DEFAULT, handler, audioListener)
        };
ExoPlayer player = new ExoPlayer.Builder(context, audioOnlyRenderersFactory).build();

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

ציון הגורמים לחילוץ (extractors) הנדרשים לאפליקציה

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

Kotlin

val mp4ExtractorFactory = ExtractorsFactory {
  arrayOf<Extractor>(Mp4Extractor(DefaultSubtitleParserFactory()))
}
val player =
  ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, mp4ExtractorFactory)).build()

Java

ExtractorsFactory mp4ExtractorFactory =
    () -> new Extractor[] {new Mp4Extractor(new DefaultSubtitleParserFactory())};
ExoPlayer player =
    new ExoPlayer.Builder(context, new DefaultMediaSourceFactory(context, mp4ExtractorFactory))
        .build();

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

אם האפליקציה לא מפעילה בכלל תוכן פרוגרסיבי, צריך להעביר את ExtractorsFactory.EMPTY למבנה DefaultMediaSourceFactory ואז להעביר את mediaSourceFactory למבנה ExoPlayer.Builder.

Kotlin

val player =
  ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY)).build()

Java

ExoPlayer player =
    new ExoPlayer.Builder(
            context, new DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY))
        .build();

יצירת מופע של MediaSource בהתאמה אישית

אם באפליקציה שלכם נעשה שימוש ב-MediaSource.Factory בהתאמה אישית ואתם רוצים להסיר את DefaultMediaSourceFactory על ידי הסרת קוד, צריך להעביר את MediaSource.Factory ישירות ל-constructor של ExoPlayer.Builder.

Kotlin

val player = ExoPlayer.Builder(context, customMediaSourceFactory).build()

Java

ExoPlayer player = new ExoPlayer.Builder(context, mediaSourceFactory).build();

אם האפליקציה משתמשת ב-MediaSource ישירות במקום ב-MediaItem, צריך להעביר את MediaSource.Factory.UNSUPPORTED למבנה ExoPlayer.Builder כדי לוודא שאפשר יהיה להסיר את DefaultMediaSourceFactory ואת DefaultExtractorsFactory באמצעות צמצום קוד.

Kotlin

val player = ExoPlayer.Builder(context, MediaSource.Factory.UNSUPPORTED).build()
val mediaSource =
  ProgressiveMediaSource.Factory(dataSourceFactory, customExtractorsFactory)
    .createMediaSource(MediaItem.fromUri(uri))

Java

ExoPlayer player = new ExoPlayer.Builder(context, MediaSource.Factory.UNSUPPORTED).build();
ProgressiveMediaSource mediaSource =
    new ProgressiveMediaSource.Factory(dataSourceFactory, customExtractorsFactory)
        .createMediaSource(MediaItem.fromUri(uri));