تقليل حجم تطبيقك

غالبًا ما يتجنّب المستخدمون تنزيل التطبيقات التي تبدو كبيرة جدًا، خاصةً في الأسواق الناشئة حيث تتصل الأجهزة بشبكات الجيل الثاني والجيل الثالث غير المتقطعة أو يعملون على خطط ذات حدود قصوى للبيانات. توضح هذه الصفحة كيفية تقليل حجم تنزيل التطبيق، مما يتيح للمزيد من المستخدمين تنزيل التطبيق.

تحميل تطبيقك باستخدام "مجموعة حزمات تطبيق Android"

حمِّل تطبيقك في صورة مجموعة حزمات تطبيق Android لتوفير حجم التطبيق على الفور عند نشره على Google Play. "مجموعة حزمات تطبيق Android" هي تنسيق تحميل يتضمّن جميع الرموز البرمجية والموارد المجمَّعة لتطبيقك، إلا أنّها تؤجِّل إنشاء حزمة APK وتوقيعها إلى Google Play.

بعد ذلك، يستخدم نموذج عرض التطبيقات في Google Play حِزمة تطبيقك لإنشاء وعرض حِزم APK محسّنة على مستوى إعدادات جهاز كل مستخدم، وذلك ليتمكّن المستخدمون من تنزيل الرمز والموارد التي يحتاجونها لتشغيل تطبيقك فقط. وليس عليك إنشاء عدة حِزم APK وتوقيعها وإدارتها للتوافق مع أجهزة مختلفة، وسيحصل المستخدمون على عمليات تنزيل أصغر حجمًا ومحسَّنة.

نظرًا لأن Google Play يفرض قيودًا على حجم التنزيل المضغوط البالغ 200 ميغابايت أو أقل على التطبيقات المنشورة باستخدام حِزم التطبيقات، ننصحك بمواصلة تطبيق الإرشادات الموضّحة في هذه الصفحة لتقليل حجم تنزيل التطبيق قدر الإمكان.

فهم بنية 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 الأساسي. يسرد هذا الملف الاسم والإصدار وحقوق الوصول وملفات المكتبة المرجعية الخاصة بالتطبيق. يستخدم الملف تنسيق XML الثنائي لنظام Android.

تقليل عدد الموارد وحجمها

يؤثر حجم حزمة APK في سرعة تحميل تطبيقك ومقدار الذاكرة التي يستهلكها والطاقة التي يستهلكها. يمكنك تصغير حزمة APK عن طريق تقليل عدد الموارد التي تحتوي عليها وحجمها. وعلى وجه الخصوص، يمكنك إزالة الموارد التي لم يعُد تطبيقك يستخدمها، ويمكنك استخدام عناصر Drawable قابلة للتطوير بدلاً من ملفات الصور. يناقش هذا القسم هذه الطرق والطرق الأخرى التي يمكنك من خلالها تقليل الموارد في تطبيقك لخفض الحجم الإجمالي لملف APK.

إزالة الموارد غير المستخدمة

ترصد أداة lint، أداة تحليل الرموز الثابتة المضمّنة في "استوديو Android"، الموارد التي لا يشير إليها الرمز في المجلد 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، يجب تفعيل ميزة تقليص الرموز. أثناء عملية التصميم، تزيل R8 أولاً التعليمات البرمجية غير المستخدمة. وبعد ذلك، يزيل المكوّن الإضافي لنظام Gradle المتوافق مع Android الموارد غير المستخدَمة.

للحصول على مزيد من المعلومات حول تقليص حجم الموارد والموارد وكيفية تصغير حجم الموارد باستخدام "استوديو Android" يمكنك الاطّلاع على المقالة تقليص حجم تطبيقك وتشويشه وتحسينه.

في الإصدار 7.0 من "المكوّن الإضافي لنظام Gradle المتوافق مع Android" والإصدارات الأحدث، يمكنك توضيح الإعدادات التي يتوافق معها تطبيقك. تنقل Gradle هذه المعلومات إلى نظام الإنشاء باستخدام نكهة resourceConfigurations والخيار defaultConfig. ويمنع نظام الإصدار بعد ذلك ظهور الموارد من الإعدادات الأخرى غير المتوافقة في حزمة APK، ما يقلل حجم حزمة APK. لمزيد من المعلومات حول هذه الميزة، يمكنك الاطّلاع على مقالة إزالة الموارد البديلة غير المستخدمة.

تقليل استخدام الموارد من المكتبات

عند تطوير تطبيق Android، يتم عادةً استخدام المكتبات الخارجية لتحسين سهولة استخدام التطبيق وتنوع استخداماته. على سبيل المثال، يمكنك الرجوع إلى AndroidX لتحسين تجربة المستخدم على الأجهزة السابقة، أو يمكنك استخدام خدمات Google Play لاسترداد الترجمات التلقائية للنص داخل تطبيقك.

إذا كانت المكتبة مصمَّمة لخادم أو كمبيوتر مكتبي، يمكن أن تتضمّن العديد من العناصر والطرق التي لا يحتاج إليها تطبيقك. لتضمين أجزاء المكتبة التي يحتاجها تطبيقك فقط، يمكنك تعديل ملفات المكتبة إذا كان الترخيص يتيح لك تعديل المكتبة. يمكنك أيضًا استخدام مكتبة بديلة متوافقة مع الأجهزة الجوّالة لإضافة وظائف محددة إلى تطبيقك.

فك ترميز الصور المتحركة الأصلية

في نظام التشغيل Android 12 (المستوى 31 من واجهة برمجة التطبيقات)، تم توسيع واجهة برمجة التطبيقات NDK ImageDecoder لفك ترميز جميع الإطارات وبيانات التوقيت من الصور التي تستخدم تنسيقات ملفات GIF المتحركة وملفات WebP المتحركة.

يمكنك استخدام ImageDecoder بدلاً من المكتبات التابعة لجهات خارجية لتقليل حجم حِزم APK والاستفادة من التحديثات المستقبلية المتعلّقة بالأمان والأداء.

لمزيد من التفاصيل حول واجهة برمجة التطبيقات ImageDecoder، يمكنك الرجوع إلى API reference والنموذج على GitHub.

دعم كثافات محدّدة فقط

يتوافق Android مع كثافات الشاشة المختلفة، مثل ما يلي:

  • ldpi
  • mdpi
  • tvdpi
  • hdpi
  • xhdpi
  • xxhdpi
  • xxxhdpi

على الرغم من أنّ Android يتوافق مع الكثافات السابقة، لن تحتاج إلى تصدير الأصول النقطية إلى كل كثافة.

إذا كنت تعلم أنّ نسبة صغيرة فقط من المستخدمين لديهم أجهزة ذات كثافات معيّنة، فكِّر في ما إذا كنت بحاجة إلى تجميع هذه الكثافات في تطبيقك. وإذا لم تُدرِج موارد لكثافة شاشة معيّنة، سيعدّل Android تلقائيًا الموارد الحالية التي تم تصميمها في الأصل لتناسب كثافات الشاشات الأخرى.

إذا كان تطبيقك يحتاج إلى صور بحجم معيّن فقط، يمكنك توفير مساحة أكبر من خلال استخدام نسخة واحدة من الصورة في drawable-nodpi/. ننصحك بتضمين خيار صورة واحد xxhdpi على الأقل في تطبيقك.

للحصول على مزيد من المعلومات عن كثافات الشاشة، يُرجى الاطّلاع على أحجام الشاشات وكثافاتها.

استخدام الكائنات القابلة للرسم

لا تتطلّب بعض الصور مصدر صورة ثابتًا. وبإمكان إطار العمل رسم الصورة بشكل ديناميكي في وقت التشغيل بدلاً من ذلك. يمكن لكائنات Drawable، أو <shape> في XML، أن تشغل مساحة صغيرة في ملف APK. بالإضافة إلى ذلك، تُنتج كائنات XML Drawable صورًا أحادية اللون متوافقة مع إرشادات التصميم المتعدد الأبعاد.

إعادة استخدام المراجع

يمكنك تضمين مصدر منفصل لنُسخ مختلفة من الصورة، مثل النُسخ الملوّنة أو المظلّلة أو التي تم تدويرها من الصورة نفسها. ومع ذلك، ننصحك بإعادة استخدام مجموعة الموارد نفسها وتخصيصها حسب الحاجة في وقت التشغيل.

يوفر 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

يمكن لأداة aapt تحسين موارد الصور الموضوعة في res/drawable/ باستخدام الضغط بدون فقدان البيانات أثناء عملية التصميم. على سبيل المثال، يمكن للأداة 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.

يمكنك تحويل صور BMP أو JPG أو PNG أو صور GIF ثابتة إلى تنسيق WebP باستخدام "استوديو Android". لمزيد من المعلومات، يُرجى الاطّلاع على إنشاء صور WebP.

استخدام الرسومات المتجهة

يمكنك استخدام الرسومات المتجهة لإنشاء رموز مستقلة عن الدقة ووسائط أخرى قابلة للتطوير. يمكنك استخدام هذه الرسومات لتقليل تأثير حزِم APK بشكلٍ كبير. يتم تمثيل صور المتجه في Android على هيئة كائنات VectorDrawable. باستخدام كائن VectorDrawable، يمكن لملف بحجم 100 بايت إنشاء صورة واضحة بحجم الشاشة.

في المقابل، يستغرق النظام وقتًا أطول بكثير لعرض كل عنصر VectorDrawable، وتستغرق الصور الأكبر حجمًا وقتًا أطول للظهور على الشاشة. لذلك، ضع في اعتبارك استخدام هذه الرسومات المتجهة فقط عند عرض صور صغيرة.

لمزيد من المعلومات حول استخدام كائنات VectorDrawable، يمكنك الاطّلاع على العناصر القابلة للرسم.

