ProGuard/R8: مفهوم، مبهم‌سازی و محافظت از برنامه‌های Android

نویسنده: IT Sectr منتشر شده: 2026-02-14 زمان مطالعه: 8 دقیقه

ProGuard و R8 — ابزارهای مبهم‌سازی، کوچک‌سازی و بهینه‌سازی برای برنامه‌های Android هستند. ProGuard که در سال 2002 ایجاد شد، مدت طولانی استاندارد دوفاکتو برای محافظت از کد Java بود. R8 — جانشین آن است که توسط Google توسعه یافته و از AGP 3.4 به بعد در Android Gradle Plugin تعبیه شده است. هر دو ابزار اندازه APK را کاهش می‌دهند، کد مرده را حذف می‌کنند و مهندسی معکوس را دشوارتر می‌سازند. طبق Android Developers، R8 در کیفیت مشابه مبهم‌سازی، ۲–۳ برابر سریع‌تر از ProGuard بیلد را انجام می‌دهد.

مهمترین نکات

  • ProGuard — ابزار مبهم‌سازی و بهینه‌سازی بایت‌کد Java، استاندارد Android از دهه ۲۰۰۰
  • R8 — جانشین ProGuard از Google، تعبیه شده در AGP، مبهم‌سازی، کوچک‌سازی و بهینه‌سازی را در یک پاس انجام می‌دهد
  • مبهم‌سازی نام کلاس‌ها و متدها را به نام‌های کوتاه تغییر می‌دهد و مهندسی معکوس برنامه را دشوار می‌کند
  • کوچک‌سازی کلاس‌ها، متدها و فیلدهای استفاده نشده را حذف کرده و اندازه APK/AAB نهایی را کاهش می‌دهد
  • ProGuard rules (فایل‌های .pro) مشخص می‌کنند که کدام بخش‌های کد نگهداری، مبهم‌سازی یا حذف شوند

ProGuard چیست؟

ProGuard — یک ابزار متن‌باز (Apache 2.0) برای مبهم‌سازی، کوچک‌سازی، بهینه‌سازی و پیش‌تأیید بایت‌کد Java است. توسط اریک لافورژ در سال ۲۰۰۲ در چارچوب پروژه SourceForge توسعه یافت. ProGuard کلاس‌های Java کامپایل شده (.class) یا بایگانی‌های JAR را به عنوان ورودی دریافت می‌کند و کلاس‌های پردازش شده با همان فرمت، اما با اندازه کوچک‌تر و عناصر تغییر نام یافته تحویل می‌دهد.

مدت طولانی ProGuard تنها استاندارد محافظت از برنامه‌های Android در برابر مهندسی معکوس بود. Google رسماً استفاده از آن را در Android SDK توصیه می‌کرد و پیکربندی پیش‌فرض را در فایل proguard-android-optimize.txt درون SDK tools ارائه می‌داد. ProGuard به عنوان یک ابزار مجزا پس از کامپایل کد Java به بایت‌کد و قبل از بسته‌بندی به DEX اجرا می‌شد.

معماری ProGuard

ProGuard از چهار فاز متوالی تشکیل شده است: shrink (حذف کلاس‌های استفاده نشده)، optimize (بهینه‌سازی بایت‌کد — درون‌خطی کردن، حذف کد مرده)، obfuscate (تغییر نام کلاس‌ها، متدها و فیلدها به نام‌های کوتاه)، preverify (بررسی سازگاری با JVM). هر فاز با قوانین جداگانه از فایل‌های پیکربندی کنترل می‌شود.

در مرحله مبهم‌سازی، ProGuard یک فایل mapping (mapping.txt) تولید می‌کند که نام‌های اصلی را به نام‌های مبهم‌سازی شده نگاشت می‌کند. این فایل برای رمزگشایی لاگ‌های crash از بیلدهای release با ابزار retrace حیاتی است. بدون فایل mapping، stack trace به مجموعه‌ای از حروف a()، b()، c() تبدیل می‌شود بدون امکان بازیابی زمینه اصلی.

فاز ProGuardهدفنتیجه
Shrinkتحلیل گراف فراخوانی و حذف کد مردهکاهش تعداد کلاس‌ها در APK
Optimizeدرون‌خطی کردن متدها، حذف پارامترهای استفاده نشدهتسریع اجرای کد
Obfuscateتغییر نام کلاس‌ها، فیلدها و متدهامحافظت در برابر مهندسی معکوس
Preverifyافزودن ویژگی‌های StackMap برای JVMسازگاری با Java 6+

R8 چیست؟

R8 — ابزار مبهم‌سازی و کوچک‌سازی نسل بعدی از Google است که اولین بار در Android Studio 3.3 (نوامبر ۲۰۱۸) معرفی و در AGP 3.4 (اوت ۲۰۱۹) به استاندارد تبدیل شد. برخلاف ProGuard، R8 بخشی از کامپایلر D8/R8 است که بایت‌کد Java را به فرمت DEX تبدیل می‌کند. R8 تمام فازها — مبهم‌سازی، کوچک‌سازی و بهینه‌سازی — را در یک پاس و بدون انتقال فایل‌های میانی بین ابزارها انجام می‌دهد.

Google R8 را با دو هدف توسعه داد: تسریع بیلد (ProGuard به عنوان ابزار خارجی کار می‌کرد) و تضمین یکپارچگی یکپارچه با پشته مدرن Android (Desugar، Core Library Desugaring، D8). R8 به زبان‌های Kotlin و Java نوشته شده و بخشی از مخزن R8/Desugar در AOSP (Android Open Source Project) است.

مزیت مهم R8 — سازگاری کامل رو به عقب با ProGuard rules است. فایل‌های .pro موجود بدون تغییر کار می‌کنند. R8 حتی از دستورات خاص ProGuard از جمله -whyareyoukeeping، -printconfiguration و -printmapping پشتیبانی می‌کند. این بدان معناست که انتقال از ProGuard به R8 به صورت شفاف انجام می‌شود: کافی است AGP را به‌روزرسانی کنید.

kotlin
// build.gradle.kts — فعال‌سازی R8 از طریق minifyEnabled
android {
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            isShrinkResources = true

            proguardFiles(
                // پیکربندی پایه از Android SDK
                getDefaultProguardFile("proguard-android-optimize.txt"),
                // قوانین سفارشی پروژه
                "proguard-rules.pro"
            )
        }
    }
}

کد پیکربندی استاندارد بیلد release را نشان می‌دهد. پرچم isMinifyEnabled = true R8 را برای مبهم‌سازی و بهینه‌سازی فعال می‌کند. isShrinkResources = true علاوه بر این منابع استفاده نشده را حذف می‌کند. getDefaultProguardFile قوانین پایه را از SDK بارگذاری می‌کند و proguard-rules.pro شامل تنظیمات خاص پروژه است.

مبهم‌سازی کد در Android

مبهم‌سازی — فرایند تبدیل کد مبدأ به فرمی است که تحلیل آن برای انسان دشوار است اما عملکرد کامل را حفظ می‌کند. در زمینه Android، مبهم‌سازی به معنای تغییر نام کلاس‌ها، متدها و فیلدها به نام‌های کوتاه و بی‌معنی است: com.example.app.auth.LoginManager به a.a.a، متد authenticateUser به a، فیلد userToken به b تبدیل می‌شود.

چرا مبهم‌سازی لازم است

فایل‌های APK Android آرشیوهایی هستند که با هر بایگانی‌کننده‌ای (ZIP، 7z، WinRAR) قابل باز شدن هستند. بدون مبهم‌سازی، مهاجم نقشه کامل برنامه را دریافت می‌کند: نام بسته‌ها، کلاس‌ها، متدها و فیلدها. ابزارهایی مانند jadx یا Bytecode Viewer تقریباً کد Java اصلی را از فایل‌های DEX در چند ثانیه بازسازی می‌کنند. مبهم‌سازی کد را غیرقابل نفوذ نمی‌کند اما آستانه ورود را به طور قابل توجهی افزایش می‌دهد: به جای نام‌های معنی‌دار، خواننده a()، b()، c() را می‌بیند.

اهداف معمول مبهم‌سازی: محافظت از منطق تجاری (الگوریتم‌ها، فرمول‌های محاسبه)، دشوار کردن سرقت کلیدهای API و توکن‌ها، جلوگیری از جایگزینی کلاس‌ها از طریق reflection، محافظت در برابر پچ و تغییر APK (repackage attack). در عمل ۷۰٪ کارها دقیقاً با تغییر نام حل می‌شود — به همین دلیل ProGuard / R8 اجرا می‌شوند.

مثال قوانین ProGuard

در زیر یک فایل معمولی proguard-rules.pro برای پروژه Android با Retrofit، Gson و Parcelable آورده شده است. قوانین -keep کلاس‌ها و متدهای لازم برای کار کتابخانه‌ها از طریق reflection را حفظ می‌کنند. بدون این قوانین، R8 کلاس‌هایی را که کتابخانه با نام رشته‌ای به آن دسترسی پیدا می‌کند حذف یا تغییر نام می‌دهد.

pro
# =====================
# 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 — حذف لاگ‌ها از release
# =====================
-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 فراداده‌ها را در بایت‌کد نگه می‌دارد — حاشیه‌نویسی‌ها، امضاها، استثناها.

قانون -keep,allowobfuscation,allowshrinking برای Retrofit به R8 اجازه می‌دهد نام رابط‌ها را تغییر دهد اما آنها را حذف نکند. این ضروری است زیرا Retrofit از طریق پروکسی پویا (java.lang.reflect.Proxy) به رابط‌ها دسترسی پیدا می‌کند و حذف آنها منجر به ClassNotFoundException در زمان اجرا می‌شود. به طور مشابه، Gson از reflection برای دسترسی به فیلدهای دارای حاشیه‌نویسی @SerializedName استفاده می‌کند — بدون -keepclassmembers فیلدها به عنوان استفاده نشده حذف می‌شوند.

کوچک‌سازی و ShrinkResources

کوچک‌سازی (shrinking) — فرایند حذف کد و منابع استفاده نشده از بیلد نهایی است. ProGuard و R8 گراف فراخوانی را از نقاط ورود (Activity، Service، BroadcastReceiver) تحلیل می‌کنند و کلاس‌ها و متدهایی را که از طریق زنجیره فراخوانی قابل دسترسی نیستند حذف می‌کنند. ShrinkResources — مرحله اضافی که منابع استفاده نشده را از res/ (layout، drawable، string، color) حذف می‌کند.

کوچک‌سازی بیشترین سود را در پروژه‌های بزرگ با کتابخانه‌ها می‌دهد. تصویر معمول: پروژه از ۱۰٪ کد کتابخانه متصل (مثلاً Google Play Services) استفاده می‌کند. بدون کوچک‌سازی، تمام کد کتابخانه وارد APK می‌شود. با کوچک‌سازی، R8 ۷۰–۹۰٪ کد کتابخانه‌ها را حذف می‌کند و فقط کلاس‌ها و متدهای واقعاً استفاده شده را باقی می‌گذارد. این به طور مستقیم بر اندازه APK، زمان بارگذاری و مصرف حافظه تأثیر می‌گذارد.

ShrinkResources در عمل

مکانیسم 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 را حفظ می‌کند.

xml
<!-- مثال: منبعی که فقط از طریق 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 ارجاع ایستا به dynamic_title_welcome را در کلاس R نمی‌بیند زیرا دسترسی از طریق 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: تفاوت‌های کلیدی

با وجود اینکه R8 جانشین ProGuard است، تفاوت‌های اساسی در معماری، عملکرد و رفتار بین ابزارها وجود دارد. Google رسماً پشتیبانی از ProGuard را در Android Gradle Plugin از AGP 7.0 متوقف کرده است، با این حال ProGuard همچنان در پروژه‌هایی که نیاز به رفتار بهینه‌سازی خاصی دارند که در R8 موجود نیست استفاده می‌شود.

جدول مقایسه

