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

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

تحميل تطبيقك باستخدام حِزم تطبيق 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 والتنسيقات اللغوية، بالإضافة إلى مسارات إلى المحتوى غير المضمّن مباشرةً في ملفresources.arsc، مثل ملفات التنسيق والصور.
  • classes.dex: يحتوي على الفئات المجمّعة بتنسيق ملف DEX الذي يمكن لجهاز ‎Dalvik أو ART الافتراضي فهمه
  • AndroidManifest.xml: يحتوي على ملف بيان Android الأساسي. يسرد هذا الملف اسم التطبيق وإصداره وحقوق الوصول إليه وملفات المكتبة المرجعية الخاصة به. ويستخدم الملف تنسيق XML الثنائي لنظام التشغيل Android.

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

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

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

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

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

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

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

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

في 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 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 المقدَّمة في حزمة Android NDK لإزالة رموزها غير الضرورية لتحديد الأخطاء وحلّها من المكتبات الأصلية. بعد ذلك، يمكنك تجميع بنية الإصدار.

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

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

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

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

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

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

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