अपने ऐप्लिकेशन को जितना हो सके उतना छोटा और तेज़ बनाने के लिए, आपको उसे ऑप्टिमाइज़ और छोटा करना होगा
isMinifyEnabled = true
के साथ आपका रिलीज़ बिल्ड.
ऐसा करने पर, साइट के कॉन्फ़िगरेशन को छोटा करने की सुविधा चालू हो जाती है. इससे, इस्तेमाल न होने वाले कोड और रिसॉर्स हट जाते हैं; अस्पष्ट बनाना, जिससे आपके ऐप्लिकेशन की क्लास और सदस्यों के नाम छोटे हो जाते हैं; और ऑप्टिमाइज़ेशन, टारगेटिंग को कम करने के लिए ज़्यादा असरदार रणनीतियां लागू करता है साइज़ और ऐप्लिकेशन की परफ़ॉर्मेंस को बेहतर बना सकते हैं. इस पेज में बताया गया है कि कैसे R8 आपके प्रोजेक्ट के लिए कंपाइल टाइम के ये टास्क करता है. साथ ही, यह भी बताता है कि इसे किस तरह कस्टमाइज़ किया जा सकता है उन्हें.
जब इसका इस्तेमाल करके प्रोजेक्ट बनाया जाता है Android Gradle प्लग इन 3.4.0 या इसके बाद वाला वर्शन, प्लगिन, कंपाइल-टाइम कोड ऑप्टिमाइज़ेशन के लिए, अब ProGuard का इस्तेमाल नहीं करता है. इसके बजाय, प्लगिन R8 कंपाइलर के साथ काम करके, नीचे बताए गए काम करता है कंपाइल-टाइम टास्क:
- कोड श्रिंकिंग (या पेड़ का झटका): इस्तेमाल न होने वाली चीज़ों का पता लगाता है और उन्हें सुरक्षित तरीके से हटाता है आपके ऐप्लिकेशन और उसकी लाइब्रेरी की क्लास, फ़ील्ड, तरीके, और एट्रिब्यूट डिपेंडेंसी (इसे डिजिटल लर्निंग की मदद से, 64 हज़ार पहचान फ़ाइलाें की सीमा). उदाहरण के लिए, अगर आपको लाइब्रेरी डिपेंडेंसी के कुछ ही एपीआई. छोटा करने से लाइब्रेरी कोड की पहचान हो सकती है कि आपका ऐप्लिकेशन इस्तेमाल नहीं कर रहा है और अपने ऐप्लिकेशन से सिर्फ़ उस कोड को हटाएं. यहां की यात्रा पर हूं कोड का साइज़ छोटा करने का तरीका बताने वाले सेक्शन पर जाएं.
- संसाधन का छोटा करना: इस्तेमाल न किए जाने वाले रिसॉर्स को आपके पैकेज किए गए ऐप्लिकेशन से हटा देता है, इसमें आपके ऐप्लिकेशन की लाइब्रेरी डिपेंडेंसी में इस्तेमाल न किए जाने वाले संसाधन भी शामिल होते हैं. यह इसमें काम करता है: कोड को इस तरह छोटा करना कि इस्तेमाल न किया गया कोड हटा दिया जाए, ऐसे संसाधन भी हटाए जा सकते हैं जिनका रेफ़रंस अब नहीं दिया जाता. सीखने में ज़्यादा जानकारी के लिए, संसाधनों का दायरा कम कर दें.
- ऑप्टिमाइज़ेशन: रनटाइम को बेहतर बनाने के लिए, आपके कोड की जांच करता है और उसे फिर से लिखता है
और अपने ऐप्लिकेशन की DEX फ़ाइलों का साइज़ कम किया जा सकता है. यह
कोड के रनटाइम की परफ़ॉर्मेंस को 30% तक बढ़ाता है. इससे
स्टार्टअप और फ़्रेम टाइम. उदाहरण के लिए, अगर R8 को पता चलता है कि
else {}
दिए गए अगर/अन्य स्टेटमेंट के लिए ब्रांच कभी नहीं ली जाती है, तो R8else {}
की ब्रांच. इसके बारे में ज़्यादा जानने के लिए, कोड ऑप्टिमाइज़ेशन. - अस्पष्ट बनाने (या आइडेंटिफ़ायर छोटा करने)): इससे क्लास का नाम छोटा हो जाता है जिससे DEX फ़ाइल का साइज़ कम हो जाता है. ज़्यादा जानकारी के लिए, इस लिंक पर जाएं सेक्शन में, अपने कोड को अस्पष्ट बनाने का तरीका जानें.
अपने ऐप्लिकेशन का रिलीज़ वर्शन बनाते समय, R8 को परफ़ॉर्मेंस के लिए कॉन्फ़िगर किया जा सकता है आपके लिए ऊपर बताए गए कंपाइल-टाइम टास्क. कुछ खास जानकारी को भी बंद किया जा सकता है ProGuard नियमों वाली फ़ाइलों की मदद से टास्क को कस्टमाइज़ कर सकते हैं या R8 के काम करने के तरीके को पसंद के मुताबिक बना सकते हैं. असल में, R8 आपकी सभी मौजूदा ProGuard नियमों वाली फ़ाइलों के साथ काम करता है. इसलिए Android Gradle प्लग इन को R8 का इस्तेमाल करने के लिए अपडेट करने पर, मौजूदा नियम सेट करें.
छोटा करने, अस्पष्ट बनाने, और ऑप्टिमाइज़ेशन की सुविधा चालू करें
Android Studio 3.4 या 'Android Gradle प्लग इन 3.4.0' और इसके बाद वाले वर्शन का इस्तेमाल करने पर, R8 यह डिफ़ॉल्ट कंपाइलर है, जो आपके प्रोजेक्ट के Java बाइटकोड को DEX में बदल देता है Android प्लैटफ़ॉर्म पर काम करता है. हालांकि, नया प्रोजेक्ट बनाने पर Android Studio का इस्तेमाल करने, छोटा करने, अस्पष्ट बनाने, और कोड ऑप्टिमाइज़ेशन डिफ़ॉल्ट रूप से चालू रहता है. ऐसा इसलिए होता है, क्योंकि कंपाइल-टाइम ऑप्टिमाइज़ेशन की वजह से समय तय करते हैं और ज़रूरत के मुताबिक न होने पर गड़बड़ियां हो सकती हैं अपनी पसंद के मुताबिक तय करें कि कौनसा कोड रखना है.
इसलिए, बेहतर होगा कि फ़ाइनल वर्शन बनाते समय, कंपाइल टाइम के इन टास्क को चालू कर दें जिसे आपने पब्लिश करने से पहले टेस्ट किया है. छोटा करने, अस्पष्ट बनाने, और ऑप्टिमाइज़ेशन के लिए, अपनी प्रोजेक्ट-लेवल की बिल्ड स्क्रिप्ट में ये शामिल करें.
Kotlin
android { buildTypes { getByName("release") { // Enables code shrinking, obfuscation, and optimization for only // your project's release build type. Make sure to use a build // variant with `isDebuggable=false`. isMinifyEnabled = true // Enables resource shrinking, which is performed by the // Android Gradle plugin. isShrinkResources = true proguardFiles( // Includes the default ProGuard rules files that are packaged with // the Android Gradle plugin. To learn more, go to the section about // R8 configuration files. getDefaultProguardFile("proguard-android-optimize.txt"), // Includes a local, custom Proguard rules file "proguard-rules.pro" ) } } ... }
ग्रूवी
android { buildTypes { release { // Enables code shrinking, obfuscation, and optimization for only // your project's release build type. Make sure to use a build // variant with `debuggable false`. minifyEnabled true // Enables resource shrinking, which is performed by the // Android Gradle plugin. shrinkResources true // Includes the default ProGuard rules files that are packaged with // the Android Gradle plugin. To learn more, go to the section about // R8 configuration files. proguardFiles getDefaultProguardFile( 'proguard-android-optimize.txt'), 'proguard-rules.pro' } } ... }
R8 कॉन्फ़िगरेशन फ़ाइलें
R8, ProGuard नियमों वाली फ़ाइलों का इस्तेमाल करके, डिफ़ॉल्ट ऐक्शन और बेहतर काम करता है अपने ऐप्लिकेशन के स्ट्रक्चर को समझना. जैसे, वे क्लास जो एंट्री पॉइंट के तौर पर काम करती हैं कोड में बदलें. हालांकि आप इनमें से कुछ नियम फ़ाइलों में बदलाव कर सकते हैं, लेकिन कुछ ऐसे नियम जो कंपाइल-टाइम टूल, जैसे कि AAPT2 या इनहेरिट किया जाता है. नीचे दी गई टेबल में, ProGuard के नियमों वाली फ़ाइलों के सोर्स, जिनका इस्तेमाल R8 करता है.
स्रोत | जगह की जानकारी | ब्यौरा |
Android Studio | <module-dir>/proguard-rules.pro
|
जब Android Studio का इस्तेमाल करके कोई नया मॉड्यूल बनाया जाता है, तो IDE
proguard-rules.pro फ़ाइल को उस मॉड्यूल की रूट डायरेक्ट्री में रखें.
डिफ़ॉल्ट रूप से, इस फ़ाइल पर कोई नियम लागू नहीं होता. इसलिए, अपनी क्वेरी शामिल करें ProGuard के नियम यहां दिए गए हैं, जैसे कि पसंद के मुताबिक नियम बनाए रखें. |
'Android Gradle प्लग इन' | कंपाइल करते समय 'Android Gradle प्लग इन' से जनरेट किया जाता है. | 'Android Gradle प्लग इन' जनरेट करता है
proguard-android-optimize.txt , जिसमें ऐसे नियम शामिल हैं जो
ज़्यादातर Android प्रोजेक्ट के लिए फ़ायदेमंद होती है और इसकी मदद से,
@Keep*
एनोटेशन.
डिफ़ॉल्ट रूप से, Android Studio का इस्तेमाल करके नया मॉड्यूल बनाते समय, मॉड्यूल-लेवल बिल्ड स्क्रिप्ट में आपके रिलीज़ बिल्ड में इस नियम फ़ाइल को शामिल किया जाता है आपके लिए.
ध्यान दें: 'Android Gradle प्लग इन' में पहले से तय किया गया एक और ProGuard शामिल है
नियम फ़ाइलों का उपयोग कर सकते हैं, लेकिन यह सुझाव दिया जाता है कि आप
|
लाइब्रेरी डिपेंडेंसी |
एएआर लाइब्रेरी में:
JAR लाइब्रेरी में: इन जगहों के अलावा, Android Gradle प्लग इन 3.6 या इसके बाद वाले वर्शन भी टारगेट किए गए, श्रिंक करने से जुड़े नियमों का इस्तेमाल किया जा सकता है. |
अगर कोई एएआर या जेएआर लाइब्रेरी अपनी नियम वाली फ़ाइल के साथ पब्लिश की जाती है, और आपको उस लाइब्रेरी को कंपाइल-टाइम डिपेंडेंसी के तौर पर शामिल करें, R8 अपने-आप आपके प्रोजेक्ट को कंपाइल करते समय उन नियमों को लागू करता है. पारंपरिक ProGuard नियमों के अलावा, Android Gradle प्लग इन 3.6 या उससे बाद का वर्शन भी काम करता है टारगेट किए गए, छोटा करने के नियम. ये नियम हैं जो खास श्रिंकर (R8 या ProGuard) के साथ-साथ खास श्रिंकर को टारगेट करते हैं. श्रिंकर वर्शन. लाइब्रेरी के साथ पैकेज की गई नियम वाली फ़ाइलों का इस्तेमाल करना तब फ़ायदेमंद होता है, जब लाइब्रेरी के ठीक से काम करने के लिए नियमों की आवश्यकता होती है—यानी, लाइब्रेरी डेवलपर ने आपके लिए समस्या हल करने वाले चरण पूरे कर लिए हैं. हालांकि, आपको यह पता होना चाहिए कि नियम योगज हैं, लाइब्रेरी डिपेंडेंसी में शामिल कुछ नियम हटाए नहीं जा सकते. आपके ऐप्लिकेशन के अन्य हिस्सों के कंपाइलेशन पर असर पड़ सकता है. उदाहरण के लिए, अगर लाइब्रेरी में कोड ऑप्टिमाइज़ेशन को बंद करने का नियम शामिल है, तो वह नियम बंद हो जाता है ऑप्टिमाइज़ेशन की सेवा का इस्तेमाल किया जा सकता है. |
Android ऐसेट पैकेज टूल 2 (AAPT2) | minifyEnabled true के साथ अपना प्रोजेक्ट बनाने के बाद:
<module-dir>/build/intermediates/aapt_proguard_file/.../aapt_rules.txt
|
AAPT2, आपके ऐप्लिकेशन की क्लास के रेफ़रंस के आधार पर, Keep के नियम जनरेट करता है मेनिफ़ेस्ट, लेआउट, और अन्य ऐप्लिकेशन संसाधन उपलब्ध हैं. उदाहरण के लिए, AAPT2 में अपने ऐप्लिकेशन के मेनिफ़ेस्ट में रजिस्टर की जाने वाली हर गतिविधि के लिए, एंट्री पॉइंट. |
कस्टम कॉन्फ़िगरेशन फ़ाइलें | डिफ़ॉल्ट रूप से, जब Android Studio का इस्तेमाल करके नया मॉड्यूल बनाया जाता है, तो IDE
ने आपके लिए <module-dir>/proguard-rules.pro बनाया, ताकि आप अपना खुद का जोड़ सकें
नियम.
|
आपके पास अन्य कॉन्फ़िगरेशन शामिल करने का विकल्प होता है. और R8 उन्हें कंपाइल के समय पर लागू करता है. |
minifyEnabled
प्रॉपर्टी को true
पर सेट करने पर, R8 में सभी नियमों को जोड़ा जाता है
ऊपर दिए गए सभी स्रोतों की सूची देखें. यह याद रखना ज़रूरी है कि आपको
R8 की मदद से समस्या हल करें, क्योंकि कंपाइल-टाइम की अन्य डिपेंडेंसी,
जैसे कि लाइब्रेरी डिपेंडेंसी जैसी सुविधाओं के साथ, R8 के व्यवहार में बदलाव हो सकते हैं
मुझे नहीं पता.
उन सभी नियमों की पूरी रिपोर्ट पाने के लिए जिन्हें R8 ने बनाया है और
प्रोजेक्ट के तहत, अपने मॉड्यूल की proguard-rules.pro
फ़ाइल में इन्हें शामिल करें:
// You can specify any path and filename.
-printconfiguration ~/tmp/full-r8-config.txt
टारगेट किए गए श्रिंक नियम
'Android Gradle प्लग इन 3.6' या इसके बाद वाला वर्शन, लाइब्रेरी की सुविधा के साथ काम करता है टारगेट करने वाले नियम खास श्रिंकर (R8 या ProGuard), और खास श्रिंकर वर्शन. यह इससे लाइब्रेरी डेवलपर, प्रोजेक्ट में बेहतर तरीके से काम करने के लिए अपने नियम खुद बना सकते हैं जो श्रिंकर वर्शन के नए वर्शन का इस्तेमाल करते हैं, लेकिन मौजूदा नियमों को पुराने श्रिन्कर वर्शन वाले प्रोजेक्ट में इस्तेमाल किया जाता है.
टारगेट किए गए साइज़ कम करने के नियम तय करने के लिए, लाइब्रेरी डेवलपर को उन्हें शामिल करना होगा एएआर या जेएआर लाइब्रेरी के अंदर खास जगहों पर.
In an AAR library:
proguard.txt (legacy location)
classes.jar
└── META-INF
└── com.android.tools (targeted shrink rules location)
├── r8-from-<X>-upto-<Y>/<R8-rules-file>
└── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>
In a JAR library:
META-INF
├── proguard/<ProGuard-rules-file> (legacy location)
└── com.android.tools (targeted shrink rules location)
├── r8-from-<X>-upto-<Y>/<R8-rules-file>
└── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>
इसका मतलब है कि टारगेट किए गए श्रिंक नियमों को META-INF/com.android.tools
में सेव किया जाता है
JAR की डायरेक्ट्री या इसके अंदर की META-INF/com.android.tools
डायरेक्ट्री में
एएआर का classes.jar
.
उस डायरेक्ट्री में, नाम के साथ कई डायरेक्ट्री हो सकती हैं
r8-from-<X>-upto-<Y>
या proguard-from-<X>-upto-<Y>
का इस्तेमाल करके यह बताएं कि
ऐसे वर्शन जिनके लिए डायरेक्ट्री में मौजूद नियमों को छोटा करने की ज़रूरत होती है.
ध्यान दें कि -from-<X>
और -upto-<Y>
वाले हिस्से ज़रूरी नहीं हैं, <Y>
वर्शन
एक्सक्लूज़िव है और वर्शन की रेंज जारी होनी चाहिए.
उदाहरण के लिए, r8-upto-8.0.0
, r8-from-8.0.0-upto-8.2.0
, और r8-from-8.2.0
टारगेट किए गए श्रिंक नियमों का एक मान्य सेट बनाएं.
R8 में r8-from-8.0.0-upto-8.2.0
डायरेक्ट्री का इस्तेमाल, वर्शन 8.0.0 से लेकर
लेकिन इसमें वर्शन 8.2.0 शामिल नहीं है.
इस जानकारी को देखते हुए, Android Gradle प्लग इन 3.6 या उसके बाद वाला वर्शन,
मेल खाने वाली R8 डायरेक्ट्री के नियम. अगर लाइब्रेरी
नियमों को छोटा करें, तो 'Android Gradle प्लग इन', लेगसी से नियम चुनेगा
जगहें (एएआर के लिए proguard.txt
या
जेएआर के लिए META-INF/proguard/<ProGuard-rules-file>
.
लाइब्रेरी के डेवलपर, टारगेट किए गए ‘कम करने के टारगेट वाले नियम’ या लेगसी वर्शन को शामिल करने का विकल्प चुन सकते हैं अपनी लाइब्रेरी में ProGuard के नियम या अगर वे इन्हें बनाए रखना चाहते हैं, तो दोनों तरह के नियम 3.6 या दूसरे टूल से पुराने 'Android Gradle प्लग इन' के साथ काम करता है या नहीं.
अन्य कॉन्फ़िगरेशन शामिल करें
जब Android Studio का इस्तेमाल करके कोई नया प्रोजेक्ट या मॉड्यूल बनाया जाता है, तो IDE
<module-dir>/proguard-rules.pro
फ़ाइल अपलोड की जा सकती है. आपने लोगों तक पहुंचाया मुफ़्त में
में अन्य फ़ाइलों के अतिरिक्त नियम भी शामिल किए जा सकते हैं. ऐसा करने के लिए,
proguardFiles
प्रॉपर्टी की मदद से अपने मॉड्यूल की बिल्ड स्क्रिप्ट में जोड़ सकते हैं.
उदाहरण के लिए, हर बिल्ड वैरिएंट के लिए खास नियम जोड़ने के लिए,
इससे जुड़े productFlavor
ब्लॉक में, proguardFiles
की अन्य प्रॉपर्टी. कॉन्टेंट बनाने
नीचे दी गई Gradle फ़ाइल, flavor2-rules.pro
को flavor2
प्रॉडक्ट फ़्लेवर में जोड़ती है.
अब flavor2
, ProGuard के तीनों नियमों का इस्तेमाल करता है, क्योंकि release
के नियम लागू हैं
ब्लॉक भी लागू होते हैं.
इसके अलावा, आपके पास testProguardFiles
प्रॉपर्टी जोड़ने का भी विकल्प होता है, जो
ProGuard फ़ाइलों की सूची जो केवल परीक्षण APK में शामिल हैं:
Kotlin
android { ... buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), // List additional ProGuard rules for the given build type here. By default, // Android Studio creates and includes an empty rules file for you (located // at the root directory of each module). "proguard-rules.pro" ) testProguardFiles( // The proguard files listed here are included in the // test APK only. "test-proguard-rules.pro" ) } } flavorDimensions.add("version") productFlavors { create("flavor1") { ... } create("flavor2") { proguardFile("flavor2-rules.pro") } } }
ग्रूवी
android { ... buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), // List additional ProGuard rules for the given build type here. By default, // Android Studio creates and includes an empty rules file for you (located // at the root directory of each module). 'proguard-rules.pro' testProguardFiles // The proguard files listed here are included in the // test APK only. 'test-proguard-rules.pro' } } flavorDimensions "version" productFlavors { flavor1 { ... } flavor2 { proguardFile 'flavor2-rules.pro' } } }
अपने कोड को छोटा करें
minifyEnabled
को सेट करने पर, R8 के साथ कोड को छोटा करने की सुविधा डिफ़ॉल्ट रूप से चालू हो जाती है
प्रॉपर्टी को true
के लिए सेट किया गया है.
कोड का आकार कम करने की प्रोसेस, कोड को हटाने की प्रोसेस है कि R8 के हिसाब से रनटाइम के दौरान इसकी ज़रूरत नहीं होती. इस प्रोसेस से बहुत कम आपके ऐप्लिकेशन का साइज़, उदाहरण के लिए, अगर आपके ऐप्लिकेशन में कई लाइब्रेरी डिपेंडेंसी शामिल हैं, लेकिन अपनी सुविधा के एक छोटे से हिस्से का इस्तेमाल करते हैं.
आपके ऐप्लिकेशन के कोड को छोटा करने के लिए, R8 सबसे पहले आपके ऐप्लिकेशन के कॉन्फ़िगरेशन फ़ाइलों के मिले-जुले सेट पर आधारित कोड. इन एंट्री पॉइंट में वे सभी क्लास शामिल हैं जिन्हें Android प्लैटफ़ॉर्म खोलने के लिए इस्तेमाल कर सकता है आपके ऐप्लिकेशन की गतिविधियां या सेवाएं. हर एंट्री पॉइंट से शुरू करते हुए, R8 जांच करता है आपके ऐप्लिकेशन का कोड, सभी तरीकों, मेंबर वैरिएबल वगैरह का ग्राफ़ बनाने के लिए क्लास की जानकारी जिन्हें आपका ऐप्लिकेशन रनटाइम के दौरान ऐक्सेस कर सकता है. वह कोड जो इससे कनेक्ट नहीं किया गया है ऐसा माना जाता है कि ग्राफ़ ऐक्सेस नहीं किया जा सकता और उसे ऐप्लिकेशन से हटाया जा सकता है.
पहली इमेज में, रनटाइम लाइब्रेरी डिपेंडेंसी वाला ऐप्लिकेशन दिखाया गया है. जांच करते समय
ऐप्लिकेशन के कोड, R8 से तय होता है कि foo()
, faz()
, और bar()
तरीके
यहां MainActivity.class
के एंट्री पॉइंट से पहुंचा जा सकता है. हालांकि, क्लास
आपका ऐप्लिकेशन, रनटाइम के दौरान OkayApi.class
या इसके तरीके baz()
का इस्तेमाल कभी नहीं करता और
आपके ऐप्लिकेशन को छोटा करने पर, R8 उस कोड को हटा देता है.
R8, प्रोजेक्ट के -keep
नियमों के हिसाब से एंट्री पॉइंट तय करता है
R8 कॉन्फ़िगरेशन फ़ाइलें. इसका मतलब है कि नियमों को तय किए
ऐप्लिकेशन का साइज़ छोटा करते समय, R8 को नहीं खारिज करना चाहिए और R8 के हिसाब से
उन क्लास को भी शामिल किया जा सकता है जिनमें आपके ऐप्लिकेशन के एंट्री पॉइंट हों. 'Android Gradle प्लग इन'
और AAPT2, ज़्यादातर ऐप्लिकेशन के लिए ज़रूरी Keep के नियम अपने-आप जनरेट करता है
प्रोजेक्ट, जैसे कि आपके ऐप्लिकेशन की गतिविधियां, व्यू, और सेवाएं. हालांकि,
अगर आपको इस डिफ़ॉल्ट तरीके को, Keep के अन्य नियमों के साथ कस्टमाइज़ करना है, तो
अपनी पसंद के मुताबिक कोड सेव रखने का तरीका जानने के लिए, इस सेक्शन में जाएं.
अगर इसके बजाय, आपको सिर्फ़ अपने ऐप्लिकेशन के संसाधनों का साइज़ कम करना है, तो सीधे संसाधनों का साइज़ कम करने का तरीका बताने वाले सेक्शन पर जाएं.
ध्यान दें कि अगर किसी लाइब्रेरी प्रोजेक्ट को छोटा किया जाता है, तो उस लाइब्रेरी पर निर्भर ऐप्लिकेशन को इसमें छोटी लाइब्रेरी वाली क्लास शामिल हैं. आपको लाइब्रेरी रखने के नियमों में बदलाव करना पड़ सकता है, अगर लाइब्रेरी के APK में क्लास मौजूद नहीं हैं. अगर आपको डिजिटल प्लैटफ़ॉर्म का इस्तेमाल करके AAR फ़ॉर्मैट वाली लाइब्रेरी, ऐसी स्थानीय JAR फ़ाइलें जिन पर आपकी लाइब्रेरी निर्भर करती है नहीं हैं AAR फ़ाइल में छोटा किया गया.
तय करें कि किस कोड को रखना है
ज़्यादातर मामलों में, ProGuard के नियमों की डिफ़ॉल्ट फ़ाइल (proguard-android-optimize.txt
)
R8, सिर्फ़ इस्तेमाल न होने वाले कोड को हटाने के लिए काफ़ी है. हालांकि,
कुछ मामलों में, R8 के लिए सही विश्लेषण करना मुश्किल होता है. इसलिए, इसे
जिसकी ज़रूरत आपके ऐप्लिकेशन को है. इसके कुछ उदाहरण कि यह गलती से कब हट सकता है
कोड में यह शामिल है:
- जब आपका ऐप्लिकेशन, Java नेटिव इंटरफ़ेस (जेएनआई) से किसी तरीके को कॉल करता है
- जब आपका ऐप्लिकेशन रनटाइम के दौरान कोड देखता है (जैसे कि रिफ़्लेक्शन के साथ)
ऐप्लिकेशन की जांच करने से, गड़बड़ियों का पता लग जाना चाहिए. ये गड़बड़ियां, ऐप्लिकेशन को गलत तरीके से हटाए जाने की वजह से हुई हैं कोड, लेकिन यह भी देखा जा सकता है कि किस कोड को हटाए गए कोड की रिपोर्ट जनरेट करना.
गड़बड़ियां ठीक करने और R8 को कोई खास कोड रखने के लिए ज़बरदस्ती करने के लिए,
-keep
पंक्ति में रखें. उदाहरण के लिए:
-keep public class MyClass
वैकल्पिक रूप से, आप
@Keep
आपके कोड के लिए एनोटेशन
रखना चाहते हैं. किसी क्लास में @Keep
जोड़ने से, पूरी क्लास पहले जैसी ही रहती है.
इसे किसी तरीके या फ़ील्ड में जोड़ने पर, तरीका/फ़ील्ड (और उसका नाम) भी बना रहेगा
क्योंकि क्लास के नाम में कोई बदलाव नहीं हुआ है. ध्यान दें कि यह एनोटेशन सिर्फ़ तब उपलब्ध होता है, जब
यह
AndroidX एनोटेशन लाइब्रेरी
और जब आप Android के साथ पैकेज की गई ProGuard नियमों वाली फ़ाइल को शामिल करते हैं
Gradle प्लग इन, जैसा कि
छोटा करने की सुविधा चालू करें.
-keep
विकल्प का इस्तेमाल करते समय आपको कई बातों का ध्यान रखना चाहिए; इसके लिए
अपनी नियम फ़ाइल को कस्टमाइज़ करने के बारे में अधिक जानकारी के लिए,
ProGuard मैन्युअल.
कॉन्टेंट बनाने
समस्या का हल
सेक्शन में उन आम समस्याओं के बारे में बताया गया है जो आपको कोड के साथ आने पर
हटाया गया.
स्थानीय लाइब्रेरी निकालें
डिफ़ॉल्ट रूप से, आपके ऐप्लिकेशन के रिलीज़ बिल्ड में नेटिव कोड लाइब्रेरी हटा दी जाती हैं. इस स्ट्रिपिंग में सिंबल टेबल और डीबग करने की जानकारी को हटाना शामिल होता है आपके ऐप्लिकेशन में इस्तेमाल की जाने वाली किसी भी नेटिव लाइब्रेरी में शामिल हों. नेटिव कोड अलग करना लाइब्रेरी के साइज़ में काफ़ी बचत होती है; हालांकि, इसका पता लगाना नामुमकिन है कि Google Play Console पर क्रैश जानकारी मौजूद न होने की वजह से क्रैश हो जाता है (जैसे क्लास और फ़ंक्शन के नाम).
स्थानीय क्रैश सहायता
Google Play Console, नेटिव क्रैश की रिपोर्ट Android की ज़रूरी जानकारी. कुछ के साथ इन चरणों का पालन करके, अपने ऐप्लिकेशन के लिए नेटिव डीबग सिंबल फ़ाइल जनरेट और अपलोड की जा सकती है. यह फ़ाइल सिम्बॉलिकेट किए गए नेटिव क्रैश स्टैक ट्रेस को चालू करती है. इनमें क्लास और फ़ंक्शन के नाम) देखें. ये चरण, Google में इस्तेमाल किए गए Android Gradle प्लग इन के वर्शन के हिसाब से अलग-अलग हो सकते हैं आपके प्रोजेक्ट और उसके बिल्ड आउटपुट की जानकारी शामिल होती है.
'Android Gradle प्लग इन' 4.1 या इसके बाद वाले वर्शन
अगर आपके प्रोजेक्ट में Android ऐप्लिकेशन बंडल बनाया जाता है, तो
नेटिव डीबग सिंबल वाली फ़ाइल होनी चाहिए. इस फ़ाइल को रिलीज़ के बिल्ड में शामिल करने के लिए,
आपके ऐप्लिकेशन की build.gradle.kts
फ़ाइल से:
android.buildTypes.release.ndk.debugSymbolLevel = { SYMBOL_TABLE | FULL }
इनमें से डीबग सिंबल लेवल चुनें:
- Play Console में सिम्बॉलिकेट किए गए स्टैक ट्रेस में फ़ंक्शन के नाम पाने के लिए,
SYMBOL_TABLE
का इस्तेमाल करें. इस लेवल पर टूंबस्टोन इस्तेमाल किए जा सकते हैं. - Play Console में फ़ंक्शन के नाम, फ़ाइलें, और लाइन नंबर पाने के लिए
FULL
का इस्तेमाल करें सिम्बॉलिकेट्ड स्टैक ट्रेस.
अगर आपके प्रोजेक्ट में APK बनाया जाता है, तो यहां दी गई build.gradle.kts
बिल्ड सेटिंग का इस्तेमाल करें
इससे पहले, नेटिव डीबग सिंबल वाली फ़ाइल को अलग से जनरेट करें. मैन्युअल तरीके से इंस्टॉल करना
नेटिव डीबग सिंबल वाली फ़ाइल अपलोड करना
ऐप्लिकेशन खोलें. बिल्ड प्रोसेस का हिस्सा होने के तौर पर, Android Gradle
प्लगिन इस फ़ाइल को नीचे दिए गए प्रोजेक्ट की जगह पर दिखाता है:
app/build/outputs/native-debug-symbols/variant-name/native-debug-symbols.zip
'Android Gradle प्लग इन' 4.0 या इससे पहले वाले वर्शन (और अन्य बिल्ड सिस्टम)
बिल्ड प्रोसेस का हिस्सा होने के तौर पर, 'Android Gradle प्लग इन', लाइब्रेरी में मौजूद अलग-अलग तरह की लाइब्रेरी होनी चाहिए. डायरेक्ट्री का यह स्ट्रक्चर, नीचे दिए गए स्ट्रक्चर से मिलता-जुलता है:
app/build/intermediates/cmake/universal/release/obj/
├── armeabi-v7a/
│ ├── libgameengine.so
│ ├── libothercode.so
│ └── libvideocodec.so
├── arm64-v8a/
│ ├── libgameengine.so
│ ├── libothercode.so
│ └── libvideocodec.so
├── x86/
│ ├── libgameengine.so
│ ├── libothercode.so
│ └── libvideocodec.so
└── x86_64/
├── libgameengine.so
├── libothercode.so
└── libvideocodec.so
इस डायरेक्ट्री के कॉन्टेंट की ज़िप फ़ाइल बनाएं:
cd app/build/intermediates/cmake/universal/release/obj
zip -r symbols.zip .
मैन्युअल तरीके से इंस्टॉल करना
symbols.zip
फ़ाइल अपलोड करें ऐप्लिकेशन खोलें.
संसाधनों को कम करें
रिसॉर्स को छोटा करने की सुविधा, सिर्फ़ कोड को छोटा करने के साथ काम करती है. इसके बाद कोड श्रिन्कर इस्तेमाल नहीं किए गए सभी कोड हटा देता है, जबकि रिसॉर्स श्रिन्कर यह पता लगा सकता है कि ऐसे संसाधन जिन्हें ऐप्लिकेशन अब भी इस्तेमाल करता है. खास तौर पर तब ऐसा होता है, जब कोड जोड़ना होता है लाइब्रेरी, जिनमें संसाधन शामिल हैं—तो आपको इस्तेमाल न किया गया लाइब्रेरी कोड हटाना होगा, ताकि लाइब्रेरी के संसाधनों का रेफ़रंस नहीं दिया जाता. इसलिए, संसाधन इस्तेमाल करके उन्हें हटाया जा सकता है छोटा करने वाला.
रिसॉर्स का साइज़ छोटा करने की सुविधा चालू करने के लिए, shrinkResources
प्रॉपर्टी को सेट करें
true
को आपकी बिल्ड स्क्रिप्ट में (साथ में)
कोड छोटा करने के लिए minifyEnabled
). उदाहरण के लिए:
Kotlin
android { ... buildTypes { getByName("release") { isShrinkResources = true isMinifyEnabled = true proguardFiles( getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" ) } } }
ग्रूवी
android { ... buildTypes { release { shrinkResources true minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
अगर आपने इसके लिए minifyEnabled
का इस्तेमाल करके, पहले से अपना ऐप्लिकेशन नहीं बनाया है
कोड छोटा करें, फिर shrinkResources
को चालू करने से पहले आज़माएं,
क्योंकि हो सकता है कि आपको अपनी proguard-rules.pro
फ़ाइल संपादित करनी पड़े
ऐसी क्लास या मेथड को सेव रखें जिन्हें आपके इस्तेमाल से पहले डाइनैमिक तौर पर बनाया या इस्तेमाल किया जाता है
संसाधनों को हटाना शुरू करें.
किन संसाधनों को सेव रखना है, यह तय करें
अगर आपको कुछ खास संसाधनों को सेव रखना या खारिज करना है, तो एक्सएमएल बनाएं
फ़ाइल को <resources>
टैग के साथ अपलोड करें और हर फ़ाइल के बारे में बताएं
tools:keep
एट्रिब्यूट में रखने के लिए संसाधन और हर रिसॉर्स को
उसे tools:discard
एट्रिब्यूट में खारिज करें. दोनों एट्रिब्यूट
संसाधन के नामों की कॉमा-सेपरेटेड लिस्ट. तारे के निशान वाले वर्ण का इस्तेमाल
वाइल्ड कार्ड.
उदाहरण के लिए:
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://schemas.android.com/tools" tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*" tools:discard="@layout/unused2" />
इस फ़ाइल को अपने प्रोजेक्ट संसाधनों में सेव करें, उदाहरण के लिए, यहां
res/raw/my.package.keep.xml
. बिल्ड इस फ़ाइल को आपकी
है.
ध्यान दें: पक्का करें कि keep
फ़ाइल के लिए, कोई यूनीक नाम दिया गया हो. टास्क कब शुरू होगा
अलग-अलग लाइब्रेरी एक साथ जुड़ी हों, तो उनके रखने के नियमों का टकराव होगा
इससे अनजान नियमों की वजह से या बिना ज़रूरत से ज़्यादा समस्याएं पैदा होती हैं
संसाधन.
यह तय करना कि किन संसाधनों को खारिज करना है, यह अजीब लग सकता है
उन्हें मिटा दें, लेकिन बिल्ड वैरिएंट का इस्तेमाल करते समय इससे मदद मिल सकती है. इसके लिए
उदाहरण के लिए, सभी संसाधनों को सामान्य प्रोजेक्ट डायरेक्ट्री में रखा जा सकता है,
इसके बाद, हर एक के लिए एक अलग my.package.build.variant.keep.xml
फ़ाइल बनाएं
बिल्ड वैरिएंट, जब आपको पता हो कि दिए गए संसाधन का इस्तेमाल, कोड में किया गया है
(और इसलिए श्रिंकर से नहीं हटाया जाता) लेकिन आपको पता है कि यह असल में
दिए गए बिल्ड वैरिएंट के लिए इस्तेमाल किया जाता है. यह भी संभव है कि बिल्ड टूल
ने ज़रूरत के हिसाब से किसी संसाधन की गलत पहचान की है. ऐसा इसलिए, क्योंकि
कंपाइलर, रिसॉर्स आईडी को इनलाइन जोड़ता है और फिर रिसॉर्स ऐनालाइज़र शायद ऐसा न करे
इससे पता चलता है कि असल में रेफ़र किए गए संसाधन और पूर्णांक वैल्यू के बीच का क्या अंतर है
का एक ही मान हो सकता है.
सख्त पहचान फ़ाइलों की जांच करने की सुविधा चालू करें
आम तौर पर, संसाधन छोटा करने वाला टूल यह तय कर सकता है कि कोई संसाधन
का इस्तेमाल किया जाता है. हालांकि, अगर आपका कोड
Resources.getIdentifier()
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
(या अगर आपकी कोई लाइब्रेरी ऐसा करती है—तो AppCompat
लाइब्रेरी करता है), इसका मतलब है कि आपका कोड इसके आधार पर संसाधन नाम ढूंढ रहा है
डाइनैमिक रूप से जनरेट होने वाली स्ट्रिंग. जब ऐसा किया जाता है, तो रिसॉर्स श्रिन्कर काम करता है
डिफ़ॉल्ट रूप से सुरक्षा करता है और सभी संसाधनों को मिलान करने वाले नाम प्रारूप के साथ इस रूप में चिह्नित करता है
संभावित रूप से इस्तेमाल किया जा सकता है और हटाया नहीं जा सकता.
उदाहरण के लिए, नीचे दिए गए कोड में
img_
प्रीफ़िक्स को 'इस्तेमाल किया गया' के तौर पर मार्क करना है.
Kotlin
val name = String.format("img_%1d", angle + 1) val res = resources.getIdentifier(name, "drawable", packageName)
Java
String name = String.format("img_%1d", angle + 1); res = getResources().getIdentifier(name, "drawable", getPackageName());
रिसॉर्स श्रिन्कर आपके कॉलम में मौजूद सभी स्ट्रिंग कॉन्सटेंट को भी देखता है
और साथ ही कई res/raw/
संसाधन खोज रहे हैं.
इससे मिलते-जुलते फ़ॉर्मैट में यूआरएल
file:///android_res/drawable//ic_plus_anim_016.png
. अगर इसे
इस तरह की स्ट्रिंग या ऐसी स्ट्रिंग, जो यूआरएल बनाने में इस्तेमाल की जा सकती हैं
बटन नहीं हटाता.
ये सुरक्षित सिकुड़ने वाले मोड के उदाहरण हैं, जो डिफ़ॉल्ट रूप से चालू होता है.
हालांकि, आपके पास "माफ़ करने से बेहतर सुरक्षित" विकल्प को बंद करने का विकल्प होता है इस्तेमाल करते हैं, और साफ़ तौर पर बताते हैं कि
कि संसाधन छोटा करने वाला टूल सिर्फ़ उन संसाधनों का इस्तेमाल करता है जिनके बारे में पूरा पता होता है कि उनका इस्तेमाल किया जा सकता है. यहां की यात्रा पर हूं
ऐसा करने के लिए, shrinkMode
को strict
पर सेट करें.
keep.xml
फ़ाइल की जानकारी यहां दी गई है:
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://schemas.android.com/tools" tools:shrinkMode="strict" />
अगर आप सख्त श्रिंकिंग मोड चालू करते हैं और आपका कोड इसका रेफ़रंस भी देता है
डाइनैमिक रूप से जनरेट की गई स्ट्रिंग वाले संसाधन हैं, जैसा कि ऊपर दिखाया गया है, तो आपको
tools:keep
एट्रिब्यूट का इस्तेमाल करके उन संसाधनों को मैन्युअल तौर पर सेव रखें.
इस्तेमाल न किए गए वैकल्पिक संसाधनों को हटाएं
Gradle रिसॉर्स श्रिन्कर सिर्फ़ उन संसाधनों को हटाता है जिनका रेफ़रंस नहीं दिया गया है
होता है, जिसका यह अर्थ है कि यह को नहीं निकालेगा
अलग-अलग डिवाइस कॉन्फ़िगरेशन के लिए वैकल्पिक संसाधनों का इस्तेमाल करें. अगर ज़रूरी हो,
आप 'Android Gradle प्लग इन' की resConfigs
प्रॉपर्टी का इस्तेमाल करके
ऐसी अन्य संसाधन फ़ाइलें हटा दें जिनकी आपके ऐप्लिकेशन को ज़रूरत नहीं है.
उदाहरण के लिए, अगर किसी ऐसी लाइब्रेरी का इस्तेमाल किया जा रहा है जिसमें भाषा के संसाधन शामिल हैं
(जैसे कि AppCompat या Google Play Services), तो आपके ऐप्लिकेशन में सभी
उन लाइब्रेरी में मौजूद संदेशों के लिए अनुवाद की गई भाषा स्ट्रिंग चाहे
आपके ऐप्लिकेशन का उन भाषाओं में अनुवाद किया गया है या नहीं. अगर आपको
सिर्फ़ वे भाषाएं इस्तेमाल करें जिन्हें आपका ऐप्लिकेशन आधिकारिक तौर पर इस्तेमाल करता है.
resConfig
प्रॉपर्टी का इस्तेमाल करके उन भाषाओं को चुनें. इसके लिए कोई भी संसाधन
तय नहीं की गई भाषाएं हटा दी गई हैं.
नीचे दिए गए स्निपेट में बताया गया है कि कैसे अपनी भाषा के संसाधनों को सिर्फ़ अंग्रेज़ी और फ़्रेंच:
Kotlin
android { defaultConfig { ... resourceConfigurations.addAll(listOf("en", "fr")) } }
ग्रूवी
android { defaultConfig { ... resConfigs "en", "fr" } }
डिफ़ॉल्ट रूप से, 'Android ऐप्लिकेशन बंडल' फ़ॉर्मैट का इस्तेमाल करके किसी ऐप्लिकेशन को रिलीज़ करते समय ऐप्लिकेशन इंस्टॉल करते समय, उपयोगकर्ता के डिवाइस पर कॉन्फ़िगर की गई भाषाएं डाउनलोड हो जाती हैं. इसी तरह, सिर्फ़ डिवाइस की स्क्रीन की सघनता से मेल खाने वाले और नेटिव विज्ञापन डिवाइस के एबीआई से मेल खाने वाली लाइब्रेरी, डाउनलोड में शामिल होती हैं. ज़्यादा के लिए ज़्यादा जानकारी के लिए Android ऐप्लिकेशन बंडल कॉन्फ़िगरेशन.
अगस्त 2021 से पहले बनाए गए APKs के साथ रिलीज़ होने वाले लेगसी ऐप्लिकेशन के लिए, ये काम किए जा सकते हैं इसके द्वारा कस्टमाइज़ करें कि किस स्क्रीन सघनता या ABI संसाधनों को आपके APK में शामिल किया जाए कई APK बनाना हैं कि हर ऐप्लिकेशन एक अलग डिवाइस कॉन्फ़िगरेशन को टारगेट करता है.
डुप्लीकेट संसाधनों को मर्ज करना
डिफ़ॉल्ट रूप से, Gradle, एक जैसे नाम वाले संसाधनों को भी मर्ज करता है, जैसे कि
ड्रॉ करने लायक एलिमेंट जो अलग-अलग रिसॉर्स फ़ोल्डर में मौजूद हो सकते हैं. यह
व्यवहार को shrinkResources
प्रॉपर्टी से कंट्रोल नहीं किया जाता है और
को बंद नहीं किया जा सकता, क्योंकि एक से ज़्यादा
संसाधन, आपके कोड के नाम से मेल खाते हैं.
किसी संसाधन को सिर्फ़ तब मर्ज किया जाता है, जब दो या उससे ज़्यादा फ़ाइलें एक जैसी हों संसाधन का नाम, टाइप, और क्वालीफ़ायर. Gradle वह फ़ाइल चुनता है जिसे वह चुन सकता है डुप्लीकेट के बीच सर्वश्रेष्ठ विकल्प नहीं होने चाहिए (बताए गए प्राथमिकता क्रम के आधार पर साथ ही, AAPT को सिर्फ़ एक संसाधन के तौर पर, फ़ाइनल आर्टफ़ैक्ट.
Gradle, इन जगहों पर डुप्लीकेट संसाधनों की खोज करता है:
- मुख्य सोर्स सेट से जुड़े मुख्य रिसॉर्स, आम तौर पर
src/main/res/
में मौजूद है. - वैरिएंट, बिल्ड टाइप और बिल्ड फ़्लेवर से ओवरले करता है.
- लाइब्रेरी प्रोजेक्ट डिपेंडेंसी.
Gradle, डुप्लीकेट संसाधनों को नीचे दिए गए कैस्केडिंग प्राथमिकता क्रम में मर्ज करता है:
डिपेंडेंसी → मुख्य → बिल्ड फ़्लेवर → बिल्ड टाइप
उदाहरण के लिए, अगर आपके मुख्य रिसॉर्स और बिल्ड फ़्लेवर है, तो Gradle, बिल्ड फ़्लेवर में से एक को चुनता है.
अगर एक ही सोर्स सेट में एक जैसे संसाधन दिखते हैं, तो Gradle मर्ज नहीं कर सकता
साथ ही, इससे रिसॉर्स मर्ज की गड़बड़ी का पता चलता है. ऐसा तब हो सकता है, जब आप कई कीवर्ड
आपकी sourceSet
प्रॉपर्टी में सोर्स सेट
build.gradle.kts
फ़ाइल—उदाहरण के लिए, अगर दोनों src/main/res/
और src/main/res2/
में एक जैसे संसाधन हैं.
अपने कोड को अस्पष्ट बनाना
अस्पष्ट बनाने का मकसद आपके ऐप्लिकेशन के नाम छोटा करके, उनका साइज़ कम करना है आपके ऐप्लिकेशन की क्लास, तरीके, और फ़ील्ड. नीचे दिए गए R8 की मदद से अस्पष्ट बनाना:
androidx.appcompat.app.ActionBarDrawerToggle$DelegateProvider -> a.a.a.b:
androidx.appcompat.app.AlertController -> androidx.appcompat.app.AlertController:
android.content.Context mContext -> a
int mListItemLayout -> O
int mViewSpacingRight -> l
android.widget.Button mButtonNeutral -> w
int mMultiChoiceItemLayout -> M
boolean mShowTitle -> P
int mViewSpacingLeft -> j
int mButtonPanelSideLayout -> K
कोड को अस्पष्ट बनाने के बावजूद, आपके ऐप्लिकेशन से कोड नहीं हटता, लेकिन ऐप्लिकेशन के साइज़ में काफ़ी बचत होती है को DEX फ़ाइलों वाले ऐप्लिकेशन में देखा जा सकता है, जो कई क्लास, तरीकों, और फ़ील्ड को इंडेक्स करता है. हालांकि, अस्पष्ट बनाने की वजह से आपके कोड के अलग-अलग हिस्सों का नाम बदल जाता है, जैसे कि कुछ टास्क, जैसे कि स्टैक ट्रेस की जांच करने के लिए अतिरिक्त टूल की ज़रूरत होती है. अपने के बाद, स्टैकट्रेस को अस्पष्ट बनाने के बाद, अस्पष्ट स्टैक ट्रेस को डिकोड करना.
इसके अलावा, अगर आपका कोड, आपके ऐप्लिकेशन के तरीकों के लिए ऐसे नाम का इस्तेमाल करता है जिनका अनुमान लगाया जा सकता है और क्लास में बदलाव करना है. उदाहरण के लिए, आपको इन चीज़ों के बारे में बताना चाहिए हस्ताक्षर को एंट्री पॉइंट के तौर पर शामिल करता है और उनके लिए बनाए रखने के नियमों को तय करता है, जैसा कि अपनी पसंद के मुताबिक कोड सेव रखने का तरीका सेक्शन पढ़ें. जो रखते हैं नियम, R8 को न सिर्फ़ आपके ऐप्लिकेशन के फ़ाइनल DEX में उस कोड को रखने के लिए कहते हैं, बल्कि अपना मूल नाम रखते हैं.
उलझाने वाले स्टैक ट्रेस को डिकोड करना
जब R8 आपके कोड को अस्पष्ट बना देता है, तब स्टैक ट्रेस को समझना मुश्किल होता है (अगर यह संभव नहीं है) क्योंकि क्लास और मेथड के नाम बदल दिया गया है. ओरिजनल स्टैक ट्रेस पाने के लिए, आपको स्टैक ट्रेस को फिर से देखें.
कोड ऑप्टिमाइज़ेशन
आपके ऐप्लिकेशन को और ज़्यादा ऑप्टिमाइज़ करने के लिए, R8 आपके कोड को बारीकी से जांचता है इस्तेमाल न किए गए ज़्यादा कोड को हटाने या जहां संभव हो, अपने कोड को दोबारा लिखने के लिए कम शब्दों में जानकारी देते हैं. नीचे ऐसे ऑप्टिमाइज़ेशन के कुछ उदाहरण दिए गए हैं:
- अगर आपका कोड दिए गए if/else स्टेटमेंट के लिए कभी भी
else {}
की ब्रांच नहीं लेता, तो ऐसा हो सकता है कि R8,else {}
की ब्रांच का कोड हटा दे. - अगर आपका कोड, कुछ ही जगहों के लिए किसी तरीके को कॉल करता है, तो R8 वह तरीका हटा सकता है और इसे कुछ कॉल साइटों पर इनलाइन करें.
- अगर R8 को पता चलता है कि क्लास में सिर्फ़ एक यूनीक सब-क्लास है, और क्लास खुद इंस्टैंशिएट नहीं होता (उदाहरण के लिए, ऐब्स्ट्रैक्ट बेस क्लास का इस्तेमाल सिर्फ़ एक कंक्रीट लागू करने की क्लास) शामिल है, तो R8 दोनों क्लास को मिला सकता है और क्लास को ऐप्लिकेशन से हटा सकते हैं.
- ज़्यादा जानने के लिए, जेक व्हार्टन की R8 ऑप्टिमाइज़ेशन ब्लॉग पोस्ट.
R8 आपको अलग-अलग ऑप्टिमाइज़ेशन को बंद या चालू करने या
ऑप्टिमाइज़ेशन का व्यवहार. असल में, R8, ProGuard के किसी भी नियम को अनदेखा कर देता है
जैसे कि -optimizations
और
-optimizationpasses
. यह पाबंदी ज़रूरी है, क्योंकि R8 के ज़रिए
और ऑप्टिमाइज़ेशन के लिए मानक व्यवहार बनाए रखने से, Android को
Studio की टीम, आपको होने वाली हर समस्या को आसानी से हल करती है.
ध्यान दें कि ऑप्टिमाइज़ेशन की सुविधा चालू करने पर, आपके कैंपेन के स्टैक ट्रेस बदल जाएंगे का इस्तेमाल करें. उदाहरण के लिए, इनलाइन करने से स्टैक फ़्रेम हटा दिए जाएंगे. सेक्शन देखें रिट्रेसिंग का इस्तेमाल करें और मूल स्टैक ट्रेस पाने का तरीका जानें.
रनटाइम की परफ़ॉर्मेंस पर असर
अगर श्रिंक करना, अस्पष्ट बनाना, और ऑप्टिमाइज़ेशन सभी चालू हैं, तो R8 कोड की रनटाइम परफ़ॉर्मेंस (इसमें यूज़र इंटरफ़ेस (यूआई) थ्रेड पर शुरू होने वाला समय और फ़्रेम टाइम शामिल है) तक कम हो जाता है. इनमें से किसी को भी बंद करने से ऑप्टिमाइज़ेशन का सेट बहुत सीमित हो जाता है R8 इस्तेमाल.
अगर R8 चालू है, तो आपको स्टार्टअप प्रोफ़ाइल बनाना ताकि स्टार्टअप की परफ़ॉर्मेंस बेहतर हो सके.
ज़्यादा एग्रेसिव ऑप्टिमाइज़ेशन चालू करें
R8 में अतिरिक्त ऑप्टिमाइज़ेशन का एक सेट शामिल होता है (इसे "फ़ुल मोड" कहा जाता है) जो इस वजह से यह ProGuard से अलग तरह से काम करता है. ये ऑप्टिमाइज़ेशन इसके ज़रिए चालू किए गए हैं इस तारीख से डिफ़ॉल्ट Android Gradle प्लग इन का 8.0.0 वर्शन.
आप इनमें निम्नलिखित को शामिल करके ये अतिरिक्त ऑप्टिमाइज़ेशन अक्षम कर सकते हैं
आपके प्रोजेक्ट की gradle.properties
फ़ाइल:
android.enableR8.fullMode=false
अतिरिक्त ऑप्टिमाइज़ेशन की वजह से, R8 और ProGuard के काम करने का तरीका अलग होता है, रनटाइम से बचने के लिए, आपको ProGuard के कुछ और नियम जोड़ने पड़ सकते हैं ताकि ProGuard के लिए बनाए गए नियमों का इस्तेमाल किया जा रहा हो. उदाहरण के लिए, मान लें कि आपके कोड Java Reflection API के ज़रिए किसी क्लास का रेफ़रंस देता है. इस्तेमाल नहीं करने पर "फ़ुल मोड" R8 का मानना है कि आपको उस क्लास का उपयोग करें—भले ही आपका कोड वास्तव में ऐसा न करता हो—और वह क्लास और उसका स्टैटिक इनिशलाइज़र रहता है.
हालांकि, "फ़ुल मोड" का इस्तेमाल करते समय, R8 यह अनुमान नहीं लगाता. अगर R8 यह दावा करता है कि आपका कोड, रनटाइम के दौरान क्लास का इस्तेमाल कभी नहीं करता है, तो यह क्लास का इस्तेमाल करें. इसका मतलब है कि अगर आपको क्लास और उसके सभी प्लैटफ़ॉर्म का इस्तेमाल स्टैटिक शुरू करने के लिए, आपको अपनी नियम फ़ाइल में एक Keep नियम शामिल करना होगा, ताकि उसे.
अगर R8 के "फ़ुल मोड" का इस्तेमाल करते समय कोई समस्या आती है, तो R8 के बारे में अक्सर पूछे जाने वाले सवालों का पेज को भी हल किया जा सकता है. अगर समस्या हल नहीं हो पा रही है, तो कृपया गड़बड़ी की शिकायत करें.
स्टैकट्रेस को फिर से ट्रैक करना
R8 के प्रोसेस किए गए कोड को कई तरीकों से बदला जाता है. इससे स्टैक ट्रेस बनाए जा सकते हैं समझना मुश्किल है, क्योंकि स्टैक ट्रेस सोर्स कोड से पूरी तरह मेल नहीं खाते. यह डीबग करने की जानकारी देते समय, लाइन नंबर में भी नहीं रखा गया है. ऐसा इनलाइनिंग और आउटलाइनिंग जैसे ऑप्टिमाइज़ेशन की वजह से हो सकता है. कॉन्टेंट बनाने सबसे बड़ा योगदान अस्पष्ट होता है, जहां क्लास और मेथड से भी नाम बदलने के लिए किया जा सकता है.
ओरिजनल स्टैक ट्रेस को वापस पाने के लिए, R8 retrace कमांड-लाइन टूल देते हैं, जो कि कमांड-लाइन टूल पैकेज के साथ बंडल किए गए होते हैं.
अपने ऐप्लिकेशन के स्टैक ट्रेस को फिर से ट्रेस करने के लिए, आपको यह पक्का करना होगा कि
बिल्ड
नियम को आपके मॉड्यूल की proguard-rules.pro
फ़ाइल पर ले जाएंगे:
-keepattributes LineNumberTable,SourceFile
-renamesourcefileattribute SourceFile
LineNumberTable
एट्रिब्यूट, पोज़िशनल जानकारी को बनाए रखता है
का इस्तेमाल किया जाता है, जिससे उन जगहों की जानकारी को स्टैक ट्रेस में प्रिंट किया जाता है. SourceFile
एट्रिब्यूट
यह पक्का करता है कि सभी संभावित रनटाइम असल में पोज़िशनल जानकारी को प्रिंट करते हैं.
-renamesourcefileattribute
डायरेक्टिव, सोर्स फ़ाइल का नाम स्टैक में सेट करता है
बस SourceFile
के लिए ट्रेस करता है. वास्तविक मूल स्रोत फ़ाइल का नाम यह नहीं है
यह ज़रूरी है, क्योंकि मैपिंग फ़ाइल में ओरिजनल सोर्स फ़ाइल मौजूद है.
हर बार चलने पर, R8 एक mapping.txt
फ़ाइल बनाता है. इससे
में वह जानकारी शामिल है जो स्टैक ट्रेस को मूल रूप से मैप करने के लिए ज़रूरी है
स्टैक ट्रेस. Android Studio, फ़ाइल को
<module-name>/build/outputs/mapping/<build-type>/
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
डायरेक्ट्री.
Google Play पर ऐप्लिकेशन को पब्लिश करते समय, mapping.txt
फ़ाइल अपलोड की जा सकती है
हर वर्शन के लिए सही है. 'Android ऐप्लिकेशन बंडल' का इस्तेमाल करके पब्लिश करते समय यह
फ़ाइल, ऐप्लिकेशन बंडल के कॉन्टेंट के हिस्से के तौर पर अपने-आप शामिल हो जाती है. फिर Google
Play, उपयोगकर्ताओं की बताई गई समस्याओं के ज़रिए मिले स्टैक ट्रेस को फिर से ट्रेस करेगा, ताकि आपको
Play Console पर जाकर उनकी समीक्षा की जा सकती है. ज़्यादा जानकारी के लिए, सहायता केंद्र पर जाएं
लेख में,
क्रैश स्टैक ट्रेस को डिकोड करना.
R8 से जुड़ी समस्या हल करना
इस सेक्शन में, चालू करते समय आने वाली समस्याओं को हल करने के तरीकों के बारे में बताया गया है छोटा करने, अस्पष्ट बनाने, और ऑप्टिमाइज़ेशन शामिल करने के लिए भी किया जा सकता है. अगर आपको कोई हल नहीं मिलता है, तो अपनी समस्या के बारे में नीचे बताया है, तो इसे भी पढ़ें R8 के बारे में अक्सर पूछे जाने वाले सवालों का पेज और ProGuard की समस्या हल करने के लिए गाइड.
हटाए गए (या रखे गए) कोड की रिपोर्ट जनरेट करना
R8 से जुड़ी कुछ समस्याओं को हल करने के लिए,
उन सभी कोड को हटा सकता है जिन्हें R8 ने आपके ऐप्लिकेशन से हटा दिया है. हर उस मॉड्यूल के लिए जिसके लिए आपको चाहिए
इस रिपोर्ट को जनरेट करने के लिए, अपने कस्टम में -printusage <output-dir>/usage.txt
जोड़ें
नियम फ़ाइल में दी गई है. जब ऐप्लिकेशन को R8 चालू किया जाता है और ऐप्लिकेशन बनाया जाता है, तो R8
आपके बताए गए पाथ और फ़ाइल नाम से रिपोर्ट करें. हटाए गए कोड के बारे में जानकारी
से मिलता-जुलता दिखता है:
androidx.drawerlayout.R$attr
androidx.vectordrawable.R
androidx.appcompat.app.AppCompatDelegateImpl
public void setSupportActionBar(androidx.appcompat.widget.Toolbar)
public boolean hasWindowFeature(int)
public void setHandleNativeActionModesEnabled(boolean)
android.view.ViewGroup getSubDecor()
public void setLocalNightMode(int)
final androidx.appcompat.app.AppCompatDelegateImpl$AutoNightModeManager getAutoNightModeManager()
public final androidx.appcompat.app.ActionBarDrawerToggle$Delegate getDrawerToggleDelegate()
private static final boolean DEBUG
private static final java.lang.String KEY_LOCAL_NIGHT_MODE
static final java.lang.String EXCEPTION_HANDLER_MESSAGE_SUFFIX
...
अगर इसके बजाय, आपको उन एंट्री पॉइंट की रिपोर्ट देखनी है जिन्हें R8 ने तय किया है
अपने प्रोजेक्ट के Keep नियम , -printseeds <output-dir>/seeds.txt
को अपने
कस्टम नियमों वाली फ़ाइल का इस्तेमाल किया जा सकता है. ऐप्लिकेशन बनाने के बाद, R8 को चालू करने पर, R8 से आउटपुट
आपके बताए गए पाथ और फ़ाइल नाम वाली रिपोर्ट. रखी गई एंट्री की रिपोर्ट
पॉइंट इनके जैसे दिखते हैं:
com.example.myapplication.MainActivity
androidx.appcompat.R$layout: int abc_action_menu_item_layout
androidx.appcompat.R$attr: int activityChooserViewStyle
androidx.appcompat.R$styleable: int MenuItem_android_id
androidx.appcompat.R$styleable: int[] CoordinatorLayout_Layout
androidx.lifecycle.FullLifecycleObserverAdapter
...
संसाधन छोटा करने की समस्या हल करना
संसाधनों को छोटा करने पर, बिल्ड विंडो का सारांश दिखाया जाता है ऐप्लिकेशन से हटा दिए जाते हैं. (आपको पहले टॉगल व्यू पर क्लिक करना होगा पर क्लिक करें.) उदाहरण के लिए:
:android:shrinkDebugResources
Removed unused resources: Resource data reduced from 2570KB to 1711KB: Removed 33%
:android:validateDebugSigning
Gradle, resources.txt
नाम की डाइग्नोस्टिक्स फ़ाइल भी बनाता है
<module-name>/build/outputs/mapping/release/
(पहले जैसा
फ़ोल्डर को ProGuard की आउटपुट फ़ाइलों के रूप में). इस फ़ाइल में यह जानकारी शामिल है
दूसरे संसाधनों का रेफ़रंस है. साथ ही, यह भी बताया गया है कि किन संसाधनों का इस्तेमाल किया जा रहा है या
हटाया गया.
उदाहरण के लिए, यह जानने के लिए कि @drawable/ic_plus_anim_016
क्यों है
अब भी अपने ऐप्लिकेशन में, resources.txt
फ़ाइल खोलें और उसे खोजें
फ़ाइल नाम. आपको ऐसा लग सकता है कि यह किसी अन्य संसाधन से लिया गया है, जैसे
अनुसरण करता है:
16:25:48.005 [QUIET] [system.out] @drawable/add_schedule_fab_icon_anim : reachable=true
16:25:48.009 [QUIET] [system.out] @drawable/ic_plus_anim_016
अब आपको यह जानना होगा कि @drawable/add_schedule_fab_icon_anim
क्यों
पहुंच योग्य नहीं है—और यदि आप ऊपर की ओर खोजें तो पाएंगे कि वह संसाधन
के नीचे "मुख्य रूप से ऐक्सेस किए जा सकने वाले संसाधन मौजूद हैं:". इसका मतलब है कि कोड रेफ़रंस उपलब्ध है
add_schedule_fab_icon_anim
तक (यानी, इसका R.ड्रॉबल आईडी था
जो रीचेबल कोड में मिलता है).
अगर सख्त जांच का इस्तेमाल नहीं किया जा रहा है, तो रिसॉर्स आईडी को 'ऐक्सेस किया जा सकता है' के तौर पर मार्क किया जा सकता है अगर स्ट्रिंग कॉन्सटेंट ऐसे हैं जो दिखते हैं, तो उन्हें बनाने के लिए इस्तेमाल किया जा सकता है गतिशील रूप से लोड होने वाले संसाधनों के लिए संसाधन नाम. इस स्थिति में, अगर आपको तो आपको संसाधन के नाम के बिल्ड आउटपुट में इस तरह का मैसेज दिख सकता है:
10:32:50.590 [QUIET] [system.out] Marking drawable:ic_plus_anim_016:2130837506
used because it format-string matches string pool constant ic_plus_anim_%1$d.
अगर आपको इनमें से कोई स्ट्रिंग दिखती है और आपको यकीन है कि स्ट्रिंग
इसका इस्तेमाल, दिए गए संसाधन को डाइनैमिक तरीके से लोड करने के लिए किया जाता है, तो
बिल्ड सिस्टम को इसे हटाने के लिए जानकारी देने के लिए tools:discard
एट्रिब्यूट,
जैसा कि किसी संसाधन को अपने हिसाब से मैनेज करने का तरीका जानने के लिए, इस सेक्शन में बताया गया है.