ویژگیProGuardR8
توسعه‌دهندهGuardSquare (اریک لافورژ)Google
سال عرضه۲۰۰۲۲۰۱۸ (پایدار در ۲۰۱۹)
معماری۴ فاز جداگانه (shrink → optimize → obfuscate → preverify)یک پاس: shrink + optimize + obfuscate همزمان
یکپارچگی در AGPابزار خارجی، پس از javac اجرا می‌شودتعبیه شده در کامپایلر D8 DEX
سرعت بیلد۲–۳ برابر کندترسریع‌تر به دلیل یک پاس و یکپارچگی بومی
پشتیبانی Kotlinمحدود (مشکلات با inline، lambdas، coroutines)کامل: coroutines، توابع inline، data class
فایل mappingmapping.txt (سازگار با retrace)mapping.txt (فرمت یکسان)
شخصی‌سازی بهینه‌سازی۶۰+ گزینه -optimizationpasses، -optimizationsمحدود: بیشتر بهینه‌سازی‌ها به طور پیش‌فرض فعال هستند
وضعیت پشتیبانیجایگزین شده با R8 (AGP 7.0+ استفاده نمی‌کند)توسعه فعال، بخشی از AOSP

چه زمانی R8 می‌تواند بیلد را خراب کند

R8 تهاجمی‌تر از ProGuard کدی را که مرده می‌داند حذف می‌کند. این منجر به موقعیت‌هایی می‌شود که بیلد debug کار می‌کند اما release با ClassNotFoundException یا NoSuchMethodException از کار می‌افتد. موارد معمول: کتابخانه‌هایی که از reflection با نام کلاس استفاده می‌کنند (Gson، Moshi، Retrofit، Room، Dagger)؛ فراخوانی‌های ServiceLoader یا java.util.ServiceLoader؛ پروکسی‌های پویا (java.lang.reflect.Proxy)؛ متدهای بومی (JNI). راه حل — اضافه کردن -keep برای همه کلاس‌هایی که از طریق reflection فراخوانی می‌شوند.

pro
# مشکلات معمول 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.** { *; }

اگر پس از اضافه کردن قوانین بیلد همچنان خراب می‌شود، از پرچم -printconfiguration full-config.txt در proguard-rules.pro استفاده کنید. R8 یک فایل پیکربندی کامل تولید می‌کند که نشان می‌دهد کدام قوانین اعمال شده و کدام کلاس‌ها نگهداری می‌شوند. همچنین دستور -whyareyoukeeping class com.example.MyClass مفید است — دلیل تصمیم R8 برای نگهداری کلاس را نشان می‌دهد.

پیکربندی ProGuard rules

پیکربندی صحیح 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 گنجانده شده و از طریق consumer guard rules به طور خودکار متصل می‌شوند. بررسی کنید که کتابخانه فایل proguard.txt را درون AAR ارائه می‌دهد — این نشانه آن است که قوانین قبلاً در نظر گرفته شده‌اند.

گام ۳: تست بیلد release

قبل از انتشار، حتماً بیلد release را روی یک دستگاه واقعی یا شبیه‌ساز تست کنید. مشکلات مبهم‌سازی فقط در زمان اجرا ظاهر می‌شوند. بررسی کنید: احراز هویت (ورود/ثبت‌نام)، بارگیری داده از شبکه، ناوبری بین صفحه‌ها، دوربین و گالری، اعلان‌های push، Deeplinks، WebView. هر crash در بیلد release باید با retrace و فایل mapping رمزگشایی شود و قوانین -keep缺失 اضافه شوند.

گام ۴: فایل mapping و CI

فایل mapping در build/outputs/mapping/release/mapping.txt تولید می‌شود. این فایل برای ذخیره‌سازی الزامی است: بدون آن نمی‌توان لاگ‌های crash را از Google Play Console رمزگشایی کرد. mapping.txt را در سیستم کنترل نسخه قرار دهید یا آن را به عنوان مصنوعات CI بارگذاری کنید. Google Play Console فایل mapping را هنگام بارگذاری AAB با uploading mapping.txt فعال به طور خودکار می‌پذیرد.

در زیر گردش کار کامل پیکربندی مبهم‌سازی در فایل proguard-rules.pro با توضیحات برای هر گروه از قوانین آورده شده است.

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 چیست؟

R8 — جانشین ProGuard است که توسط Google توسعه یافته. R8 مبهم‌سازی، کوچک‌سازی و بهینه‌سازی را در یک پاس انجام می‌دهد، ۲–۳ برابر سریع‌تر از ProGuard کار می‌کند و مستقیماً در Android Gradle Plugin یکپارچه شده است. ProGuard از چهار فاز جداگانه استفاده می‌کند و نیاز به اجرای خارجی دارد. از AGP 7.0 ProGuard استفاده نمی‌شود — به طور پیش‌فرض R8 کار می‌کند.

آیا هنگام استفاده از R8 باید ProGuard rules نوشت؟

بله، R8 از همان ProGuard rules (فایل‌های .pro) استفاده می‌کند. دستورات -keep، -keepclassmembers، -keepattributes، -assumenosideeffects به طور یکسان کار می‌کنند. قوانین پایه در proguard-android-optimize.txt از Android SDK وجود دارند و قوانین خاص کتابخانه‌ها (Retrofit، Room، Gson) در proguard-rules.pro پروژه اضافه می‌شوند. بدون این قوانین، R8 می‌تواند کلاس‌های لازم برای کار کتابخانه‌ها از طریق reflection را حذف کند.

چگونه R8 را در پروژه Android فعال کنیم؟

R8 به طور پیش‌فرض در Android Gradle Plugin از AGP 3.4 فعال است. برای فعال‌سازی کوچک‌سازی، isMinifyEnabled = true را در بلوک release buildType فایل build.gradle.kts تنظیم کنید. پرچم اضافی isShrinkResources = true حذف منابع استفاده نشده را فعال می‌کند. در gradle.properties می‌توان R8 را از طریق android.enableR8=false به زور غیرفعال کرد، اما این توصیه نمی‌شود — R8 سریع‌تر و پایدارتر است.

مبهم‌سازی کد در Android چیست؟

مبهم‌سازی — تغییر نام کلاس‌ها، متدها و فیلدها به نام‌های کوتاه بی‌معنی (a، b، c). کلاس com.example.app.auth.LoginManager به a.a.a، متد authenticateUser به a تبدیل می‌شود. این مهندسی معکوس برنامه را دشوار می‌کند اما بر منطق اجرا تأثیر نمی‌گذارد. ProGuard و R8 فقط عناصری را تغییر نام می‌دهند که توسط قوانین -keep محافظت نشده‌اند. فایل mapping تناظر نام‌های اصلی و مبهم‌سازی شده را برای رمزگشایی لاگ‌های crash حفظ می‌کند.

چگونه crash-log برنامه مبهم‌سازی شده را دیباگ کنیم؟

برای رمزگشایی stack trace از ابزار retrace (بخشی از ProGuard/R8 SDK) استفاده می‌شود. دستور: retrace mapping.txt crash-stacktrace.txt. فایل mapping در build/outputs/mapping/release/mapping.txt قرار دارد. Google Play Console نیز از بارگذاری mapping.txt هنگام انتشار AAB پشتیبانی می‌کند — لاگ‌های crash به طور خودکار در کنسول رمزگشایی می‌شوند. بدون فایل mapping، stack trace فقط شامل نام‌های مبهم‌سازی شده a.b.c() خواهد بود که برای دیباگ بی‌فایده است.

خلاصه

  • ProGuard — ابزار کلاسیک مبهم‌سازی و بهینه‌سازی بایت‌کد Java، متشکل از چهار فاز متوالی
  • R8 — جانشین مدرن از Google، تعبیه شده در AGP، تمام فازها را در یک پاس با عملکرد ۲–۳ برابر بالاتر انجام می‌دهد
  • مبهم‌سازی نام کلاس‌ها، متدها و فیلدها را به نام‌های کوتاه تغییر می‌دهد، مهندسی معکوس را دشوار می‌کند و از منطق تجاری برنامه محافظت می‌کند
  • کوچک‌سازی کد و منابع استفاده نشده را حذف می‌کند، اندازه APK را در پروژه‌های معمولی ۲۰–۵۰٪ کاهش می‌دهد
  • ProGuard rules (فایل‌های .pro) رفتار مبهم‌سازی را کنترل می‌کنند — دستورات -keep، -keepclassmembers، -assumenosideeffects مشخص می‌کنند کدام عناصر نگهداری، حذف یا تغییر نام می‌یابند
  • فایل mapping (mapping.txt) — مصنوع بیلد حیاتی برای رمزگشایی لاگ‌های crash از بیلدهای release از طریق retrace
  • تست بیلد release روی دستگاه واقعی الزامی است — مشکلات مبهم‌سازی فقط در زمان اجرا ظاهر می‌شوند و نیاز به اضافه کردن قوانین -keep缺失 دارند

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید