'रखें' नियम जोड़ना

डिफ़ॉल्ट सेटिंग के साथ ऐप्लिकेशन ऑप्टिमाइज़ेशन चालू करने पर, R8 ज़्यादा से ज़्यादा ऑप्टिमाइज़ेशन करता है, ताकि आपको परफ़ॉर्मेंस से जुड़े फ़ायदे मिल सकें. R8, कोड में कई बदलाव करता है. जैसे, क्लास फ़ील्ड और तरीकों का नाम बदलना, उन्हें एक जगह से दूसरी जगह ले जाना, और उन्हें हटाना. अगर इससे गड़बड़ियां होती हैं, तो आपको नियमों को बनाए रखें लिखकर, यह बताना होगा कि कोड के किन हिस्सों को बदलना नहीं है.

R8, इन स्थितियों में कोड को गलत तरीके से हटा सकता है या उसमें बदलाव कर सकता है:

  • रिफ़्लेक्शन: रिफ़्लेक्शन का इस्तेमाल करके ऐक्सेस किया गया कोड. उदाहरण के लिए, Class.forName() या Method.invoke() का इस्तेमाल करके. आम तौर पर, R8 यह नहीं बता सकता कि इस तरह से कौनसी क्लास या तरीकों को ऐक्सेस किया जाएगा.
  • सीरियलाइज़ेशन: ऐसा हो सकता है कि R8 को सीरियलाइज़ेशन और डीसीरियलाइज़ेशन के लिए ज़रूरी क्लास या फ़ील्ड का इस्तेमाल न करना पड़े. यह रिफ़्लेक्शन का एक और रूप है.
  • Java नेटिव इंटरफ़ेस (JNI): नेटिव कोड से कॉल किए गए Java तरीके. R8, नेटिव कोड का विश्लेषण नहीं करता, ताकि यह पता लगाया जा सके कि वह Java में क्या कॉल कर सकता है.

इस पेज पर, R8 के ऑप्टिमाइज़ेशन की सीमा तय करने का तरीका बताया गया है. कौनसे संसाधन बनाए रखने हैं, यह तय करने का तरीका जानने के लिए, संसाधनों को बनाए रखने के लिए नियम जोड़ना लेख पढ़ें.

'रखें' नियम कहां जोड़ें

आपको अपने नियम, मॉड्यूल की रूट डायरेक्ट्री में मौजूद proguard-rules.pro फ़ाइल में जोड़ने चाहिए. हो सकता है कि फ़ाइल पहले से मौजूद हो, लेकिन अगर नहीं है, तो उसे बनाएं. फ़ाइल में नियम लागू करने के लिए, आपको अपने मॉड्यूल-लेवल की build.gradle.kts (या build.gradle) फ़ाइल में फ़ाइल का एलान करना होगा, जैसा कि नीचे दिए गए कोड में दिखाया गया है:

Kotlin

android {
    buildTypes {
        release {
            isMinifyEnabled = true
            isShrinkResources = true

            proguardFiles(
                // Default file with default optimization rules.
                getDefaultProguardFile("proguard-android-optimize.txt"),

                // File with your custom rules.
                "proguard-rules.pro"
            )
            ...
        }
    }
    ...
}

Groovy

android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true

            proguardFiles(
                // Default file with default optimization rules.
                getDefaultProguardFile('proguard-android-optimize.txt'),

                // File with your custom rules.
                'proguard-rules.pro'
            )
        }
    }
    // ...
}

डिफ़ॉल्ट रूप से, आपकी बिल्ड स्क्रिप्ट में proguard-android-optimize.txt फ़ाइल भी शामिल होती है. इस फ़ाइल में ऐसे नियम शामिल होते हैं जो ज़्यादातर Android प्रोजेक्ट के लिए ज़रूरी होते हैं. इसलिए, आपको इसे बिल्ड स्क्रिप्ट में रखना चाहिए.

'डेटा सेव रखें' नियम लिखने का तरीका

ऐप्लिकेशन को कंपाइल करने के दौरान, R8 आपके ऐप्लिकेशन के कॉल ग्राफ़ का विश्लेषण करके यह पता लगाता है कि ऐप्लिकेशन में कौनसा कोड रखना है. यह विश्लेषण, मेनिफ़ेस्ट एंट्री (जैसे, आपकी गतिविधियां या सेवाएं) से शुरू होता है और हर ऐप्लिकेशन और लाइब्रेरी फ़ंक्शन कॉल को ट्रैक करता है. R8 उस कोड को हटा देता है जिसका सीधे तौर पर इस तरह से रेफ़रंस नहीं दिया गया है. अगर चलाया गया कोड इस ग्राफ़ का हिस्सा नहीं है, तो इससे समस्याएं हो सकती हैं. उदाहरण के लिए, रिफ़्लेक्शन की मदद से शुरू किया गया कोड. अपने हिसाब से नियम लिखकर, R8 को उस कोड के बारे में बताया जा सकता है जिसे ऐप्लिकेशन में बनाए रखना है.

'रखें' नियम जोड़ने के लिए, proguard-rules.pro फ़ाइल में -keep लाइन जोड़ें.

नियम का सिंटैक्स बनाए रखना

आम तौर पर, रखरखाव के नियम इस फ़ॉर्मैट में होते हैं:

-<KeepOption> [OptionalModifier,...] <ClassSpecification> [{ OptionalMemberSpecification }]

उदाहरण के लिए, किसी क्लास और उसके सभी सदस्यों को सुरक्षित रखने के लिए, यह तरीका अपनाएं:

-keep class com.myapp.MyClass { *; }

ज़्यादा उदाहरणों के लिए, उदाहरण वाला सेक्शन देखें.

यहां बताया गया है कि 'डेटा को सेव रखें' नियम के कॉम्पोनेंट क्या करते हैं:

  • <KeepOption> की मदद से, यह तय किया जा सकता है कि किसी क्लास के कौनसे हिस्से को सेव रखना है:

    विकल्प बनाए रखना ब्यौरा

    -keep

    [{ OptionalMemberSpecification }] में दी गई क्लास और सदस्यों को बनाए रखें.

    -keepclassmembers

    क्लास को ऑप्टिमाइज़ करने की अनुमति दें. अगर क्लास को सुरक्षित रखा जाता है, तो [{ OptionalMemberSpecification }] में दिए गए सदस्यों को सुरक्षित रखें.

    -keepnames

    क्लास और सदस्यों को हटाने की अनुमति दें, लेकिन उन्हें छिपाने या किसी दूसरे तरीके से बदलने की अनुमति न दें.

    -keepclassmembernames

    क्लास और सदस्यों को हटाने की अनुमति दें. हालांकि, सदस्यों की पहचान छिपाने या उनमें किसी दूसरे तरीके से बदलाव न करें.

    -keepclasseswithmembers

    अगर सदस्य तय किए गए पैटर्न से मेल खाते हैं, तो क्लास को न तो हटाया जाएगा और न ही धुंधला किया जाएगा.

    हमारा सुझाव है कि ज़्यादातर मामलों में -keepclassmembers का इस्तेमाल करें, क्योंकि इससे ज़्यादा ऑप्टिमाइज़ेशन की सुविधा मिलती है. इसके बाद, ज़रूरत पड़ने पर -keepnames का इस्तेमाल करें. -keep का इस्तेमाल करने पर, ऑप्टिमाइज़ेशन की सुविधा काम नहीं करती. इसलिए, इसका इस्तेमाल कम से कम करें.

  • [OptionalModifier],...] की मदद से, किसी क्लास के लिए Java भाषा के शून्य या उससे ज़्यादा मॉडिफ़ायर की सूची बनाई जा सकती है. उदाहरण के लिए, public या final.

  • <ClassSpecification> की मदद से, यह तय किया जा सकता है कि किस क्लास (या किस सुपरक्लास या लागू किए गए इंटरफ़ेस) पर, 'रखें' नियम लागू होना चाहिए. सबसे आसान मामले में, यह एक पूरी तरह से क्वालिफ़ाइड क्लास होती है.

  • [{ OptionalMemberSpecification }] की मदद से, 'डेटा को सेव रखें' सुविधा को सिर्फ़ उन क्लास और तरीकों के लिए फ़िल्टर किया जा सकता है जो कुछ पैटर्न से मैच करते हैं. आम तौर पर, ज़रूरत से ज़्यादा डेटा सेव होने से रोकने के लिए, डेटा सेव रखने के ज़्यादातर नियमों में इसका सुझाव दिया जाता है.

नियम के उदाहरण रखें

यहां, अच्छी तरह से डिज़ाइन किए गए 'रखें' नियमों के कुछ उदाहरण दिए गए हैं.

सब-क्लास बनाना

डेटाबेस कन्स्ट्रक्टर को रिफ़्लेक्शन की मदद से इंस्टैंशिएट करने के लिए, इस नियम को androidx.room:room-runtime के अंदर पैकेज किया गया है.

-keep class * extends androidx.room.RoomDatabase { void <init>(); }

Android फ़्रेमवर्क से मिलने वाला रिफ़्लेक्शन ObjectAnimator

'रखें' नियम को androidx.vectordrawable:vectordrawable-animated के अंदर पैकेज किया गया है, ताकि ObjectAnimator, JNI की मदद से नेटिव कोड से गेट्टर या सेटर को कॉल कर सके. ध्यान दें कि Compose में नए ऐनिमेशन सिस्टम के लिए, इस तरह के नियम रखने की ज़रूरत नहीं होती. यह नियम के स्ट्रक्चर का सिर्फ़ एक उदाहरण है.

-keepclassmembers class androidx.vectordrawable.graphics.drawable.VectorDrawableCompat$* {
   void set*(***);
   *** get*();
}

JNI रजिस्ट्रेशन

'रखें' नियम को androidx.graphics:graphics-path के अंदर पैकेज किया जाता है. इसका इस्तेमाल, नेटिव तरीकों को बनाए रखने के लिए किया जाता है. ऐसा तब ज़रूरी हो सकता है, जब आपकी लाइब्रेरी env->RegisterNatives() के साथ नेटिव तरीकों को मैन्युअल तरीके से रजिस्टर करती हो.

-keepclasseswithmembers class androidx.graphics.path.** {
    native <methods>;
}