ProGuard और R8 Android एप्लिकेशन के लिए ऑबफ़स्केशन, मिनिफिकेशन और ऑप्टिमाइज़ेशन उपकरण हैं। ProGuard, जो 2002 में बनाया गया था, लंबे समय तक Java कोड सुरक्षा के लिए डी-फैक्टो मानक था। R8 इसका उत्तराधिकारी है, जिसे Google ने विकसित किया और AGP 3.4 से Android Gradle Plugin में बनाया गया। दोनों उपकरण APK आकार कम करते हैं, मृत कोड हटाते हैं और रिवर्स इंजीनियरिंग को जटिल बनाते हैं। Android Developers के अनुसार, R8 तुलनीय ऑबफ़स्केशन गुणवत्ता के साथ ProGuard की तुलना में 2–3 गुना तेज़ी से बिल्ड करता है।
मुख्य बातें
ProGuard Java बाइटकोड के ऑबफ़स्केशन, मिनिफिकेशन, ऑप्टिमाइज़ेशन और प्रीवेरिफिकेशन के लिए एक ओपन-सोर्स टूल (Apache 2.0) है। इसे Eric Lafarge ने 2002 में SourceForge प्रोजेक्ट के भाग के रूप में विकसित किया था। ProGuard संकलित Java क्लासेस (.class) या JAR आर्काइव को इनपुट के रूप में लेता है और उसी प्रारूप की प्रोसेस्ड क्लासेस तैयार करता है, लेकिन छोटे आकार और पुनर्नामित तत्वों के साथ।
लंबे समय तक, ProGuard Android एप्लिकेशन को रिवर्स इंजीनियरिंग से बचाने का एकमात्र मानक था। Google ने आधिकारिक तौर पर Android SDK में इसके उपयोग की सिफारिश की और SDK टूल्स के अंदर proguard-android-optimize.txt फ़ाइल में डिफ़ॉल्ट कॉन्फ़िगरेशन प्रदान किया। ProGuard एक अलग उपकरण के रूप में काम करता था, जो Java कोड के बाइटकोड में संकलन के बाद और DEX में पैकेजिंग से पहले चलाया जाता था।
ProGuard चार अनुक्रमिक चरणों से बना है: shrink (अप्रयुक्त क्लासेस को हटाना), optimize (बाइटकोड ऑप्टिमाइज़ेशन — इनलाइनिंग, मृत कोड हटाना), obfuscate (क्लासेस, मेथड्स और फ़ील्ड्स को छोटे नामों में बदलना), preverify (JVM संगतता जाँच)। प्रत्येक चरण कॉन्फ़िगरेशन फ़ाइलों से अलग-अलग नियमों द्वारा नियंत्रित होता है।
ऑबफ़स्केशन चरण के दौरान, ProGuard एक मैपिंग फ़ाइल (mapping.txt) उत्पन्न करता है जो मूल नामों को ऑबफ़स्केट नामों से मैप करती है। यह फ़ाइल retrace उपयोगिता के माध्यम से रिलीज़ बिल्ड से क्रैश लॉग को डीकोड करने के लिए महत्वपूर्ण है। मैपिंग फ़ाइल के बिना, स्टैक ट्रेस अक्षरों a(), b(), c() का एक सेट बन जाता है जिसमें मूल संदर्भ को पुनर्स्थापित करने का कोई तरीका नहीं होता।
| ProGuard चरण | उद्देश्य | परिणाम |
|---|---|---|
| Shrink | कॉल ग्राफ़ विश्लेषण और मृत कोड हटाना | APK में कम क्लासेस |
| Optimize | मेथड इनलाइनिंग, अप्रयुक्त पैरामीटर हटाना | तेज़ कोड निष्पादन |
| Obfuscate | क्लासेस, फ़ील्ड्स और मेथड्स का पुनर्नामकरण | रिवर्स इंजीनियरिंग सुरक्षा |
| Preverify | JVM के लिए StackMap विशेषताएँ जोड़ना | Java 6+ संगतता |
R8 Google का अगली पीढ़ी का ऑबफ़स्केशन और मिनिफिकेशन उपकरण है, जिसे पहली बार Android Studio 3.3 (नवंबर 2018) में पेश किया गया और AGP 3.4 (अगस्त 2019) में मानक बन गया। ProGuard के विपरीत, R8 D8/R8 कंपाइलर का हिस्सा है जो Java बाइटकोड को DEX प्रारूप में बदलता है। R8 सभी चरणों — ऑबफ़स्केशन, मिनिफिकेशन और ऑप्टिमाइज़ेशन — को एक ही पास में करता है, बिना उपकरणों के बीच मध्यवर्ती फ़ाइलें पास किए।
Google ने R8 को दो उद्देश्यों के साथ विकसित किया: बिल्ड को गति देना (ProGuard एक बाहरी उपकरण के रूप में काम करता था) और आधुनिक Android स्टैक (Desugar, Core Library Desugaring, D8) के साथ निर्बाध एकीकरण प्रदान करना। R8 Kotlin और Java में लिखा गया है और AOSP (Android Open Source Project) पर R8/Desugar रिपॉजिटरी का हिस्सा है।
R8 का एक महत्वपूर्ण लाभ ProGuard नियमों के साथ पूर्ण बैकवर्ड संगतता है। मौजूदा .pro फ़ाइलें बिना किसी बदलाव के काम करती हैं। R8 विशिष्ट ProGuard निर्देशों का भी समर्थन करता है, जिनमें -whyareyoukeeping, -printconfiguration और -printmapping शामिल हैं। इसका मतलब है कि ProGuard से R8 में संक्रमण पारदर्शी है: बस AGP अपडेट करें।
// build.gradle.kts — minifyEnabled के माध्यम से R8 सक्षम करना
android {
buildTypes {
getByName("release") {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
// Android SDK से मूल कॉन्फ़िगरेशन
getDefaultProguardFile("proguard-android-optimize.txt"),
// कस्टम प्रोजेक्ट नियम
"proguard-rules.pro"
)
}
}
}कोड एक मानक रिलीज़ बिल्ड कॉन्फ़िगरेशन दिखाता है। फ़्लैग isMinifyEnabled = true ऑबफ़स्केशन और ऑप्टिमाइज़ेशन के लिए R8 को सक्रिय करता है। isShrinkResources = true अतिरिक्त रूप से अप्रयुक्त संसाधनों को हटाता है। getDefaultProguardFile SDK से डिफ़ॉल्ट नियम लोड करता है, जबकि proguard-rules.pro में प्रोजेक्ट-विशिष्ट सेटिंग्स होती हैं।
ऑबफ़स्केशन स्रोत कोड को ऐसे रूप में बदलने की प्रक्रिया है जिसका विश्लेषण करना मनुष्यों के लिए कठिन हो लेकिन जो पूर्ण कार्यक्षमता बनाए रखता है। Android संदर्भ में, ऑबफ़स्केशन का अर्थ है क्लासेस, मेथड्स और फ़ील्ड्स को छोटे, अर्थहीन नामों में बदलना: com.example.app.auth.LoginManager बन जाता है a.a.a, मेथड authenticateUser बन जाता है a, फ़ील्ड userToken बन जाता है b।
Android APK फ़ाइलें आर्काइव हैं जिन्हें किसी भी आर्काइवर (ZIP, 7z, WinRAR) से खोला जा सकता है। ऑबफ़स्केशन के बिना, एक हमलावर को एप्लिकेशन का पूरा नक्शा मिल जाता है: पैकेज नाम, क्लासेस, मेथड्स और फ़ील्ड्स। jadx या Bytecode Viewer जैसे उपकरण सेकंडों में DEX फ़ाइलों से लगभग मूल Java कोड पुनर्स्थापित कर सकते हैं। ऑबफ़स्केशन कोड को अभेद्य नहीं बनाता, लेकिन प्रवेश बाधा को काफी बढ़ा देता है: सार्थक नामों के बजाय, पाठक a(), b(), c() देखता है।
विशिष्ट ऑबफ़स्केशन लक्ष्य: व्यावसायिक तर्क की सुरक्षा (एल्गोरिदम, गणना सूत्र), API कुंजियों और टोकन की चोरी को रोकना, reflection के माध्यम से क्लास प्रतिस्थापन को रोकना, और APK पैचिंग और संशोधन (रीपैकेज अटैक) को रोकना। व्यवहार में, 70% कार्य केवल पुनर्नामकरण द्वारा हल हो जाते हैं — यही कारण है कि ProGuard/R8 का उपयोग किया जाता है।
नीचे Retrofit, Gson और Parcelable के साथ एक Android प्रोजेक्ट के लिए एक विशिष्ट proguard-rules.pro फ़ाइल है। -keep नियम reflection के माध्यम से लाइब्रेरी संचालन के लिए आवश्यक क्लासेस और मेथड्स को संरक्षित करते हैं। इन नियमों के बिना, R8 उन क्लासेस को हटा या पुनर्नामित कर देगा जिन तक लाइब्रेरी स्ट्रिंग नाम से पहुँचती है।
# =====================
# Retrofit — इंटरफ़ेस संरक्षित करना
# =====================
-keep,allowobfuscation,allowshrinking interface retrofit2.** { *; }
-keepattributes Signature, Exceptions
# =====================
# Gson — JSON सीरियलाइज़ेशन
# =====================
-keepclassmembers class * {
@com.google.gson.annotations.SerializedName <fields>;
}
-keep class *.serialization.** {
<fields>;
}
# =====================
# Parcelable — Creator
# =====================
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator CREATOR;
}
# =====================
# Logging — रिलीज़ से लॉग हटाना
# =====================
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(String, int);
public static int v(...);
public static int d(...);
public static int i(...);
public static int w(...);
public static int e(...);
}
# =====================
# Kotlin डेटा क्लासेस — कंस्ट्रक्टर संरक्षित करना
# =====================
-keepclassmembers class * {
@kotlin.Metadata <fields>;
}
# =====================
# Activity — प्रवेश बिंदु
# =====================
-keep class * extends android.app.Activity {
@android.annotation.SuppressLint <methods>;
}.pro फ़ाइल में प्रत्येक निर्देश एक विशिष्ट कार्य को हल करता है। -keep पूरी क्लास को हटाए या पुनर्नामित किए जाने से रोकता है। -keepclassmembers केवल क्लास सदस्यों (फ़ील्ड्स और मेथड्स) की रक्षा करता है लेकिन क्लास को स्वयं हटाने की अनुमति देता है यदि अप्रयुक्त हो। -assumenosideeffects R8 को बताता है कि मेथड कॉल का कोई साइड इफ़ेक्ट नहीं है और इसे सुरक्षित रूप से हटाया जा सकता है। निर्देश -keepattributes बाइटकोड में मेटाडेटा — एनोटेशन, सिग्नेचर, अपवाद — संरक्षित करता है।
Retrofit के लिए नियम -keep,allowobfuscation,allowshrinking R8 को इंटरफ़ेस को पुनर्नामित करने की अनुमति देता है लेकिन उन्हें हटाने की नहीं। यह आवश्यक है क्योंकि Retrofit डायनामिक प्रॉक्सी (java.lang.reflect.Proxy) के माध्यम से इंटरफ़ेस तक पहुँचता है, और हटाने से रनटाइम पर ClassNotFoundException होगा। इसी तरह, Gson @SerializedName से एनोटेटेड फ़ील्ड्स तक पहुँचने के लिए reflection का उपयोग करता है — -keepclassmembers के बिना फ़ील्ड्स को अप्रयुक्त मानकर हटा दिया जाएगा।
मिनिफिकेशन (shrinking) अंतिम बिल्ड से अप्रयुक्त कोड और संसाधनों को हटाने की प्रक्रिया है। ProGuard और R8 एंट्री पॉइंट (Activity, Service, BroadcastReceiver) से शुरू होकर कॉल ग्राफ़ का विश्लेषण करते हैं और उन क्लासेस और मेथड्स को हटाते हैं जिन तक कॉल श्रृंखला के माध्यम से नहीं पहुँचा जा सकता। ShrinkResources एक अतिरिक्त चरण है जो res/ (layout, drawable, string, color) से अप्रयुक्त संसाधनों को हटाता है।
मिनिफिकेशन लाइब्रेरी वाले बड़े प्रोजेक्ट्स में सबसे अधिक लाभ प्रदान करता है। एक विशिष्ट परिदृश्य: एक प्रोजेक्ट कनेक्टेड लाइब्रेरी (जैसे Google Play Services) से 10% कोड का उपयोग करता है। मिनिफिकेशन के बिना, सारा लाइब्रेरी कोड APK में चला जाता है। मिनिफिकेशन के साथ, R8 70–90% लाइब्रेरी कोड हटा देता है, केवल वास्तव में उपयोग की जाने वाली क्लासेस और मेथड्स को छोड़कर। यह सीधे APK आकार, लोडिंग समय और मेमोरी खपत को प्रभावित करता है।
ShrinkResources तंत्र कोड मिनिफिकेशन के साथ मिलकर काम करता है। R8 द्वारा यह निर्धारित करने के बाद कि कौन सी क्लासेस उपयोग में हैं, संसाधन संकोचन कोड से संसाधन संदर्भों का विश्लेषण करता है: R.layout.main, R.drawable.icon, getString(R.string.title)। सभी संसाधन जिनका प्रत्यक्ष या अप्रत्यक्ष संदर्भ नहीं है, अंतिम APK या AAB से हटा दिए जाते हैं। यह संसाधन फ़ाइल resources.arsc और res/ फ़ोल्डर्स का उपयोग करके किया जाता है।
एक महत्वपूर्ण बारीकियाँ: संसाधनों को getIdentifier() या Resources.getResourceName() के माध्यम से स्ट्रिंग नाम से एक्सेस किया जा सकता है, R क्लास को दरकिनार करते हुए। ऐसे मामलों में, R8 को सीधा लिंक नहीं दिखता और वह उस संसाधन को हटा सकता है जो वास्तव में उपयोग में है। ऐसे संसाधनों की सुरक्षा के लिए, निर्देश -keep class **.R$* { *; } है — यह R क्लास के सभी पहचानकर्ताओं को संरक्षित करता है।
<!-- उदाहरण: एक संसाधन जो केवल getIdentifier() के माध्यम से उपयोग किया जाता है -->
<string name="dynamic_title_welcome">स्वागत है</string>
<string name="dynamic_title_share">साझा करें</string>
<!-- Kotlin कोड जो स्ट्रिंग द्वारा एक्सेस करता है -->
<!-- val title = getString(resources.getIdentifier( -->
<!-- \"dynamic_title_${type}\", \"string\", packageName)) -->इस मामले में, R8 को R क्लास में dynamic_title_welcome का स्थिर संदर्भ नहीं दिखता क्योंकि एक्सेस डायनामिक नाम के साथ getIdentifier के माध्यम से है। ऐसे संसाधनों को संरक्षित करने के लिए, proguard-rules.pro में निर्देश -keepclassmembers class **.R$string { *; } जोड़ें — यह सभी R$string क्लासेस से किसी भी फ़ील्ड को हटाने से रोकता है।
| निर्देश | उद्देश्य | उदाहरण |
|---|---|---|
| -keep | क्लास और उसके सभी सदस्यों को संरक्षित करता है | -keep class com.example.api.** { *; } |
| -keepclassmembers | केवल क्लास सदस्यों को संरक्षित करता है | -keepclassmembers class * { @SerializedName <fields>; } |
| -keepattributes | बाइटकोड मेटाडेटा संरक्षित करता है | -keepattributes *Annotation*, Signature |
| -assumenosideeffects | बिना साइड इफ़ेक्ट वाले कॉल हटाता है | -assumenosideeffects class Log { d(...); } |
| -dontwarn | चेतावनियों को दबाता है | -dontwarn com.example.legacy.** |
इस तथ्य के बावजूद कि R8 ProGuard का उत्तराधिकारी है, उपकरणों के बीच आर्किटेक्चर, प्रदर्शन और व्यवहार में मूलभूत अंतर हैं। Google ने AGP 7.0 से Android Gradle Plugin में ProGuard समर्थन को आधिकारिक रूप से बंद कर दिया, लेकिन ProGuard का उपयोग उन प्रोजेक्ट्स में जारी है जिन्हें R8 में उपलब्ध न होने वाले विशिष्ट ऑप्टिमाइज़ेशन व्यवहार की आवश्यकता होती है।
| विशेषता | ProGuard | R8 |
|---|---|---|
| डेवलपर | GuardSquare (Eric Lafarge) | |
| रिलीज़ वर्ष | 2002 | 2018 (2019 में स्थिर) |
| आर्किटेक्चर | 4 अलग-अलग चरण (shrink → optimize → obfuscate → preverify) | एक पास: shrink + optimize + obfuscate एक साथ |
| AGP एकीकरण | बाहरी उपकरण, javac के बाद चलाया जाता है | D8 DEX कंपाइलर में निर्मित |
| बिल्ड गति | 2–3 गुना धीमा | एक पास और मूल एकीकरण के कारण तेज़ |
| Kotlin समर्थन | सीमित (inline, lambdas, coroutines में समस्याएँ) | पूर्ण: coroutines, inline फ़ंक्शन, data class |
| मैपिंग फ़ाइल | mapping.txt (retrace के साथ संगत) | mapping.txt (समान प्रारूप) |
| ऑप्टिमाइज़ेशन अनुकूलन | 60+ विकल्प -optimizationpasses, -optimizations | सीमित: अधिकांश ऑप्टिमाइज़ेशन डिफ़ॉल्ट रूप से सक्षम |
| समर्थन स्थिति | R8 द्वारा प्रतिस्थापित (AGP 7.0+ उपयोग नहीं करता) | सक्रिय विकास, AOSP का हिस्सा |
R8 ProGuard की तुलना में कोड हटाने में अधिक आक्रामक है जिसे वह मृत मानता है। इससे ऐसी स्थितियाँ उत्पन्न होती हैं जहाँ डीबग बिल्ड काम करता है लेकिन रिलीज़ बिल्ड ClassNotFoundException या NoSuchMethodException के साथ क्रैश होता है। विशिष्ट मामले: क्लास नाम (Gson, Moshi, Retrofit, Room, Dagger) द्वारा reflection का उपयोग करने वाली लाइब्रेरी; ServiceLoader या java.util.ServiceLoader कॉल; डायनामिक प्रॉक्सी (java.lang.reflect.Proxy); नेटिव मेथड्स (JNI)। समाधान सभी क्लासेस के लिए -keep जोड़ना है जो reflection के माध्यम से बुलाई जाती हैं।
# विशिष्ट reflection समस्याएँ — R8 स्थैतिक लिंकेज नहीं देखता
# Room — DAO और माइग्रेशन संरक्षित करना
-keep class * extends androidx.room.RoomDatabase { *; }
-keep class *.DatabaseMigrations { *; }
# Dagger / Hilt — घटकों को संरक्षित करना
-keep class * extends dagger.hilt.android.components.** { *; }
# JNI — नेटिव मेथड्स का पुनर्नामकरण न करना
-keepclasseswithmembernames class * {
native <methods>;
}
# Data Binding — Binding क्लासेस संरक्षित करना
-keep class *.databinding.** { *; }यदि नियम जोड़ने के बाद भी बिल्ड क्रैश होता है, तो proguard-rules.pro में फ़्लैग -printconfiguration full-config.txt का उपयोग करें। R8 एक पूर्ण कॉन्फ़िगरेशन फ़ाइल उत्पन्न करेगा जो दिखाती है कि कौन से नियम लागू हैं और कौन सी क्लासेस संरक्षित हैं। निर्देश -whyareyoukeeping class com.example.MyClass भी उपयोगी है — यह वह कारण बताता है जिसके लिए R8 ने दी गई क्लास को संरक्षित करने का निर्णय लिया।
ProGuard rules का उचित कॉन्फ़िगरेशन रनटाइम बग के बिना स्थिर ऑबफ़स्केशन की कुंजी है। नीचे एक नए प्रोजेक्ट या ऐसे प्रोजेक्ट के लिए चरण-दर-चरण सेटअप प्रक्रिया दी गई है जहाँ ऑबफ़स्केशन त्रुटियाँ पैदा करता है।
मानक Android SDK फ़ाइल — proguard-android-optimize.txt को शामिल करके शुरू करें। इसमें मूल Android घटकों के लिए नियम हैं: Activity, Service, BroadcastReceiver, ContentProvider, View, Fragment। यह फ़ाइल SDK फ़ोल्डर में स्थित है: $ANDROID_HOME/tools/proguard/proguard-android-optimize.txt। यदि आप AGP का उपयोग करते हैं, तो getDefaultProguardFile इसे स्वचालित रूप से लोड करेगा।
प्रत्येक लोकप्रिय लाइब्रेरी के पास अनुशंसित ProGuard नियम हैं। Retrofit, OkHttp, Glide, Fresco, Coil, Room, Dagger/Hilt, Kotlin Coroutines — सभी को विशिष्ट -keep नियमों की आवश्यकता होती है। आमतौर पर नियम AAR लाइब्रेरी में शामिल होते हैं और उपभोक्ता गार्ड नियमों के माध्यम से स्वचालित रूप से लिंक हो जाते हैं। जाँचें कि लाइब्रेरी AAR के अंदर proguard.txt फ़ाइल प्रदान करती है — यह इंगित करता है कि नियम पहले से शामिल हैं।
प्रकाशन से पहले, वास्तविक डिवाइस या एम्युलेटर पर रिलीज़ बिल्ड का परीक्षण करना सुनिश्चित करें। ऑबफ़स्केशन समस्याएँ केवल रनटाइम पर प्रकट होती हैं। जाँचें: प्रमाणीकरण (लॉगिन/रजिस्ट्रेशन), नेटवर्क से डेटा लोड करना, स्क्रीन के बीच नेविगेशन, कैमरा और गैलरी, पुश नोटिफिकेशन, Deeplinks, WebView। रिलीज़ बिल्ड में प्रत्येक क्रैश को मैपिंग फ़ाइल के साथ retrace का उपयोग करके डीकोड करने और लापता -keep नियम जोड़ने की आवश्यकता होती है।
मैपिंग फ़ाइल build/outputs/mapping/release/mapping.txt पर उत्पन्न होती है। इस फ़ाइल को संरक्षित किया जाना चाहिए: इसके बिना Google Play Console से क्रैश लॉग को डीकोड करना असंभव है। mapping.txt को अपने वर्शन कंट्रोल सिस्टम में शामिल करें या इसे CI आर्टिफ़ैक्ट में अपलोड करें। Google Play Console uploading mapping.txt सक्षम के साथ AAB अपलोड करने पर स्वचालित रूप से मैपिंग फ़ाइल स्वीकार करता है।
नीचे proguard-rules.pro फ़ाइल में नियमों के प्रत्येक समूह के लिए टिप्पणियों के साथ एक पूर्ण ऑबफ़स्केशन सेटअप वर्कफ़्लो है।
# ===========================================
# proguard-rules.pro — पूर्ण उदाहरण
# ===========================================
# --- सामान्य सेटिंग्स ---
-keepattributes *Annotation*, Signature, Exceptions, InnerClasses, EnclosingMethod
-dontpreverify
# --- Android घटक ---
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.Fragment
-keep public class * extends androidx.fragment.app.Fragment
-keep public class * extends android.view.View
# --- OkHttp / Retrofit ---
-dontwarn okhttp3.**
-dontwarn okio.**
-keep class retrofit2.** { *; }
-keepattributes Exceptions
# --- Gson / Moshi ---
-keepclassmembers class * {
@com.google.gson.annotations.SerializedName <fields>;
}
-keep class com.google.gson.** { *; }
# --- Firebase ---
-keep class com.google.firebase.** { *; }
-keep class com.google.android.gms.** { *; }
# --- Kotlin Coroutines ---
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
# --- सीरियलाइज़ेशन ---
-keepclassmembers class * implements java.io.Serializable {
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
# --- केवल R8: बलपूर्वक संरक्षण ---
# (ProGuard इस निर्देश को अनदेखा करता है)
-keep,allowobfuscation class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator CREATOR;
}कॉन्फ़िगरेशन के बाद, बिल्ड चलाएँ: ./gradlew assembleRelease। सत्यापित करें कि build/outputs/mapping/release/ में फ़ाइलें दिखाई दीं: mapping.txt (मूल से ऑबफ़स्केट नामों का मैपिंग), seeds.txt (-keep नियमों द्वारा संरक्षित क्लासेस), usage.txt (मिनिफिकेशन के दौरान हटाई गई क्लासेस)। ऑबफ़स्केशन के बाद APK आकार कनेक्टेड लाइब्रेरी की संख्या के आधार पर 20–50% तक कम होना चाहिए।
अक्सर पूछे जाने वाले प्रश्न
R8 ProGuard का उत्तराधिकारी है, जिसे Google ने विकसित किया है। R8 एक ही पास में ऑबफ़स्केशन, मिनिफिकेशन और ऑप्टिमाइज़ेशन करता है, ProGuard की तुलना में 2–3 गुना तेज़ काम करता है और सीधे Android Gradle Plugin में एकीकृत है। ProGuard चार अलग-अलग चरणों का उपयोग करता है और बाहरी निष्पादन की आवश्यकता होती है। AGP 7.0 से, ProGuard का उपयोग नहीं किया जाता — डिफ़ॉल्ट रूप से R8 काम करता है।
हाँ, R8 उसी ProGuard rules (.pro फ़ाइलें) का उपयोग करता है। निर्देश -keep, -keepclassmembers, -keepattributes, -assumenosideeffects समान रूप से काम करते हैं। मूल नियम Android SDK से proguard-android-optimize.txt में आते हैं, जबकि लाइब्रेरी-विशिष्ट नियम (Retrofit, Room, Gson) प्रोजेक्ट के proguard-rules.pro में जोड़े जाते हैं। इन नियमों के बिना, R8 उन क्लासेस को हटा सकता है जो reflection के माध्यम से काम करने वाली लाइब्रेरी के लिए आवश्यक हैं।
R8 AGP 3.4 से Android Gradle Plugin में डिफ़ॉल्ट रूप से सक्षम है। मिनिफिकेशन सक्रिय करने के लिए, build.gradle.kts फ़ाइल के release buildType ब्लॉक में isMinifyEnabled = true सेट करें। अतिरिक्त फ़्लैग isShrinkResources = true अप्रयुक्त संसाधनों को हटाने में सक्षम करता है। gradle.properties में, आप android.enableR8=false के माध्यम से R8 को बलपूर्वक अक्षम कर सकते हैं, लेकिन यह अनुशंसित नहीं है — R8 तेज़ और अधिक स्थिर है।
ऑबफ़स्केशन — क्लासेस, मेथड्स और फ़ील्ड्स को छोटे अर्थहीन नामों (a, b, c) में बदलना। क्लास com.example.app.auth.LoginManager a.a.a बन जाती है, मेथड authenticateUser a बन जाता है। यह एप्लिकेशन के रिवर्स इंजीनियरिंग को जटिल बनाता है लेकिन निष्पादन तर्क को प्रभावित नहीं करता। ProGuard और R8 केवल उन तत्वों का पुनर्नामकरण करते हैं जो -keep नियमों द्वारा संरक्षित नहीं हैं। मैपिंग फ़ाइल क्रैश लॉग को डीकोड करने के लिए मूल और ऑबफ़स्केट नामों के पत्राचार को संरक्षित करती है।
स्टैक ट्रेस को डीकोड करने के लिए, retrace उपयोगिता (ProGuard/R8 SDK का हिस्सा) का उपयोग करें। कमांड: retrace mapping.txt crash-stacktrace.txt। मैपिंग फ़ाइल build/outputs/mapping/release/mapping.txt पर स्थित है। Google Play Console AAB प्रकाशित करते समय mapping.txt अपलोड करने का भी समर्थन करता है — क्रैश लॉग कंसोल में स्वचालित रूप से डीकोड हो जाते हैं। मैपिंग फ़ाइल के बिना, स्टैक ट्रेस में केवल ऑबफ़स्केट नाम जैसे a.b.c() होंगे, जो डीबगिंग के लिए बेकार है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें