לעיתים קרובות משתמשים נמנעים מהורדת אפליקציות שנראות גדולות מדי, במיוחד בשווקים מתעוררים שבהם מכשירים מתחברים לרשתות 2G ו-3G לא יציבות או עובדים על תוכניות עם מגבלות נתונים. בדף הזה נסביר איך להקטין את גודל ההורדה של האפליקציה, כדי לאפשר ליותר משתמשים להוריד אותה.
העלאת אפליקציה באמצעות קובצי Android App Bundle
מעלים את האפליקציה כקובץ Android App Bundle כדי שמירת גודל האפליקציה כשמפרסמים ב-Google Play. קובץ Android App Bundle הוא פורמט העלאה שכולל את כל הקוד והמשאבים המורכבים של האפליקציה, אבל מונעים יצירת APK וכניסה ל-Google Play.
לאחר מכן, מודל הצגת האפליקציות של Google Play משתמש ב-App Bundle כדי ליצור ולהציג חבילות APK שעברו אופטימיזציה. לתצורת המכשיר של כל משתמש, כדי שהוא יוריד רק את הקוד והמשאבים שדרושים לו להריץ את האפליקציה. אתם לא צריכים לפתח, לחתום ולנהל חבילות APK מרובות כדי לתמוך במכשירים שונים, והמשתמשים מקבלים הורדות קטנות ומשופרות.
Google Play אוכפת הורדה דחוסה הגבלת גודל של 200MB לאפליקציות שפורסמו באמצעות קובצי App Bundle. גדלים גדולים יותר אפשריות באמצעות Play Feature Delivery ו-Play Asset Delivery, אבל הגדלה של גודל האפליקציה תשפיע לרעה על הצלחת ההתקנה ותגדיל את מספר ההסרות, לכן אנחנו ממליצים להחיל שמתוארות בדף הזה כדי להקטין את גודל ההורדה של האפליקציה ככל האפשר.
הסבר על מבנה ה-APK
לפני שמקטינים את גודל האפליקציה, חשוב להבין את מבנה ה-APK של האפליקציה. קובץ APK מורכב מארכיון ZIP שמכיל את כל הקבצים שמהם מורכבת האפליקציה. האלה הקבצים כוללים קובצי מחלקה של Java, קובצי משאבים וקובץ שמכיל משאבים שעברו הידור.
חבילת APK מכילה את הספריות הבאות:
META-INF/
: מכיל את החתימהCERT.SF
ו-CERT.RSA
קבצים שונים, וגםMANIFEST.MF
בקובץ המניפסט.assets/
: מכיל את נכסי האפליקציה, שהאפליקציה יכולה לאחזר באמצעותAssetManager
לאובייקט.res/
: מכיל משאבים שלא עברו הידורresources.arsc
.lib/
: מכיל את הקוד שעבר הידור שספציפי לשכבת התוכנה של ומעבד מידע. הספרייה הזו מכילה ספריית משנה לכל סוג פלטפורמה, כמוarmeabi
,armeabi-v7a
,arm64-v8a
,x86
x86_64
ו-mips
.
חבילת APK מכילה גם את הקבצים הבאים. חובה להזין רק AndroidManifest.xml
:
resources.arsc
: מכיל משאבים שעברו הידור. הקובץ הזה מכיל את התוכן בפורמט XML מכל ההגדרות של התיקייהres/values/
. כלי האריזה מחלץ את זה תוכן XML, מהדר אותו לצורה בינארית ומעביר את התוכן לארכיון. התוכן הזה כולל שפה מחרוזות וסגנונות, וכן נתיבים לתוכן שלא נכלל ישירותresources.arsc
, למשל קובצי פריסה ותמונות.classes.dex
: מכיל את הכיתות שעברו הידור בפורמט קובץ DEX שמבינים על ידי במכונה הווירטואלית Dalvik או ART.AndroidManifest.xml
: מכיל את קובץ המניפסט המרכזי של Android. בקובץ הזה מפורטים השם, הגרסה, הרשאות הגישה וקובצי הספרייה של האפליקציה. הקובץ משתמש ב-Android בפורמט XML בינארי.
הקטנה של מספר המשאבים והגודל שלהם
גודל ה-APK משפיע על מהירות הטעינה של האפליקציה, על נפח הזיכרון שהיא משתמשת בו ועל אופן הטעינה
שהוא צורך. ניתן להקטין את ה-APK על ידי הקטנת המספר והגודל של ה-APK
את המשאבים שהוא מכיל. באופן ספציפי, אפשר להסיר משאבים שהאפליקציה כבר לא משתמשת בהם,
יכולים להשתמש במודל יכולת התאמה
Drawable
אובייקטים ב-
המקום של קובצי התמונות. הקטע הזה דן בשיטות האלה ובדרכים נוספות שבהן אפשר לצמצם את
משאבים באפליקציה שלך כדי להקטין את הגודל הכולל של ה-APK.
הסרת משאבים שלא נמצאים בשימוש
הכלי lint
– כלי לניתוח קוד סטטי
שכלולות ב-Android Studio – המערכת מזהה משאבים בתיקייה res/
שבהם הקוד
לא מפנה. כשהכלי lint
מאתר משאב שעשוי להיות שלא נמצא בשימוש בחשבון שלך
המערכת מדפיסה הודעה כמו בדוגמה הבאה:
res/layout/preferences.xml: Warning: The resource R.layout.preferences appears to be unused [UnusedResources]
יכול להיות שספריות שהוספת לקוד יכללו משאבים שלא נמצאים בשימוש. Gradle יכולה אוטומטית
להסיר משאבים בשמך אם מפעילים
shrinkResources
ב-
את קובץ build.gradle.kts
של האפליקציה.
Kotlin
android { // Other settings. buildTypes { getByName("release") { minifyEnabled = true shrinkResources = true proguardFiles(getDefaultProguardFile('proguard-android.txt'), "proguard-rules.pro") } } }
מגניב
android { // Other settings. buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
כדי להשתמש ב-shrinkResources
, צריך להפעיל כיווץ קוד. במהלך ה-build, מקישים קודם על R8
מסירה קוד שלא בשימוש. אחר כך, הפלאגין של Android Gradle מסיר את המשאבים שלא נמצאים בשימוש.
בקישורים הבאים תוכלו למצוא מידע נוסף על כיווץ הקוד והמשאבים ועל דרכים נוספות שבהן Android Studio גודל ה-APK זמין במאמר כיווץ, ערפול קוד (obfuscation) ואופטימיזציה של האפליקציה.
ב-Android Gradle Plugin מגרסה 7.0 ואילך, אפשר להצהיר על ההגדרות שהאפליקציה שלך
נתמך. Gradle מעבירה את המידע הזה למערכת ה-build באמצעות
resourceConfigurations
טעם חדש והאפשרות defaultConfig
. לאחר מכן מערכת ה-build מונעת משאבים
תצורות אחרות שאינן נתמכות ב-APK, וכתוצאה מכך הקטנת את גודל ה-APK. לקבלת מידע נוסף
על התכונה הזאת:
הסרת חלופה שלא בשימוש
משאבים.
צמצום השימוש במשאבים מספריות
כשמפתחים אפליקציה ל-Android, בדרך כלל משתמשים בספריות חיצוניות כדי לשפר את שימושיות וגמישות. לדוגמה, אפשר להיעזר ב-AndroidX כדי לשפר את חוויית המשתמש במכשירים קודמים, או שאפשר להשתמש Google Play Services לאחזור תרגומים אוטומטיים של טקסט בתוך האפליקציה.
אם ספרייה מיועדת לשרת או לשולחן עבודה, היא יכולה לכלול הרבה אובייקטים ושיטות שהאפליקציה לא נחוצה. כדי לכלול רק את החלקים מהספרייה שנדרשים לאפליקציה, אפשר לערוך את הקבצים של הספרייה, אם הרישיון מאפשר לכם לשנות את הספרייה. אפשר גם להשתמש בחלופה לספרייה ידידותית לנייד כדי להוסיף פונקציונליות ספציפית לאפליקציה.
פענוח תמונה מונפשת רגילה
ב-Android 12 (רמת API 31), ה-NDK
ממשק ה-API של ImageDecoder
מורחב לפענוח קוד
כל נתוני הפריימים והתזמון מתמונות שנעשה בהן שימוש בפורמט GIF מונפש וקובץ WebP מונפש.
יש להשתמש ב-ImageDecoder
במקום בספריות של צד שלישי כדי להמשיך
הקטנת ה-APK והפקת תועלת מעתיד
עדכונים שקשורים לאבטחה ולביצועים.
לפרטים נוספים על ImageDecoder
API, אפשר לעיין במאמר בנושא
API reference
וגם
דוגמה
ב-GitHub.
תמיכה בדחיסות ספציפיות בלבד
מערכת Android תומכת בדחיסות מסך שונות, למשל:
ldpi
mdpi
tvdpi
hdpi
xhdpi
xxhdpi
xxxhdpi
למרות ש-Android תומך בדחיסות הקודמת, אין צורך לייצא את נכסים לכל צפיפות.
אם אתם יודעים שרק לאחוז קטן מהמשתמשים יש מכשירים עם צפיפות ספציפית, מומלץ לשקול אם עליך לקבץ את הדחיסות האלה באפליקציה שלך. אם לא כוללים משאבים לצפיפות מסך ספציפית, מערכת Android מתאימה באופן אוטומטי את הגודל של משאבים קיימים שתוכננו במקור לדחיסות מסך אחרות.
אם האפליקציה שלך צריכה רק תמונות מותאמות, תוכל לחסוך עוד יותר מקום אם תשתמש בווריאציה אחת של
תמונה באוסף drawable-nodpi/
. מומלץ לכלול לפחות xxhdpi
של קבוצת התמונות באפליקציה שלך.
למידע נוסף על דחיסות המסך, גדלים ודחיסויות של מסכים.
שימוש באובייקטים שניתנים להזזה
בחלק מהתמונות אין צורך במשאב של תמונה סטטית. תוכנת ה-framework יכולה לשרטט באופן דינמי את התמונה
בזמן ריצה. Drawable
אובייקטים — או <shape>
אינץ'
XML - יכול לתפוס שטח קטן ב-APK. בנוסף, XML Drawable
אובייקטים מייצרים תמונות מונוכרומטיות שתואמות להנחיות של Material Design.
שימוש חוזר במשאבים
אפשר לכלול משאב נפרד לווריאציות של תמונה, כמו שימוש בגוון, הצללה או מסובבים את אותה התמונה. עם זאת, מומלץ להשתמש שוב באותה קבוצת משאבים ולהתאים אותם אישית לפי הצורך בזמן הריצה.
ב-Android יש כמה כלים לשינוי צבע של נכס, באמצעות
android:tint
ו-tintMode
.
אפשר גם להשמיט משאבים שהם רק מקבילים של משאב אחר ברוטציה. הבאים היא דוגמה להפיכת 'תמונה ממוזערת' למצב 'אל תוך אגודל' באמצעות שינוי באמצע התמונה, ומסובב ב-180 מעלות:
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_thumb_up" android:pivotX="50%" android:pivotY="50%" android:fromDegrees="180" />
עיבוד מקוד
ניתן גם להקטין את גודל ה-APK על ידי עיבוד פרוצדורלי של התמונות. רינדור פרוצדורלי מפנה מקום כי כבר לא מאחסנים קובץ תמונה ב-APK.
קובצי PNG מסוג Crunch
הכלי aapt
יכול לבצע אופטימיזציה של משאבי התמונות שמוצבים בres/drawable/
עם דחיסת נתונים ללא אובדן מידע במהלך תהליך ה-build. לדוגמה, הכלי aapt
יכול
צריך להמיר קובץ PNG בצבע אמיתי שלא דורש יותר מ-256 צבעים לקובץ PNG עם 8 ביט עם צבע
לוח צבעים. אם עושים זאת, מתקבלת תמונה באיכות זהה אבל טביעת הרגל הפחמנית קטנה יותר של הזיכרון.
המגבלות הבאות חלות על aapt
:
- הכלי
aapt
לא מכווץ קובצי PNG שכלולים בasset/
. - כדי לבצע אופטימיזציה של קובצי תמונה, צריך להשתמש ב-256 צבעים או פחות כדי שהכלי
aapt
יבצע אופטימיזציה אותם. - הכלי
aapt
עשוי לנפח קובצי PNG שכבר דחוסים. כדי למנוע במקרה הזה אפשר להשתמש בדגלisCrunchPngs
כדי להשבית את התהליך הזה בקובצי PNG:
Kotlin
buildTypes.all { isCrunchPngs = false }
מגניב
buildTypes.all { isCrunchPngs = false }
דחיסת קובצי PNG ו-JPEG
אפשר להקטין את הגודל של קובצי PNG בלי לגרוע מאיכות התמונה באמצעות כלים כמו pngcrush, pngquant, או zopflipng. כל הכלים האלה יכולים להקטין את קובץ ה-PNG תוך שמירה על איכות התמונה.
הכלי pngcrush
יעיל במיוחד. הכלי הזה מבצע איטרציה על בסיס מסנני PNG
zlib (Deflate) באמצעות כל שילוב של מסננים ופרמטרים כדי לדחוס את התמונה.
לאחר מכן הוא בוחר את התצורה שיוצרת את הפלט הדחוס הקטן ביותר.
כדי לדחוס קובצי JPEG, אפשר להשתמש בכלים כמו packJPG ו-guetzli.
שימוש בפורמט הקובץ WebP
במקום להשתמש בקובצי PNG או JPEG, אפשר להשתמש גם פורמט הקובץ WebP של התמונות. ה-WebP שמספק דחיסת נתונים מסוג איבוד מידע ושקיפות, כמו JPG ו-PNG, והוא יכול לספק שקיפות דחיסת נתונים מאשר JPEG או PNG.
Android Studio מאפשר להמיר תמונות קיימות בפורמט BMP, JPG, PNG או GIF סטטי לפורמט WebP. מידע נוסף זמין במאמר יצירת תמונות WebP.
שימוש בגרפיקה וקטורית
ניתן להשתמש בגרפיקה וקטורית כדי ליצור סמלים שאינם תלויים ברזולוציה ומדיה אחרת שניתן לשנות את הגודל שלה.
אפשר להשתמש בגרפיקה הזו כדי לצמצם משמעותית את טביעת הרגל הפחמנית של ה-APK. תמונות וקטוריות מיוצגות ב
Android בתור
VectorDrawable
אובייקטים. באמצעות אובייקט VectorDrawable
, קובץ בגודל 100 בייטים יכול ליצור תמונה חדה
גודל המסך.
עם זאת, נדרש הרבה יותר זמן עד שהמערכת תעבד את
אובייקט אחד (VectorDrawable
) ותמונות גדולות יותר מופיעות על המסך אפילו יותר זמן.
לכן, כדאי להשתמש בגרפיקה הווקטורית הזו רק כאשר מציגים תמונות קטנות.
למידע נוסף על עבודה עם אובייקטים מסוג VectorDrawable
:
נכסים דיגיטליים.
שימוש בגרפיקה וקטורית לתמונות מונפשות
אני לא רוצה להשתמש
AnimationDrawable
כדי ליצור אנימציות של פריים אחרי פריים, כי הפעולה הזו דורשת הוספה של מפת סיביות נפרדת
עבור כל פריים באנימציה, פעולה שמגדילה משמעותית את גודל ה-APK.
במקום זאת, השתמשו
AnimatedVectorDrawableCompat
כדי ליצור
וקטור מונפש
פריטים שניתנים להזזה.
הפחתת הקוד המקורי וקוד Java
אפשר להשתמש בשיטות הבאות כדי להקטין את הגודל של Java ושל Native Codebase אפליקציה.
מסירים קוד מיותר שנוצר
חשוב להבין את טביעת הרגל של כל קוד שנוצר באופן אוטומטי. לדוגמה, כלים רבים למאגר נתונים זמני של פרוטוקולים מייצרים מספר גדול של שיטות ומחלקות, מה שעלול להכפיל או פי 3 מגודל האפליקציה.
נמנעים מספירה
enum אחד יכול להוסיף בין 1.0 ל-1.4KB לקובץ classes.dex
של האפליקציה. האלה
ותוספות יכולות להצטבר במהירות במערכות מורכבות או בספריות משותפות. אם אפשר, כדאי
באמצעות ההערה @IntDef
וכיווץ הקוד
כדי להסיר ספירות ולהמיר אותן למספרים שלמים. המרה מסוג זה שומרת את כל
יתרונות הבטיחות של טיפוסים בני מנייה (enum).
הקטנת הגודל של הקבצים הבינאריים המקוריים
אם באפליקציה נעשה שימוש בקוד נייטיב וב-Android NDK, אפשר גם להקטין את גודל הגרסה של האפליקציה על ידי אופטימיזציה של הקוד. יש שתי שיטות שימושיות להסרת סמלים של ניפוי באגים, ולא מחלצים ספריות נייטיב.
הסרת סמלים של ניפוי באגים
כדאי להשתמש בסמלים לניפוי באגים אם האפליקציה נמצאת בפיתוח ועדיין מחייבת שימוש בניפוי באגים. כדאי להשתמש
הכלי arm-eabi-strip
שמסופק ב-Android NDK להסרת ניפוי באגים מיותר
מספריות מקוריות. לאחר מכן, תוכלו להדר את ה-build של הגרסה.
הימנעות מחילוץ ספריות נייטיב
כשיוצרים את גרסת ההפצה של האפליקציה, צריך לארוז קובצי .so
לא דחוסים
APK לפי הגדרה
useLegacyPackaging
אל false
בקובץ build.gradle.kts
של האפליקציה שלך. השבתת הסימון הזה מונעת
PackageManager
מ-
העתקת .so
קבצים מה-APK למערכת הקבצים במהלך ההתקנה. השיטה הזאת מאפשרת
של האפליקציה.
ניהול מספר חבילות APK רזות
יכול להיות שה-APK מכיל תוכן שמשתמשים מורידים אבל אף פעם לא משתמשים בו, כמו שפה נוספת או משאבים בדחיסות מסך. כדי להבטיח הורדה מינימלית של המשתמשים, כדאי להעלות את האפליקציה אל Google Play באמצעות קובצי Android App Bundle. העלאת קובצי App Bundle מאפשרת ל-Google מערכת Play יוצרת ומציגה חבילות APK שעברו אופטימיזציה בהתאם להגדרת המכשיר של כל משתמש, כדי שהן יוכלו להוריד רק את הקוד והמשאבים הדרושים להם כדי להפעיל את האפליקציה. לא צריך ליצור, לחתום ולנהל כמה פלטפורמות חבילות APK שתומכות במכשירים שונים, והמשתמשים מקבלים הורדות קטנות ומשופרות.
אם לא מפרסמים את האפליקציה ב-Google Play, אפשר לפלח את האפליקציה לכמה חבילות APK, שונה בהתאם לגורמים כמו גודל המסך או תמיכה בטקסטורה של GPU.
כשמשתמש מוריד את האפליקציה שלך, המכשיר שלו מקבל את ה-APK הנכון, בהתאם
תכונות והגדרות. כך, מכשירים לא יקבלו נכסים עבור תכונות שהמכשירים לא מקבלים
שיש. לדוגמה, אם למשתמש יש מכשיר hdpi
, הוא לא צריך xxxhdpi
שאולי תוכלו לכלול במכשירים עם מסכים עם צפיפות גבוהה יותר.
אפשר לקרוא מידע נוסף במאמר יצירת גרסאות מרובות חבילות APK ותמיכה ב-APK מרובים.