ضغط APK ، في محاولة للحفاظ على العمل


/ PxHere / PD


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


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


قبل القراءة


  • قبل تطبيق النصائح من المقالة ، حسّن دليل APK لـ Google . هذه المقالة مخصصة لأولئك الذين ليس لديهم تحسينات قياسية كافية.
  • بواسطة "proguard" أعني برنامج التحويل البرمجي الأمثل مع التصغير.
  • حسب المكون ، أعني ميزة معينة للمنتج من وجهة نظر العمل. في حالتنا ، هذه مجرد مجموعة من الملفات في حزمة معينة. لدينا وحدة واحدة للمهارة للتطبيق بأكمله.

كان وزن Google المحسن - APK الخاص بنا هو 4.4 .


ملفات اضافية


لنبدأ مع واحد بسيط. إذا كنت لا تستخدم kotlin-reflect ، فيمكنك استبعاد المعلومات الوصفية حول فئات kotlin من التجميع. يمكنك القيام بذلك على النحو التالي:
في build.gradle (Module: app)


 android { packagingOptions { exclude("META-INF/*.kotlin_module") exclude("**.kotlin_builtins") exclude("**.kotlin_metadata") } } 

لا يحتاج انعكاس Java إلى *.kotlin_module *.kotlin_builtins و *.kotlin_metadata و *.kotlin_metadata . تحديد الانعكاس الذي تستخدمه بسيط للغاية. إذا قمت بكتابة obj::class.<method> ، فإنك تستخدم انعكاس kotlin ، إذا obj::class.java.<method> ، ثم انعكاس java.


نتيجة التحسين بالنسبة لنا: -602.1 كيلو بايت


اعتمادا على


تضيف المكتبات أحيانًا تبعيات للحالات التي لا تحدث أبدًا في تطبيقك. على سبيل المثال ، ktor-client يسحب kotlin-reflect معه (0.5 ميغابايت!).
لقد minifyEnabled = true مثل هذه الحالات على النحو التالي: جمعت ملف APK باستخدام minifyEnabled = true ، minifyEnabled = true في محلل Android Studio ، وقمت بتنزيل mapping.txt وبحثت عن حزم ، من الناحية النظرية ، يجب ألا تكون موجودة في التجميع. على سبيل المثال ، kotlin.reflect . بعد التشغيل ./gradlew app:dependencies في مجلد المشروع للبحث عن التبعيات (لا تنسَ زيادة طول السجل في الجهاز. يمكن أن تكون شجرة التبعية كبيرة!). من هذه الشجرة ، من السهل فهم ما يشير إلى التبعيات غير الضرورية واستبعادها. في build.gradle الوحدة النمطية الخاصة بك:


 dependencies { implementation("io.ktor:ktor-client-core:$ktorVersion") { exclude(group: "org.jetbrains.kotlin", module: "kotlin-reflect") } implementation("io.ktor:ktor-client-okhttp:$ktorVersion") { exclude(group: "org.jetbrains.kotlin", module: "kotlin-reflect") } } 

يزيل هذا الرمز تبعية مكتبة ktor-client على انعكاس kotlin . إذا كنت تريد استبعاد شيء آخر ، فاستبدل قيمك.


!!! استخدم هذه النصيحة بعناية فائقة! قبل التخلص من التبعيات ، تأكد من أنك لست بحاجة إليها. إذا لم تقم بذلك ، فقد يبدأ التطبيق في الانخفاض في الإنتاج !!!


نتيجة التحسين بالنسبة لنا: -500.3 كيلو بايت


التحقق من صحة XML الخاص بك


لسوء الحظ ، لا يقوم proguard بإزالة ملفات علامات XML الإضافية من مجلد التخطيط. يمكن أن تستخدم XML غير المستخدمة عناصر واجهة المستخدم "الثقيلة" ولن يتمكن proguard من استبعادها من التجميع أيضًا! لتجنب ذلك ، قم بإزالة الموارد غير المستخدمة مع Refactor -> Remove unused resources...


تحقق دي الخاص بك


إذا كنت ، مثلنا ، تستخدم وقت التشغيل DI ، فتحقق مما إذا كان لديك مزودين لتلك التبعيات التي لا تستخدمها. يتعذر على Proguard استبعادها من التجميع لأنها غير مستخدمة من وجهة نظر المترجم. يمكنك استخدامها عند بناء الرسم البياني التبعية.


استبعاد التبعيات Debug من الإصدار Builds


يمكن أن تأخذ أدوات تصحيح الأخطاء مساحة كبيرة بشكل غير متوقع. على سبيل المثال ، يزن stetho حوالي 0.2 بعد الضغط! في أي حال ، من الأفضل استبعاد البنية الأساسية لتصحيح الأخطاء بالكامل من إصدار الإصدار حتى لا يستطيع أحد معرفة الكثير عن تطبيقك ببساطة عن طريق تنزيله من Google Play.


يمكنك عمل إصدارات مختلفة من نفس الملفات لتصحيح الأخطاء والإصدار. للقيام بذلك ، في مجلد src ، بجانب main ، قم بإنشاء مجلدات debug release . الآن يمكنك كتابة دالة initStetho التي تقوم بتهيئة Stetho في ملف src/debug/java/your/pkg/Stetho.kt initStetho ووظيفة initStetho التي لا تفعل شيئًا في ملف src/release/java/your/pkg/Stetho.kt .


فقط في حالة ، تأكد من تضمين هذا التبعية فقط في بنيات التصحيح. يمكنك القيام بذلك عن طريق استبدال implementation مع debugImplementation في build.gradle . في أكثر الأحيان ، يحذف proguard الملفات غير الضرورية حتى بدون هذه الخطوة ، ولكن ليس دائمًا. الجواب على السؤال "لماذا؟" أدناه في نص المقال .


منصة


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



/ PxHere / PD


تجربتنا


نحن نعمل على تطوير مصمم تطبيقات الأجهزة المحمولة E-SHOP . لدينا عدة عشرات من العملاء ولكل منهم مجموعة مكوناته الخاصة. يتم استخدام بعض المكونات من قبل جميع العملاء ، وبعضها جزء فقط. مهمتنا هي أن ندرج في تجميع العميل فقط تلك المكونات التي يحتاجها.


استثناء العلم


لكل عميل نقوم بإنشاء productFlavor منفصلة. هذا مناسب لأنه من السهل إنشاء موارد مختلفة لعملاء مختلفين ، يوفر IDE واجهة رسومية للتبديل بين النكهات ، وتعمل التخزين المؤقت جيدًا. ويمكنك أيضًا إنشاء BuildConfig.java الخاص بك لكل عميل. تُعرف قيم الحقول في هذه الفئة في مرحلة التجميع. هذا هو ما نحتاجه! قم بإنشاء حقل نوع boolean لكل مكون.


 android { productFlavors { client1 { buildConfigField("boolean", "IS_CATALOG_ENABLED", "true") } client2 { buildConfigField("boolean", "IS_CATALOG_ENABLED", "false") } } } 

هذا هو نسخة مبسطة من التكوين. الحاضر معقد بسبب التكامل مع CI لدينا.


من المعروف الآن ما إذا كان المكون نشطًا في مرحلة التجميع ، ويمكن للحارس استبعاده من التجميع!


XML مرة أخرى


الآن مشكلة تخطيطات XML غير المستخدمة تأخذ بعدًا جديدًا! لا يمكنك أخذ علامة مكون وإزالتها فقط لأن بعض العملاء لا يحتاجون إليها.


في تطبيق XML الخاص بنا لأحد المكونات النادرة الاستخدام ، استخدمنا عنصر واجهة تعامل مستخدم يشير إلى مكتبة التعرف على الصور firebase.ml.vision . يزن حوالي 0.2 ميغابايت ، وهو الكثير. تقرر إضافة هذه الأداة برمز بدلاً من الإعلان عنها في الترميز. بعد ذلك ، تمكن الحارس من استبعاد vision من التجميع للعملاء الذين لا يحتاجون إليها.


نتيجة التحسين بالنسبة لنا: -222.3 كيلو بايت لمتوسط ​​APK


@Keep


هناك طريقتان لإخبار proguard بأن فصلك لا يمكن تصغيره: اكتب قاعدة في ملف proguard-rules.pro أو ضع @Keep توضيحيًا على @Keep . في مكتبة play-services-vision ، يوجد هذا التعليق التوضيحي في فئة الجذر. لذلك ، تم تعليق 0.2 ميغابايت حتى في تطبيقات العميل التي لا تحتاج إلى التعرف على الصور.


لم أجد طريقة بسيطة وآمنة لإزالة هذا التعليق التوضيحي. إذا كنت تعرف كيف - يرجى الكتابة في التعليقات.


لحسن الحظ ، فإن مكتبة firebase.ml.vision ، وهي إصدار أحدث من play-services-vision ، لا تستخدم هذا التعليق التوضيحي وقمنا بحل المشكلة عن طريق الذهاب إليها.


ومرة أخرى DI


أخيرًا وليس آخرًا DI للمكونات غير المتصلة. كل شيء بسيط هنا: لكل مكون نستخدم الحاوية الخاصة بنا ، ونربط التبعيات العامة من خلال وحدة منفصلة.


نتيجة التحسين بالنسبة لنا: -20.1 كيلو بايت لمتوسط ​​APK


النتائج


  • انخفض متوسط ​​APK APK من 4.4 إلى 3.1 ، والحد الأدنى - إلى 2.5 !
  • لم يتضرر رمز التطبيق ، ولكن تم تحسينه. DI الآن أسهل للعمل مع

جميع التحسينات الواردة في المقال هي "ثمار منخفضة المعلقة". فهي سهلة التنفيذ وسرعان ما تحصل على النتيجة. ما يصل إلى -43 ٪ للحصول على APK الأمثل بالفعل في حالتنا. آمل أن أكون قد وفرت وقتك من خلال سرد كل شيء في مكان واحد.


شكرا لكم جميعا!

Source: https://habr.com/ru/post/ar452524/


All Articles