ProGuard এবং R8 হল Android অ্যাপ্লিকেশনের জন্য অবফাসকেশন, মিনিফিকেশন এবং অপটিমাইজেশন টুল। ProGuard, যা ২০০২ সালে তৈরি হয়েছিল, দীর্ঘদিন ধরে Java কোড সুরক্ষার জন্য ডি-ফ্যাক্টো স্ট্যান্ডার্ড ছিল। R8 হল এর উত্তরসূরি, যা Google তৈরি করেছে এবং AGP ৩.৪ থেকে Android Gradle Plugin-এ অন্তর্ভুক্ত। উভয় টুলই APK আকার কমায়, মৃত কোড সরায় এবং রিভার্স ইঞ্জিনিয়ারিং জটিল করে তোলে। Android Developers-এর মতে, R8 তুলনামূলক অবফাসকেশন গুণমান সহ ProGuard-এর তুলনায় ২–৩ গুণ দ্রুত বিল্ড করে।
মূল পয়েন্ট
ProGuard হল একটি ওপেন-সোর্স টুল (Apache 2.0) Java বাইটকোডের অবফাসকেশন, মিনিফিকেশন, অপটিমাইজেশন এবং প্রিভেরিফিকেশনের জন্য। এটি Eric Lafarge ২০০২ সালে 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 নির্ধারণ করার পরে কোন ক্লাসগুলি ব্যবহার করা হয়, রিসোর্স shrinking কোড থেকে রিসোর্স রেফারেন্স বিশ্লেষণ করে: 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) | |
| রিলিজ বছর | ২০০২ | ২০১৮ (২০১৯-এ স্থিতিশীল) |
| আর্কিটেকচার | ৪টি পৃথক পর্যায় (shrink → optimize → obfuscate → preverify) | একক পাস: shrink + optimize + obfuscate একসাথে |
| AGP একীকরণ | বাহ্যিক টুল, javac-এর পরে চালিত | D8 DEX কম্পাইলারে অন্তর্ভুক্ত |
| বিল্ড গতি | ২–৩ গুণ ধীর | একক পাস এবং নেটিভ একীকরণের কারণে দ্রুত |
| Kotlin সমর্থন | সীমিত (inline, lambdas, coroutines-এ সমস্যা) | সম্পূর্ণ: coroutines, inline ফাংশন, data class |
| ম্যাপিং ফাইল | mapping.txt (retrace-এর সাথে সামঞ্জস্যপূর্ণ) | mapping.txt (একই ফরম্যাট) |
| অপটিমাইজেশন কাস্টমাইজেশন | ৬০+ অপশন -optimizationpasses, -optimizations | সীমিত: অধিকাংশ অপটিমাইজেশন ডিফল্টরূপে সক্রিয় |
| সমর্থন অবস্থা | R8 দ্বারা প্রতিস্থাপিত (AGP 7.0+ ব্যবহার করে না) | সক্রিয় উন্নয়ন, AOSP-এর অংশ |
R8 কোড অপসারণে ProGuard-এর চেয়ে বেশি আক্রমণাত্মক যা এটি মৃত বলে মনে করে। এটি এমন পরিস্থিতি তৈরি করে যেখানে ডিবাগ বিল্ড কাজ করে কিন্তু রিলিজ বিল্ড ClassNotFoundException বা NoSuchMethodException-এর সাথে ক্র্যাশ করে। সাধারণ ক্ষেত্রে: লাইব্রেরি যা ক্লাস নাম দ্বারা reflection ব্যবহার করে (Gson, Moshi, Retrofit, Room, Dagger); 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 আকার ২০–৫০% হ্রাস পাওয়া উচিত।
সচরাচর জিজ্ঞাস্য
R8 হল ProGuard-এর উত্তরসূরি, Google দ্বারা তৈরি। R8 একক পাসে অবফাসকেশন, মিনিফিকেশন এবং অপটিমাইজেশন করে, ProGuard-এর তুলনায় ২–৩ গুণ দ্রুত কাজ করে এবং সরাসরি Android Gradle Plugin-এ একীভূত। ProGuard চারটি পৃথক পর্যায় ব্যবহার করে এবং বাহ্যিক নির্বাহ প্রয়োজন। AGP ৭.০ থেকে, 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 ৩.৪ থেকে 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 অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন