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

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

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

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

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

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

التعرّف على بنية حِزم 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 قابلة للتوسيع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")
        }
    }
}

Groovy

android {
    // Other settings.

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

لاستخدام shrinkResources، فعِّل خيار تقليل حجم الرموز. أثناء عملية الإنشاء، تزيل أداة R8 أولاً الرموز غير المستخدَمة. بعد ذلك، يزيل المكوّن الإضافي لنظام Gradle المتوافق مع Android الموارد غير المستخدَمة.

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

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

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

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

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

ترميز الصور المتحركة المدمجة مع المحتوى

في الإصدار 12 من نظام التشغيل Android (المستوى 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 صورًا أحادية اللون متوافقة مع إرشادات 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

يمكن لأداة aapt تحسين موارد الصور الموضوعة في res/drawable/ باستخدام الضغط بدون فقدان البيانات أثناء عملية الإنشاء. على سبيل المثال، يمكن لأداة aapt تحويل ملف PNG بألوان حقيقية لا يتطلّب أكثر من 256 لونًا إلى ملف PNG بـ 8 بت مع لوحة ألوان. ويؤدي ذلك إلى الحصول على صورة بجودة مماثلة ولكن بحجم أصغر.

يخضع aapt للقيود التالية:

  • لا تقلّل الأداة aapt حجم ملفات PNG المتوفّرة في المجلد asset/.
  • يجب أن تستخدم ملفات الصور 256 لونًا أو أقل كي تتمكّن الأداة aapt من تحسينها.
  • قد يؤدي استخدام الأداة aapt إلى زيادة حجم ملفات PNG المضغوطة. لمنع حدوث ذلك، يمكنك استخدام العلامة isCrunchPngs لإيقاف هذه العملية لملفات PNG:
  • Kotlin

        buildTypes.all { isCrunchPngs = false }
        

    Groovy

        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 Studio. لمزيد من المعلومات، يُرجى الاطّلاع على إنشاء صور 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 المتعددة.