إذا كان تطبيقك يحتوي على minSdk
من واجهة برمجة التطبيقات 20 أو أقل وكان تطبيقك
المكتبات التي يشير إليها أكثر من 65,536 طريقة، فسيواجه خطأ الإصدار التالي
يشير إلى أنّ تطبيقك بلغ الحدّ الأقصى المسموح به لبنية إصدار Android:
trouble writing output: Too many field references: 131000; max is 65536. You may try using --multi-dex option.
تُبلغ الإصدارات القديمة من نظام الإصدار عن خطأ مختلف، وهو ما يدل على الخطأ نفسه المشكلة:
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536
تعرض حالات الخطأ هذه رقمًا شائعًا: 65536. هذا الرقم العدد الإجمالي للمراجع التي يمكن تم استدعاءها بواسطة الرمز البرمجي داخل ملف بايت واحد بتنسيق Dalvik قابل للتنفيذ (DEX). تشرح هذه الصفحة كيفية تجاوز هذا القيد من خلال تفعيل تهيئة التطبيق المعروفة باسم multidex، والتي تسمح لتطبيقك لإنشاء وقراءة ملفات DEX متعددة.
حوالي 64 ألف مرجع
تحتوي ملفات تطبيق Android (APK) على ملفات رموز بايت قابلة للتنفيذ في النموذج من دالفيك الملفات القابلة للتنفيذ (DEX) التي تحتوي على الرمز البرمجي المجمَّع المستخدَم لتشغيل تطبيقك. تحد مواصفات Dalvik التنفيذية من إجمالي عدد الطرق التي ضمن ملف DEX واحد إلى 65536، بما في ذلك Android وأساليب إطار العمل وطرق المكتبة والطرق في التعليمات البرمجية الخاصة بك.
في جلسة المعمل، لعلوم الكمبيوتر، فإن المصطلح kilo أو K الذي يشير إلى 1024 (أو 2^10). ولأن 65,536 تساوي 64×1024، يُشار إلى هذا الحد _64 ألف حد أقصى لعدد الملفات المرجعية_.دعم Multidex قبل الإصدار Android 5.0
تستخدم إصدارات النظام الأساسي التي تسبق Android 5.0 (مستوى واجهة برمجة التطبيقات 21) ملف Dalvik
وقت التشغيل لتنفيذ رمز التطبيق. بشكل تلقائي، تقصر Dalvik التطبيقات على إصدار واحد
ملف رمز بايت واحد (classes.dex
) لكل حزمة APK للتحايل على هذا
إضافة مكتبة الوسائط المتعددة إلى build.gradle
على مستوى الوحدة أو
build.gradle.kts
الملف:
Groovy
dependencies { def multidex_version = "2.0.1" implementation "androidx.multidex:multidex:$multidex_version" }
Kotlin
dependencies { val multidex_version = "2.0.1" implementation("androidx.multidex:multidex:$multidex_version") }
تصبح هذه المكتبة جزءًا من ملف DEX الأساسي لتطبيقك، ثم يدير الوصول إلى ملفات DEX الإضافية والتعليمات البرمجية التي تحتوي عليها. لعرض النُسخ الحالية لهذه المكتبة، يُرجى مراجعة إصدارات Multidex.
لمزيد من التفاصيل، راجع القسم الخاص بكيفية ضبط تطبيقك لـ Multidexدعم Multidex لنظام التشغيل Android 5.0 والإصدارات الأحدث
يستخدم Android 5.0 (المستوى 21 من واجهة برمجة التطبيقات) والإصدارات الأحدث بيئة تشغيل تُسمى ART
تتيح في الأصل تحميل ملفات DEX متعددة من ملفات APK. الفن
التجميع المسبق للبيانات في وقت تثبيت التطبيق، ويبحث عن
classesN.dex
ملف وتجميعها في ملف واحد
ملف OAT لـ
الجهاز الذي يعمل بنظام التشغيل Android. لذلك، إذا كانت minSdkVersion
إذا كان عمر 21 عامًا أو أكثر، يتم تفعيل ميزة Multidex تلقائيًا ولا تحتاج إلى مكتبة Multidex.
للحصول على مزيد من المعلومات حول Android 5.0 وقت التشغيل، يمكنك قراءة "بيئة تشغيل Android (ART)" وDalvik.
ملاحظة: عند تشغيل تطبيقك باستخدام "استوديو Android"، اتّبِع الخطوات التالية: يتم تحسين التصميم للأجهزة المستهدفة التي تنشر عليها. ويشمل ذلك تفعيل إمكانية التشغيل المتعدّد عندما تكون الأجهزة المستهدفة قيد التشغيل. الإصدار 5.0 من Android والإصدارات الأحدث. ولأن هذا التحسين لا يتم تطبيقه إلا عند نشر التطبيق باستخدام قد لا تزال بحاجة إلى ضبط إصدار الإصدار على "استوديو Android". لـ Multidex.لتجنب حد 64 كيلوبايت.
تجنَّب الوصول إلى عدد أكبر من 64 ألف
قبل إعداد تطبيقك لإتاحة استخدام فيديوهات بتنسيق 64K أو أكثر، يُرجى اتّباع الخطوات التالية: لتقليل إجمالي عدد المراجع التي يطلبها رمز التطبيق، بما في ذلك الطرق التي تحدّدها رمز تطبيقك أو المكتبات المضمنة.
يمكن أن تساعدك الاستراتيجيات التالية في تجنُّب بلوغ الحدّ الأقصى لمراجع DEX:
- مراجعة التبعيات المباشرة والمتعدية لتطبيقك
- التفكير في ما إذا كانت قيمة أي تبعية كبيرة للمكتبة تُدرجها في تطبيقك تفوق عدد الرموز البرمجية التي تتم إضافتها إلى التطبيق. هناك نمط شائع ولكن إشكالي هو تضمين مكتبة كبيرة جدًا لأن بعض طرق المنفعة كانت مفيدة. غالبًا ما يساعد تقليل اعتماديات رمز تطبيقك تجنب الحد الأقصى لمراجع DEX.
- إزالة الرمز غير المستخدَم باستخدام R8
- تفعيل تقليص الرموز لتشغيل R8 لإصدارات الإصدارات. يمكنك تفعيل التقليل للمساعدة في ضمان لا تشحن رمزًا غير مستخدَم باستخدام حِزم APK إذا تمت تهيئة تقليص التعليمات البرمجية بشكل صحيح، أيضًا إزالة التعليمات البرمجية والموارد غير المستخدمة من تبعياتك.
ويمكن أن يساعدك استخدام هذه الأساليب في خفض الحجم الإجمالي لملف APK لتجنُّب الحاجة إلى تعدد الأذونات في تطبيقك
ضبط تطبيقك لاستخدام ميزة Multidex
ملاحظة: إذا تم ضبطminSdkVersion
على 21 أو أعلى، سيتم تفعيل ميزة Multidex تلقائيًا.
ولا تحتاج إلى مكتبة الوسائط المتعددة.
وإذا تم ضبط minSdkVersion
على 20 أو أقل، يجب:
استخدام
مكتبة Multidex وإجراء
التعديلات التالية على مشروع تطبيقك:
-
عدِّل ملف
build.gradle
على مستوى الوحدة ليصبح تفعيل Multidex وإضافة مكتبة Multidex كملحق، كما هو موضَّح هنا:Groovy
android { defaultConfig { ... minSdkVersion 15 targetSdkVersion 33 multiDexEnabled true } ... } dependencies { implementation "androidx.multidex:multidex:2.0.1" }
Kotlin
android { defaultConfig { ... minSdk = 15 targetSdk = 33 multiDexEnabled = true } ... } dependencies { implementation("androidx.multidex:multidex:2.0.1") }
- اعتمادًا على ما إذا تم إلغاء
Application
، فقم بإجراء أحد الإجراءات التالية:في حال عدم إلغاء
Application
الفئة: عدِّل ملف البيان لضبطandroid:name
في العلامة<application>
على النحو التالي:<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <application android:name="androidx.multidex.MultiDexApplication" > ... </application> </manifest>
في حال إلغاء
Application
الفئة، قم بتغييرها إلىMultiDexApplication
كما يلي:Kotlin
class MyApplication : MultiDexApplication() {...}
Java
public class MyApplication extends MultiDexApplication { ... }
في حال إلغاء
Application
الفئة لكن لا يمكن تغيير الفئة الأساسية، فعندئذ بدلاً من ذلك، إلغاء طريقةattachBaseContext()
والاتصال بـMultiDex.install(this)
للتفعيل :multidex:Kotlin
class MyApplication : SomeOtherApplication() { override fun attachBaseContext(base: Context) { super.attachBaseContext(base) MultiDex.install(this) } }
Java
public class MyApplication extends SomeOtherApplication { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); } }
تنبيه: يجب عدم التنفيذ
MultiDex.install()
أو أي رمز آخر من خلال الانعكاس أو JNI قبل اكتمالMultiDex.install()
. سيساعدك تتبع الارتباطات المتعددة عدم متابعة هذه المكالمات، ما يؤدي إلى حدوثClassNotFoundException
أو التحقّق من الأخطاء بسبب تقسيم فئة غير صالح بين ملفات DEX.
والآن، عندما تنشئ تطبيقك، تُنشئ أدوات تصميم Android رمز DEX أساسيًا.
(classes.dex
) وملفات DEX الداعمة
(classes2.dex
وclasses3.dex
وما إلى ذلك) حسب الحاجة.
بعد ذلك، يعمل نظام الإصدار على تجميع جميع ملفات DEX في حزمة APK.
في وقت التشغيل، بدلاً من البحث فقط في الصفحة الرئيسية
classes.dex
، تستخدم واجهات برمجة التطبيقات المتعددة الإشارات أداة تحميل فئة خاصة للبحث في جميع
ملفات DEX المتاحة لأساليبك.
حدود مكتبة الوسائط المتعددة
هناك بعض القيود المعروفة في مكتبة الوسائط المتعددة. عند دمج المكتبة في إعدادات إصدار التطبيق، يجب مراعاة ما يلي:
- يُعد تثبيت ملفات DEX أثناء بدء التشغيل في قسم بيانات الجهاز أمرًا معقدًا إلى ظهور أخطاء "التطبيق لا يستجيب" (ANR) إذا كانت ملفات DEX الثانوية كبيرة. إلى لتجنُّب هذه المشكلة، يمكنك تفعيل تخفيض حجم الرموز لتقليل النتائج. حجم ملفات DEX وإزالة الأجزاء غير المستخدمة من التعليمات البرمجية.
- عند تشغيل التطبيق على إصدارات أقدم من Android 5.0 (المستوى 21 من واجهة برمجة التطبيقات)، فإن استخدام
لا يكفي استخدام Multidex للتوافق مع الحد الخطي (المشكلة 37008143). تمت زيادة هذا الحد في
Android 4.0 (المستوى 14 من واجهة برمجة التطبيقات)، ولكن لم يحل ذلك المشكلة بالكامل.
في الإصدارات الأقل من Android 4.0، قد تصل إلى حد السرعة الخطية قبل الوصول إلى حد مؤشر DEX. لذلك إذا كنت تستهدف مستويات واجهة برمجة تطبيقات أقل من 14، اختبر جيدًا على تلك الإصدارات من النظام الأساسي، لأن تطبيقك قد إذا واجهت بعض المشكلات عند بدء التشغيل أو عند تحميل مجموعات معينة من الفئات.
يمكن أن يؤدي تصغير الرمز إلى تقليل والقضاء على هذه المشكلات.
يُرجى تعريف الفئات المطلوبة في ملف DEX الأساسي.
عند إنشاء كل ملف DEX لتطبيق متعدد الوسائط، تؤدي أدوات الإنشاء
عملية اتخاذ القرار المعقدة لتحديد الفئات المطلوبة في قيم DEX الأولية
بحيث يمكن بدء التطبيق بنجاح. إذا كانت هناك أي فئة مطلوبة
أثناء بدء التشغيل لم يتم توفيره في ملف DEX الأساسي، فسيتعطّل تطبيقك
مع الخطأ java.lang.NoClassDefFoundError
.
تتعرّف أدوات التصميم على مسارات الرموز البرمجية التي يمكن الوصول إليها مباشرةً من تطبيقك. الرمز. ومع ذلك، يمكن أن تحدث عندما تكون مسارات الرموز البرمجية أقل وضوحًا، مثلاً عندما تتضمّن المكتبة التي تستخدمها والتبعيات المعقدة. على سبيل المثال، إذا كان الرمز يستخدم التأمل الداخلي أو الاستدعاء من طرق Java من خلال التعليمات البرمجية الأصلية، فقد لا يتم التعرف على هذه الفئات المطلوبة في ملف DEX الأساسي.
إذا تلقّيت java.lang.NoClassDefFoundError
، ستصبح
يجب تحديد الفئات الإضافية المطلوبة في رمز DEX الأساسي يدويًا
من خلال تعريفها باستخدام السمة multiDexKeepProguard
في نوع الإصدار. إذا تمت مطابقة فئة في
ملف multiDexKeepProguard
، ثم الفئة
تتم إضافته إلى ملف DEX الأساسي.
خاصية MultiDexKeepProguard
يستخدم ملف multiDexKeepProguard
التنسيق نفسه المستخدَم في ProGuard، ويتوافق مع
قواعد ProGuard بالكامل. لمزيد من المعلومات عن طريقة تخصيص المعلومات المحفوظة في تطبيقك، يُرجى الاطّلاع على
تخصيص الرمز الذي تريد الاحتفاظ به
يجب أن يحتوي الملف الذي تحدّده في multiDexKeepProguard
على -keep
.
بأي بنية ProGuard صالحة. على سبيل المثال:
-keep com.example.MyClass.class
يمكنك إنشاء ملف يسمى
multidex-config.pro
الذي يبدو كما يلي:
-keep class com.example.MyClass -keep class com.example.MyClassToo
إذا كنت تريد تحديد جميع الفئات في حزمة، سيبدو الملف كما يلي:
-keep class com.example.** { *; } // All classes in the com.example package
بعد ذلك، يمكنك الإعلان عن هذا الملف لنوع إصدار كما يلي:
Groovy
android { buildTypes { release { multiDexKeepProguard file('multidex-config.pro') ... } } }
Kotlin
android { buildTypes { getByName("release") { multiDexKeepProguard = file("multidex-config.pro") ... } } }
تحسين أداء متعدد القنوات في إصدارات التطوير
يتطلب الإعداد المتعدّد الأذونات زيادة كبيرة في معالجة الإصدار. لأن نظام التصميم يجب أن يتخذ قرارات معقدة بشأن الفئات في ملف DEX الأساسي والفئات التي يمكن تضمينها ملفات DEX الثانوية. هذا يعني أنّ الإصدارات التدريجية التي تستخدم تحليلاً متعدّدًا عادةً يستغرق وقتًا أطول وقد يؤدي إلى إبطاء عملية التطوير.
للتخفيف من أوقات الإنشاء المتزايدة، استخدم
pre-dexing لإعادة استخدام إخراج Multidex بين الإصدارات.
يعتمد التحليل المسبق على تنسيق ART الذي لا يتوفّر إلا على Android 5.0
(المستوى 21 من واجهة برمجة التطبيقات) والإصدارات الأحدث إذا كنت تستخدم "استوديو Android"، سيستخدم IDE تلقائيًا ميزة الفهرسة المُسبقة.
عند نشر تطبيقك على جهاز يعمل بالإصدار 5.0 من نظام التشغيل Android (المستوى 21 من واجهة برمجة التطبيقات) أو بإصدارات أحدث.
ومع ذلك، إذا كنت تشغل إصدارات Gradle من سطر الأوامر، فيجب تعيين
من minSdkVersion
إلى 21 أو أعلى لتفعيل التحكّم المسبق.
minSdkVersion
،
كما هو موضح:
Groovy
android { defaultConfig { ... multiDexEnabled true // The default minimum API level you want to support. minSdkVersion 15 } productFlavors { // Includes settings you want to keep only while developing your app. dev { // Enables pre-dexing for command-line builds. When using // Android Studio 2.3 or higher, the IDE enables pre-dexing // when deploying your app to a device running Android 5.0 // (API level 21) or higher, regardless of minSdkVersion. minSdkVersion 21 } prod { // If you've configured the defaultConfig block for the production version of // your app, you can leave this block empty and Gradle uses configurations in // the defaultConfig block instead. You still need to include this flavor. // Otherwise, all variants use the "dev" flavor configurations. } } buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation "androidx.multidex:multidex:2.0.1" }
Kotlin
android { defaultConfig { ... multiDexEnabled = true // The default minimum API level you want to support. minSdk = 15 } productFlavors { // Includes settings you want to keep only while developing your app. create("dev") { // Enables pre-dexing for command-line builds. When using // Android Studio 2.3 or higher, the IDE enables pre-dexing // when deploying your app to a device running Android 5.0 // (API level 21) or higher, regardless of minSdkVersion. minSdk = 21 } create("prod") { // If you've configured the defaultConfig block for the production version of // your app, you can leave this block empty and Gradle uses configurations in // the defaultConfig block instead. You still need to include this flavor. // Otherwise, all variants use the "dev" flavor configurations. } } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") } } } dependencies { implementation("androidx.multidex:multidex:2.0.1") }
للاطّلاع على مزيد من الاستراتيجيات للمساعدة في تحسين سرعات التصميم، سواء من "استوديو Android" أو من خلال أمر الأوامر يُرجى قراءة المقالة تحسين سرعة الإصدار. لمزيد من المعلومات عن استخدام صيغ الإصدار، يُرجى الاطّلاع على ضبط صيغ الإصدار
ملاحظة: إذا كانت لديك صيغ مختلفة لإصدارات مختلفة
متعددة، يمكنك تقديم ملف بيان مختلف لكل منها
لذلك، لا يتم تغيير سوى ملف المستوى 20 لواجهة برمجة التطبيقات الأقل
اسم العلامة <application>
يمكنك أيضًا
إنشاء فئة فرعية Application
مختلفة لكل خيار منتج
الفئة الفرعية فقط للمستوى 20 من واجهة برمجة التطبيقات والأدنى هي التي تضيف الفئة MultiDexApplication
أو
يتصل بـ MultiDex.install(this)
.
اختبار تطبيقات Multidex
عند كتابة اختبارات قياس حالة تطبيقات Multidex، لا حاجة إلى ضبط أي إعدادات إضافية.
إذا كنت تستخدم
MonitoringInstrumentation
أو
AndroidJUnitRunner
الأدوات. في حال استخدام عنوان URL آخر
Instrumentation
,
فمن ثم، يجب عليك إلغاء طريقة onCreate()
الخاصة بها باستخدام الرمز التالي:
Kotlin
fun onCreate(arguments: Bundle) { MultiDex.install(targetContext) super.onCreate(arguments) ... }
Java
public void onCreate(Bundle arguments) { MultiDex.install(getTargetContext()); super.onCreate(arguments); ... }