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

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

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

يمكنك تحميل تطبيقك بتنسيق مجموعة حزمات تطبيق Android لحفظ حجم التطبيق فورًا عند نشره على Google Play. "مجموعة حزمات تطبيق Android" هي تنسيق تحميل يتضمّن جميع الرموز والمصادر المجمَّعة لتطبيقك، ولكنّه يؤجّل إنشاء حِزمة 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 قابلة للتطوير بدلاً من ملفات الصور. يناقش هذا القسم هذه الطرق وغيرها من الطرق التي يمكنك من خلالها تقليل الموارد المتاحة في تطبيقك لخفض الحجم الإجمالي لحزمة 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" في تقليل حجم APK، يمكنك الاطّلاع على تقليص حجم التطبيق وإخفاء مفاتيح فك تشفيره وتحسينه.

في الإصدار 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

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

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

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

تجنُّب التعداد

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

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

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

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

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

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

عند إنشاء إصدار الإصدار من تطبيقك، يمكنك تجميع ملفات .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 متعددة.