अगर आपके ऐप्लिकेशन में एपीआई 20 या उससे पहले के वर्शन का minSdk
है और आपका ऐप्लिकेशन और
जिन लाइब्रेरी का रेफ़रंस 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. यह नंबर उन रेफ़रंस की कुल संख्या दिखाता है जिन्हें जिसे किसी एक Delvik वित्तीय सेवा देने वाले (DEX) बाइट कोड फ़ाइल के कोड से शुरू किया गया हो. इस पेज पर बताया गया है कि multidex नाम की ऐप्लिकेशन कॉन्फ़िगरेशन को चालू करना, जिससे आपके ऐप्लिकेशन को का इस्तेमाल करें.
64 हज़ार पहचान सीमा के बारे में जानकारी
Android ऐप्लिकेशन (APK) की फ़ाइलों में, एक्ज़ीक्यूटेबल बाइट कोड फ़ाइलें होती हैं Dalvik का एक्ज़ीक्यूटेबल (DEX) फ़ाइलें, जिनमें आपके ऐप्लिकेशन को चलाने के लिए इस्तेमाल किया जाने वाला कंपाइल कोड होता है. डलास के हिसाब से दिए गए नियमों में, उन तरीकों की कुल संख्या को सीमित किया जाता है जो एक DEX फ़ाइल में 65,536 तक का संदर्भ दिया जा सकता है—इसमें Android भी शामिल है फ़्रेमवर्क के तरीके, लाइब्रेरी के तरीके, और तरीकों की जानकारी अपने कोड में शामिल करें.
इस कंप्यूटर साइंस के संदर्भ में, किलो या K शब्द 1024 दिखाता है (या 2^10). 65,536 का साइज़ 64x1024 के बराबर होता है. इसलिए, इस सीमा को _64K में रेफ़रंस की सीमा तय की गई_.Android 5.0 से पहले के वर्शन के लिए मल्टीडेक्स सहायता
Android 5.0 (एपीआई लेवल 21) से पहले के प्लैटफ़ॉर्म के वर्शन में, Delvik का इस्तेमाल किया जाता है
किसी ऐप्लिकेशन कोड को चलाने के लिए रनटाइम. डिफ़ॉल्ट रूप से, Delvik ऐप्लिकेशन को एक बार में एक
हर APK के लिए classes.dex
बाइट कोड फ़ाइल. इससे बचने के लिए
सीमा है, तो मल्टीडेक्स लाइब्रेरी को मॉड्यूल-लेवल build.gradle
में जोड़ें या
build.gradle.kts
फ़ाइल:
ग्रूवी
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 फ़ाइलों और उनमें मौजूद कोड के ऐक्सेस को मैनेज करता है. इस लाइब्रेरी का मौजूदा वर्शन देखने के लिए, यह देखें मल्टीडेक्स वर्शन में उपलब्ध है.
ज़्यादा जानकारी के लिए, मल्टीडेक्स के लिए अपने ऐप्लिकेशन को कॉन्फ़िगर करें.Android 5.0 और इसके बाद के वर्शन के लिए Multidex की सुविधा
Android 5.0 (एपीआई लेवल 21) और उसके बाद के वर्शन, ART नाम के रनटाइम का इस्तेमाल करते हैं
मूल रूप से, APK फ़ाइलों से कई DEX फ़ाइलें लोड करने की सुविधा मिलती है. एआरटी
ऐप्लिकेशन इंस्टॉल के समय पूर्व-संकलन करता है,
classesN.dex
फ़ाइलें और उन्हें एक में कंपाइल करना
इसके लिए OAT फ़ाइल
Android डिवाइस पर लागू होता है. इसलिए, अगर आपका minSdkVersion
21 या उससे ज़्यादा है, मल्टीडेक्स डिफ़ॉल्ट रूप से चालू है और आपको मल्टीडेक्स लाइब्रेरी की ज़रूरत नहीं है.
Android 5.0 के बारे में ज़्यादा जानकारी पाने के लिए रनटाइम, Android रनटाइम (ART) और Delvik को पढ़ें.
ध्यान दें: Android Studio का इस्तेमाल करके अपना ऐप्लिकेशन चलाते समय, बिल्ड को उन टारगेट डिवाइसों के हिसाब से ऑप्टिमाइज़ किया गया है जिन पर आपका ऐप्लिकेशन काम करता है. इसमें, टारगेट किए गए डिवाइसों के चलने के दौरान मल्टीडेक्स को चालू करना शामिल है Android 5.0 और इसके बाद के वर्शन. चूंकि यह ऑप्टिमाइज़ेशन केवल तभी लागू होता है, जब Android Studio का इस्तेमाल करने पर, आपको अब भी रिलीज़ बिल्ड को कॉन्फ़िगर करना पड़ सकता है मल्टीडेक्स के लिए 64K सीमा से बचने के लिए भी ऐसा ही करें.
64 हज़ार की सीमा पार करने से बचें
अपने ऐप्लिकेशन को 64K या इससे ज़्यादा तरीकों के रेफ़रंस के तौर पर इस्तेमाल करने के लिए कॉन्फ़िगर करने से पहले, यह तरीका अपनाएं आपके ऐप्लिकेशन कोड से कॉल किए गए रेफ़रंस की कुल संख्या को कम करने के लिए, इसमें आपके ऐप्लिकेशन कोड या शामिल लाइब्रेरी की जानकारी शामिल होती है.
नीचे दी गई रणनीतियों की मदद से, DEX पहचान सीमा के अंदर आने से बचा जा सकता है:
- अपने ऐप्लिकेशन की डायरेक्ट और ट्रांज़िटिव डिपेंडेंसी की समीक्षा करना
- ध्यान रखें कि आपने अपने ऐप्लिकेशन में बड़ी लाइब्रेरी डिपेंडेंसी शामिल की है या नहीं, इसकी वैल्यू कोड की तय सीमा से ज़्यादा है को ऐप में जोड़ा जा रहा है. एक बहुत बड़ी लाइब्रेरी को शामिल करना, एक आम लेकिन समस्या वाला पैटर्न है क्योंकि कुछ उपयोगी तरीके उपयोगी थे. ऐप्लिकेशन कोड डिपेंडेंसी कम करने से, अक्सर आप DEX पहचान सीमा से बच जाते हैं.
- R8 की मदद से इस्तेमाल नहीं किए गए कोड को हटाएं
- R8 चलाने के लिए, कोड छोटा करने की सुविधा चालू करें का सुझाव भी देता है. श्रिंकिंग की सुविधा चालू करें, ताकि यह पक्का किया जा सके कि आपके APK के साथ इस्तेमाल न किया गया कोड नहीं भेज रहे हैं. अगर कोड का आकार छोटा करने की सुविधा को सही तरीके से कॉन्फ़िगर किया गया है, तो आपकी डिपेंडेंसी से इस्तेमाल नहीं होने वाले कोड और रिसॉर्स को भी हटा सकता है.
इन तकनीकों का इस्तेमाल करके आप अपने APK का कुल साइज़ कम कर सकते हैं और अपने ऐप्लिकेशन में मल्टीडेक्स की ज़रूरत से बचें.
मल्टीडेक्स के लिए अपने ऐप्लिकेशन को कॉन्फ़िगर करें
ध्यान दें: अगर आपकाminSdkVersion
21 या उससे बाद पर सेट है, तो मल्टीडेक्स डिफ़ॉल्ट रूप से चालू रहता है
और आपको मल्टीडेक्स लाइब्रेरी की ज़रूरत नहीं है.
अगर आपके minSdkVersion
को 20 या इससे कम पर सेट किया गया है, तो
को
multidex लाइब्रेरी और
आपके ऐप्लिकेशन प्रोजेक्ट में ये बदलाव किए गए हैं:
-
मॉड्यूल-लेवल
build.gradle
फ़ाइल को इसमें बदलें मल्टीडेक्स को चालू करें और मल्टीडेक्स लाइब्रेरी को डिपेंडेंसी के तौर पर जोड़ें, जैसा कि यहां दिखाया गया है:ग्रूवी
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)
को कॉल करें मल्टीडेक्स: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
वगैरह) ज़रूरत के मुताबिक.
इसके बाद, बिल्ड सिस्टम आपके APK में सभी DEX फ़ाइलों को पैकेज कर देता है.
रनटाइम के दौरान, सिर्फ़ मुख्य ऐप्लिकेशन में खोजने के बजाय
classes.dex
फ़ाइल है, तो मल्टीडेक्स एपीआई
आपके तरीकों के लिए उपलब्ध DEX फ़ाइलें.
मल्टीडेक्स लाइब्रेरी की सीमाएं
मल्टीडेक्स लाइब्रेरी की कुछ सीमाएं हैं जिनके बारे में पहले से जानकारी है. अपने ऐप्लिकेशन के बिल्ड कॉन्फ़िगरेशन में लाइब्रेरी को शामिल करते समय, इन बातों का ध्यान रखें:
- किसी डिवाइस के डेटा पार्टीशन पर स्टार्टअप के दौरान DEX फ़ाइलों को इंस्टॉल करना जटिल और सेकंडरी DEX फ़ाइलें बड़ी होने पर, ऐप्लिकेशन में कोई समस्या है (एएनआर) की गड़बड़ियां दिख सकती हैं. यहां की यात्रा पर हूं इस समस्या से बचने के लिए, कोड को छोटा करने की सुविधा चालू करें DEX फ़ाइलों का साइज़ बदल सकते हैं और कोड के इस्तेमाल न किए गए हिस्से हटा सकते हैं.
- Android 5.0 (एपीआई लेवल 21) से पहले के वर्शन पर चलाते समय,
मल्टीडेक्स, लीनियरएलोक सीमा (समस्या 37008143) के आस-पास काम करने के लिए काफ़ी नहीं है. यह सीमा इतनी बढ़ाई गई
Android 4.0 (एपीआई लेवल 14) के वर्शन के साथ काम करता है, लेकिन इससे समस्या पूरी तरह से हल नहीं हुई.
Android 4.0 से पहले के वर्शन पर, हो सकता है कि आप लीनियर ऐलोकेशन की सीमा तक पहले पहुंच जाएं DEX इंडेक्स की सीमा तक पहुंच रहा है. इसलिए, अगर एपीआई लेवल इससे नीचे वाले लेवल को टारगेट किया जा रहा है 14, प्लैटफ़ॉर्म के उन वर्शन की अच्छी तरह से जांच कर लें, क्योंकि आपका ऐप्लिकेशन स्टार्टअप पर या क्लास के किसी ग्रुप के लोड होने पर समस्याएं हों.
कोड छोटा करने की सुविधा का इस्तेमाल करके, इस समस्या को हल किया जा सकता है.
मुख्य DEX फ़ाइल में ज़रूरी क्लास के बारे में बताएं
किसी मल्टीडेक्स ऐप्लिकेशन के लिए हर DEX फ़ाइल बनाते समय, बिल्ड टूल अच्छी परफ़ॉर्मेंस देते हैं
यह तय करने के लिए मुश्किल फ़ैसले लेना कि प्राइमरी DEX में किस क्लास की ज़रूरत है
फ़ाइल में मौजूद है ताकि आपका ऐप्लिकेशन सफलतापूर्वक शुरू हो सके. अगर किसी क्लास की जानकारी देना ज़रूरी है, तो
शुरू करने के दौरान प्राथमिक DEX फ़ाइल में नहीं दिया गया है, तो आपका ऐप्लिकेशन क्रैश हो जाता है
java.lang.NoClassDefFoundError
गड़बड़ी हुई.
बिल्ड टूल, ऐसे कोड के कोड पाथ की पहचान करता है जिसे सीधे आपके ऐप्लिकेशन से ऐक्सेस किया जाता है कोड. हालांकि, यह समस्या हो सकती है ये तब होते हैं, जब कोड पाथ कम दिखते हैं, जैसे कि जब इस्तेमाल की जाने वाली लाइब्रेरी में जटिल डिपेंडेंसी. उदाहरण के लिए, अगर कोड में आत्मनिरीक्षण या शुरू करने की कोशिश का इस्तेमाल किया गया है का इस्तेमाल किया है, तो हो सकता है कि उन क्लास की पहचान प्राथमिक 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
इसके बाद, बिल्ड टाइप के लिए उस फ़ाइल का एलान इस तरह किया जा सकता है:
ग्रूवी
android { buildTypes { release { multiDexKeepProguard file('multidex-config.pro') ... } } }
Kotlin
android { buildTypes { getByName("release") { multiDexKeepProguard = file("multidex-config.pro") ... } } }
डेवलपमेंट बिल्ड में मल्टीडेक्स को ऑप्टिमाइज़ करें
मल्टीडेक्स कॉन्फ़िगरेशन के लिए बिल्ड प्रोसेसिंग में काफ़ी बढ़ोतरी करने की ज़रूरत है समय पर पाबंदी लगा दी जाती है, क्योंकि बिल्ड सिस्टम को यह तय करना होता है कि कौनसे क्लास प्राथमिक DEX फ़ाइल में शामिल होना चाहिए और कौन-सी क्लास में शामिल किया जा सकता है दूसरी DEX फ़ाइलें शामिल की जाती हैं. इसका मतलब है कि आम तौर पर मल्टीडेक्स का इस्तेमाल करने वाले इंक्रीमेंटल बिल्ड इसमें ज़्यादा समय लगता है और इससे आपकी डेवलपमेंट प्रोसेस धीमी हो सकती है.
बिल्ड में लगने वाले ज़्यादा समय को कम करने के लिए,
प्री-डेक्सिंग का इस्तेमाल करें, ताकि बिल्ड के बीच मल्टीडेक्स आउटपुट का फिर से इस्तेमाल किया जा सके.
प्री-डेक्सिंग, सिर्फ़ Android 5.0 पर उपलब्ध एआरटी फ़ॉर्मैट के हिसाब से होती है
(एपीआई लेवल 21) और उसके बाद वाले वर्शन. Android Studio का इस्तेमाल करने पर, आईडीई अपने-आप प्री-डेक्सिंग का इस्तेमाल करता है
Android 5.0 (एपीआई लेवल 21) या उसके बाद के वर्शन वाले डिवाइस पर अपना ऐप्लिकेशन डिप्लॉय करते समय.
हालांकि, अगर कमांड लाइन से Gradle बिल्ड चलाया जा रहा है, तो आपको
प्री-डेक्सिंग चालू करने के लिए, minSdkVersion
से 21 या उससे ज़्यादा.
minSdkVersion
के लिए अलग-अलग मान,
जैसा कि दिखाया गया है:
ग्रूवी
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 Studio या 'निर्देश' की मदद से, बिल्ड की स्पीड बढ़ाने के लिए ज़्यादा रणनीतियां लाइन में, अपने बिल्ड की स्पीड ऑप्टिमाइज़ करें लेख पढ़ें. बिल्ड के वैरिएंट का इस्तेमाल करने के बारे में ज़्यादा जानने के लिए, यहां देखें बिल्ड वैरिएंट कॉन्फ़िगर करें.
सलाह: अगर आपके पास अलग-अलग प्रॉडक्ट के लिए अलग-अलग बिल्ड वैरिएंट हैं
मल्टीडेक्स ज़रूरतों के लिए, आप हर एक फ़ाइल के लिए एक अलग मेनिफ़ेस्ट फ़ाइल दे सकते हैं
वैरिएंट वाले वर्शन का इस्तेमाल करने से पहले
<application>
टैग का नाम. आप यह भी कर सकते हैं
हर वैरिएंट के लिए एक अलग Application
सब-क्लास बनाएं, ताकि
सिर्फ़ एपीआई लेवल 20 और उससे पहले के लेवल के लिए सब-क्लास, MultiDexApplication
क्लास को बढ़ाती है या
MultiDex.install(this)
को कॉल करता है.
मल्टीडेक्स ऐप्लिकेशन को टेस्ट करें
मल्टीडेक्स ऐप्लिकेशन के लिए इंस्ट्रुमेंटेशन टेस्ट लिखते समय, किसी अतिरिक्त कॉन्फ़िगरेशन की ज़रूरत नहीं होती
अगर आप किसी
MonitoringInstrumentation
या
AndroidJUnitRunner
इंस्ट्रुमेंटेशन चुनें. अगर आपको किसी अन्य
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); ... }