استخدام الرسومات المتجهة للصور المتحركة

لا تستخدِم AnimationDrawable لإنشاء صور متحرّكة لكل إطار، لأنّ ذلك يتطلّب تضمين ملف صورة نقطية منفصل لكل إطار من الصورة المتحركة، ما يؤدي إلى زيادة حجم حِزمة APK بشكلٍ كبير.

بدلاً من ذلك، يمكنك استخدام AnimatedVectorDrawableCompat لإنشاء رسومات متحرّكة قابلة للرسم.

تقليل الرموز البرمجية الأصلية ولغة Java

يمكنك استخدام الطرق التالية لتقليل حجم Java وقاعدة الرموز البرمجية الأصلية في تطبيقك.

إزالة الرمز غير الضروري الذي تم إنشاؤه

تأكّد من فهم تأثير أي رمز يتم إنشاؤه تلقائيًا. على سبيل المثال، تنشئ العديد من أدوات التخزين المؤقت للبروتوكولات عددًا كبيرًا من الطرق والفئات، ما قد يؤدي إلى مضاعفة حجم التطبيق أو مضاعفة هذا الحجم.

تجنب التعداد

يمكن أن يضيف تعداد واحد حوالي 1.0 إلى 1.4 كيلوبايت إلى ملف classes.dex الخاص بتطبيقك. يمكن أن تتراكم هذه الإضافات بسرعة للأنظمة المعقدة أو المكتبات المشتركة. إن أمكن، ننصحك باستخدام التعليق التوضيحي @IntDef وتقليص الرموز لإزالة التعداد وتحويلها إلى أعداد صحيحة. يحافظ تحويل النوع هذا على جميع فوائد أمان النوع للتعدادات.

تقليل حجم البرامج الثنائية الأصلية

وإذا كان تطبيقك يستخدم رمزًا برمجيًا أصليًا مع Android NDK، يمكنك أيضًا تقليل حجم إصدار تطبيقك عن طريق تحسين الرمز. هناك أسلوبان مفيدان هما إزالة رموز تصحيح الأخطاء وعدم استخراج المكتبات الأصلية.

إزالة رموز تصحيح الأخطاء

من المفيد استخدام رموز تصحيح الأخطاء إذا كان تطبيقك في مرحلة التطوير ولا يزال يتطلب تصحيح الأخطاء. استخدِم أداة arm-eabi-strip المتوفّرة في NDK على Android لإزالة رموز تصحيح الأخطاء غير الضرورية من المكتبات الأصلية. بعد ذلك، يمكنك تجميع بنية الإصدار.

تجنُّب استخراج المكتبات الأصلية

عند إنشاء إصدار الإصدار من تطبيقك، يمكنك إنشاء حزمة غير مضغوطة من ملفات .so في APK من خلال ضبط useLegacyPackaging على false في ملف build.gradle.kts الخاص بالتطبيق. يؤدي إيقاف هذه العلامة إلى منع PackageManager من نسخ ملفات .so من حزمة APK إلى نظام الملفات أثناء التثبيت. تجعل هذه الطريقة تحديثات تطبيقك أصغر.

الاحتفاظ بالعديد من حِزم APK الفعّالة

قد تحتوي حزمة APK على محتوى ينزّله المستخدمون بدون استخدامه أبدًا، مثل لغة إضافية أو موارد كثافة شاشة واحدة. لضمان أقل قدر ممكن من التنزيل للمستخدمين، عليك تحميل تطبيقك إلى Google Play باستخدام "مجموعة حزمات تطبيق Android". من خلال تحميل حِزم التطبيقات، يمكن لـ Google Play إنشاء حِزم APK محسّنة وعرضها وفقًا لإعدادات كل مستخدم على حدة، ما يتيح لهم تنزيل الرمز والموارد التي يحتاجونها لتشغيل تطبيقك فقط. وليس عليك إنشاء حِزم APK متعدّدة وتوقيعها وإدارتها لإتاحة استخدامها على أجهزة مختلفة، ويمكن للمستخدمين الحصول على عمليات تنزيل أصغر حجمًا ومحسَّنة.

إذا كنت لا تنشر تطبيقك على Google Play، يمكنك تقسيمه إلى عدة حِزم APK، والتي يتم تمييزها بعوامل مثل حجم الشاشة أو توافق بنية وحدة معالجة الرسومات.

عندما ينزّل أحد المستخدمين تطبيقك، يتلقّى جهازه حزمة APK الصحيحة بناءً على ميزات الجهاز وإعداداته. وبهذه الطريقة، لن تتلقّى الأجهزة مواد عرض للميزات التي لا تتوفّر فيها. على سبيل المثال، إذا كان المستخدم يملك جهاز hdpi، لن يحتاج إلى موارد xxxhdpi التي قد تُدرجها في الأجهزة ذات الشاشات العالية الكثافة.

لمزيد من المعلومات، يُرجى الاطّلاع على القسم إنشاء حِزم APK متعددة ودعم حِزم APK متعددة.