बिल्ड के वैरिएंट कॉन्फ़िगर करें

इस पेज पर बताया गया है कि आप एक ही प्रोजेक्ट से अपने ऐप्लिकेशन के अलग-अलग वर्शन बनाने के लिए, बिल्ड वैरिएंट कैसे कॉन्फ़िगर कर सकते हैं. साथ ही, अपनी डिपेंडेंसी और साइनिंग कॉन्फ़िगरेशन को सही तरीके से मैनेज करने का तरीका भी बताया गया है.

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

बिल्ड के वैरिएंट, Gradle को बनाने के लिए बने नियमों के खास सेट का इस्तेमाल करते हैं. इससे आपके बिल्ड टाइप और प्रॉडक्ट के फ़्लेवर में कॉन्फ़िगर की गई सेटिंग, कोड, और संसाधनों को जोड़ा जाता है. हालांकि, सीधे तौर पर बिल्ड वैरिएंट को कॉन्फ़िगर नहीं किया जाता, लेकिन उनसे बने बिल्ड टाइप और प्रॉडक्ट फ़्लेवर को कॉन्फ़िगर किया जाता है.

उदाहरण के लिए, किसी "डेमो" प्रॉडक्ट फ़्लेवर से कुछ सुविधाओं और डिवाइस की ज़रूरी शर्तों के बारे में पता चल सकता है. जैसे, कस्टम सोर्स कोड, रिसॉर्स, और एपीआई लेवल के कम से कम लेवल. वहीं, "डीबग" बिल्ड टाइप में, बिल्ड और पैकेजिंग की अलग-अलग सेटिंग लागू होती हैं. जैसे, डीबग करने के विकल्प और साइनिंग पासकोड. इन दोनों को मिलाकर बनाया गया बिल्ड वैरिएंट, आपके ऐप्लिकेशन का "demoDebug" वर्शन होता है. इसमें "demo" प्रॉडक्ट फ़्लेवर, "debug" बिल्ड टाइप, और main/ सोर्स सेट में शामिल कॉन्फ़िगरेशन और संसाधनों का कॉम्बिनेशन शामिल होता है.

बिल्ड टाइप कॉन्फ़िगर करना

मॉड्यूल-लेवल build.gradle.kts फ़ाइल के android ब्लॉक में, बिल्ड टाइप बनाए और कॉन्फ़िगर किए जा सकते हैं. नया मॉड्यूल बनाने पर, Android Studio अपने-आप डीबग और रिलीज़ बाइल्ड टाइप बना देता है. हालांकि, डीबग बिल्ड टाइप, बिल्ड कॉन्फ़िगरेशन फ़ाइल में नहीं दिखता, लेकिन Android Studio इसे debuggable true के साथ कॉन्फ़िगर करता है. इसकी मदद से, सुरक्षित Android डिवाइसों पर ऐप्लिकेशन को डीबग किया जा सकता है. साथ ही, सामान्य डीबग कीस्टोर की मदद से, ऐप्लिकेशन साइनिंग को कॉन्फ़िगर किया जा सकता है.

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

Kotlin

android {
    defaultConfig {
        manifestPlaceholders["hostName"] = "www.example.com"
        ...
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
        }

        getByName("debug") {
            applicationIdSuffix = ".debug"
            isDebuggable = true
        }

        /**
         * The `initWith` property lets you copy configurations from other build types,
         * then configure only the settings you want to change. This one copies the debug build
         * type, and then changes the manifest placeholder and application ID.
         */
        create("staging") {
            initWith(getByName("debug"))
            manifestPlaceholders["hostName"] = "internal.example.com"
            applicationIdSuffix = ".debugStaging"
        }
    }
}

Groovy

android {
    defaultConfig {
        manifestPlaceholders = [hostName:"www.example.com"]
        ...
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug {
            applicationIdSuffix ".debug"
            debuggable true
        }

        /**
         * The `initWith` property lets you copy configurations from other build types,
         * then configure only the settings you want to change. This one copies the debug build
         * type, and then changes the manifest placeholder and application ID.
         */
        staging {
            initWith debug
            manifestPlaceholders = [hostName:"internal.example.com"]
            applicationIdSuffix ".debugStaging"
        }
    }
}

ध्यान दें: किसी बिल्ड कॉन्फ़िगरेशन फ़ाइल में बदलाव करने पर, Android Studio आपसे अपने प्रोजेक्ट को नए कॉन्फ़िगरेशन के साथ सिंक करने के लिए कहता है. अपने प्रोजेक्ट को सिंक करने के लिए, बदलाव करने पर दिखने वाली सूचना बार में अभी सिंक करें पर क्लिक करें या टूलबार में जाकर प्रोजेक्ट सिंक करें पर क्लिक करें. अगर Android Studio को आपके कॉन्फ़िगरेशन में कोई गड़बड़ी दिखती है, तो समस्या के बारे में बताने के लिए मैसेज विंडो दिखती है.

उन सभी प्रॉपर्टी के बारे में ज़्यादा जानने के लिए जिन्हें बिल्ड टाइप के साथ कॉन्फ़िगर किया जा सकता है, BuildType रेफ़रंस पढ़ें.

प्रॉडक्ट के अलग-अलग वर्शन कॉन्फ़िगर करना

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

ध्यान दें: आपको अब भी main/ मेनिफ़ेस्ट फ़ाइल में, package एट्रिब्यूट का इस्तेमाल करके पैकेज का नाम बताना होगा. आपको अपने सोर्स कोड में उस पैकेज के नाम का भी इस्तेमाल करना होगा, ताकि R क्लास को रेफ़र किया जा सके या किसी भी गतिविधि या सेवा के रजिस्ट्रेशन से जुड़ी समस्या को हल किया जा सके. इससे, applicationId का इस्तेमाल करके, हर प्रॉडक्ट फ़्लेवर को पैकेजिंग और डिस्ट्रिब्यूशन के लिए यूनीक आईडी दिया जा सकता है. इसके लिए, आपको अपने सोर्स कोड में बदलाव करने की ज़रूरत नहीं है.

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

  Error: All flavors must now belong to a named flavor dimension.
  The flavor 'flavor_name' is not assigned to a flavor dimension.

अगर किसी मॉड्यूल में सिर्फ़ एक फ़्लेवर डाइमेंशन तय किया गया है, तो Android Gradle प्लग इन उस डाइमेंशन में मॉड्यूल के सभी फ़्लेवर को अपने-आप असाइन कर देता है.

नीचे दिया गया कोड सैंपल, "वर्शन" नाम का एक फ़्लेवर डाइमेंशन बनाता है और "डेमो" और "पूरा" प्रॉडक्ट फ़्लेवर जोड़ता है. इन फ़्लेवर की पहचान, अपने-आप applicationIdSuffix और versionNameSuffix के लिए की जाती है:

Kotlin

android {
    ...
    defaultConfig {...}
    buildTypes {
        getByName("debug"){...}
        getByName("release"){...}
    }
    // Specifies one flavor dimension.
    flavorDimensions += "version"
    productFlavors {
        create("demo") {
            // Assigns this product flavor to the "version" flavor dimension.
            // If you are using only one dimension, this property is optional,
            // and the plugin automatically assigns all the module's flavors to
            // that dimension.
            dimension = "version"
            applicationIdSuffix = ".demo"
            versionNameSuffix = "-demo"
        }
        create("full") {
            dimension = "version"
            applicationIdSuffix = ".full"
            versionNameSuffix = "-full"
        }
    }
}

Groovy

android {
    ...
    defaultConfig {...}
    buildTypes {
        debug{...}
        release{...}
    }
    // Specifies one flavor dimension.
    flavorDimensions "version"
    productFlavors {
        demo {
            // Assigns this product flavor to the "version" flavor dimension.
            // If you are using only one dimension, this property is optional,
            // and the plugin automatically assigns all the module's flavors to
            // that dimension.
            dimension "version"
            applicationIdSuffix ".demo"
            versionNameSuffix "-demo"
        }
        full {
            dimension "version"
            applicationIdSuffix ".full"
            versionNameSuffix "-full"
        }
    }
}

ध्यान दें: अगर आपके पास अगस्त 2021 से पहले बनाया गया कोई लेगसी ऐप्लिकेशन है, जिसे Google Play पर APKs का इस्तेमाल करके डिस्ट्रिब्यूट किया जाता है, तो Google Play पर एक से ज़्यादा APKs के साथ काम करने की सुविधा का इस्तेमाल करके अपना ऐप्लिकेशन डिस्ट्रिब्यूट करने के लिए, सभी वैरिएंट के लिए एक ही applicationId वैल्यू असाइन करें. साथ ही, हर वैरिएंट के लिए एक अलग versionCode असाइन करें. Google Play पर अपने ऐप्लिकेशन के अलग-अलग वैरिएंट को अलग-अलग ऐप्लिकेशन के तौर पर डिस्ट्रिब्यूट करने के लिए, आपको हर वैरिएंट के लिए एक अलग applicationId असाइन करना होगा.

प्रॉडक्ट के फ़्लेवर बनाने और उन्हें कॉन्फ़िगर करने के बाद, सूचना बार में अभी सिंक करें पर क्लिक करें. सिंक होने के बाद, Gradle आपके बिल्ड टाइप और प्रॉडक्ट के स्वाद के आधार पर, बिल्ड वैरिएंट अपने-आप बनाता है और उन्हें <product-flavor><Build-Type> के हिसाब से नाम देता है. उदाहरण के लिए, अगर आपने "डेमो" और "पूरा" प्रॉडक्ट फ़्लेवर बनाए हैं और डिफ़ॉल्ट "डीबग" और "रिलीज़" बिल्ड टाइप को बनाए रखा है, तो Gradle ये बिल्ड वैरिएंट बनाता है:

  • demoDebug
  • demoRelease
  • fullDebug
  • fullRelease

बिल्ड का कौनसा वैरिएंट बनाना और चलाना है, यह चुनने के लिए, बिल्ड > बिल्ड वैरिएंट चुनें पर जाएं और मेन्यू से कोई बिल्ड वैरिएंट चुनें. हर बिल्ड वैरिएंट को अपनी सुविधाओं और संसाधनों के हिसाब से कस्टमाइज़ करने के लिए, आपको इस पेज पर बताए गए तरीके से सोर्स सेट बनाने और उन्हें मैनेज करने होंगे.

बिल्ड वैरिएंट के लिए ऐप्लिकेशन आईडी बदलना

अपने ऐप्लिकेशन के लिए APK या AAB बनाते समय, बिल्ड टूल ऐप्लिकेशन को build.gradle.kts फ़ाइल के defaultConfig ब्लॉक में बताए गए ऐप्लिकेशन आईडी से टैग करते हैं. इस बारे में नीचे दिए गए उदाहरण में बताया गया है. हालांकि, अगर आपको Google Play Store पर अपने ऐप्लिकेशन के अलग-अलग वर्शन, जैसे कि "मुफ़्त" और "प्रो" वर्शन, अलग-अलग स्टोर पेज के तौर पर दिखाने हैं, तो आपको उन वैरिएंट को बनाने की ज़रूरत होगी जिनमें हर एक का ऐप्लिकेशन आईडी अलग-अलग हो.

इस मामले में, हर बिल्ड वैरिएंट को अलग-अलग प्रॉडक्ट फ़्लेवर के तौर पर तय करें. productFlavors ब्लॉक में हर फ़्लेवर के लिए, applicationId प्रॉपर्टी को फिर से तय किया जा सकता है या applicationIdSuffix का इस्तेमाल करके, डिफ़ॉल्ट ऐप्लिकेशन आईडी में एक सेगमेंट जोड़ा जा सकता है, जैसा कि यहां दिखाया गया है:

Kotlin

android {
    defaultConfig {
        applicationId = "com.example.myapp"
    }
    productFlavors {
        create("free") {
            applicationIdSuffix = ".free"
        }
        create("pro") {
            applicationIdSuffix = ".pro"
        }
    }
}

Groovy

android {
    defaultConfig {
        applicationId "com.example.myapp"
    }
    productFlavors {
        free {
            applicationIdSuffix ".free"
        }
        pro {
            applicationIdSuffix ".pro"
        }
    }
}

इस तरह, "मुफ़्त" प्रॉडक्ट फ़्लेवर के लिए ऐप्लिकेशन आईडी, "com.example.myapp.free" होगा.

अपने बिल्ड टाइप के आधार पर, सेगमेंट को जोड़ने के लिए applicationIdSuffix का भी इस्तेमाल किया जा सकता है, जैसा कि यहां दिखाया गया है:

Kotlin

android {
    ...
    buildTypes {
        getByName("debug") {
            applicationIdSuffix = ".debug"
        }
    }
}

Groovy

android {
    ...
    buildTypes {
        debug {
            applicationIdSuffix ".debug"
        }
    }
}

Gradle, प्रॉडक्ट फ़्लेवर के बाद बिल्ड टाइप कॉन्फ़िगरेशन लागू करता है. इसलिए, "मुफ़्त डीबग" बिल्ड वैरिएंट के लिए ऐप्लिकेशन आईडी, "com.example.myapp.free.debug" है. यह तब फ़ायदेमंद होता है, जब आपको एक ही डिवाइस में डीबग और रिलीज़, दोनों को रखना हो, क्योंकि किसी भी दो ऐप्लिकेशन का ऐप्लिकेशन आईडी एक जैसा नहीं हो सकता.

अगर आपके पास अगस्त 2021 से पहले बनाया गया कोई लेगसी ऐप्लिकेशन है, जिसे Google Play पर APKs का इस्तेमाल करके डिस्ट्रिब्यूट किया जाता है और आपको एक ही ऐप्लिकेशन लिस्टिंग का इस्तेमाल करके, कई APKs डिस्ट्रिब्यूट करने हैं, तो हर APK को एक अलग versionCode दें. साथ ही, हर APK के लिए एक ही ऐप्लिकेशन आईडी का इस्तेमाल करें. ज़्यादा जानकारी के लिए, एक से ज़्यादा APK इस्तेमाल करने की सुविधा के बारे में पढ़ें. AABs का इस्तेमाल करके पब्लिश करने पर कोई असर नहीं पड़ता, क्योंकि इसमें एक आर्टफ़ैक्ट का इस्तेमाल किया जाता है. यह आर्टफ़ैक्ट डिफ़ॉल्ट रूप से एक वर्शन कोड और ऐप्लिकेशन आईडी का इस्तेमाल करता है.

सलाह: अगर आपको अपनी मेनिफ़ेस्ट फ़ाइल में ऐप्लिकेशन आईडी का रेफ़रंस देना है, तो किसी भी मेनिफ़ेस्ट एट्रिब्यूट में ${applicationId} प्लेसहोल्डर का इस्तेमाल किया जा सकता है. बिल्ड के दौरान, Gradle इस टैग को असली ऐप्लिकेशन आईडी से बदल देता है. ज़्यादा जानकारी के लिए, मेनिफ़ेस्ट में बिल्ड वैरिएबल इंजेक्ट करना लेख पढ़ें.

फ़्लेवर डाइमेंशन की मदद से, प्रॉडक्ट के कई फ़्लेवर को जोड़ना

कुछ मामलों में, आपको कई प्रॉडक्ट के वर्शन के कॉन्फ़िगरेशन को एक साथ जोड़ना पड़ सकता है. उदाहरण के लिए, हो सकता है कि आप प्रॉडक्ट के "फ़ुल" और "डेमो" फ़्लेवर के लिए, अलग-अलग कॉन्फ़िगरेशन बनाना चाहें. ये कॉन्फ़िगरेशन, एपीआई लेवल पर आधारित होते हैं. ऐसा करने के लिए, Android Gradle प्लग इन की मदद से, प्रॉडक्ट के अलग-अलग वर्शन के कई ग्रुप बनाए जा सकते हैं. इन्हें, वर्शन के डाइमेंशन के तौर पर बनाया जाता है.

आपके ऐप्लिकेशन को बिल्ड करते समय, Gradle आपके तय किए गए हर फ़्लेवर डाइमेंशन के प्रॉडक्ट फ़्लेवर कॉन्फ़िगरेशन को, बिल्ड टाइप कॉन्फ़िगरेशन के साथ जोड़ता है. इससे, फ़ाइनल बिल्ड वैरिएंट बनता है. Gradle, एक ही फ़्लेवर डाइमेंशन से जुड़े प्रॉडक्ट फ़्लेवर को एक साथ नहीं जोड़ता.

यहां दिए गए कोड सैंपल में, "फ़ुल" और "डेमो" प्रॉडक्ट फ़्लेवर को ग्रुप करने के लिए, "मोड" फ़्लेवर डाइमेंशन बनाने के लिए flavorDimensions प्रॉपर्टी का इस्तेमाल किया गया है. साथ ही, एपीआई लेवल के आधार पर प्रॉडक्ट फ़्लेवर कॉन्फ़िगरेशन को ग्रुप करने के लिए, "एपीआई" फ़्लेवर डाइमेंशन का इस्तेमाल किया गया है:

Kotlin

android {
  ...
  buildTypes {
    getByName("debug") {...}
    getByName("release") {...}
  }

  // Specifies the flavor dimensions you want to use. The order in which you
  // list the dimensions determines their priority, from highest to lowest,
  // when Gradle merges variant sources and configurations. You must assign
  // each product flavor you configure to one of the flavor dimensions.
  flavorDimensions += listOf("api", "mode")

  productFlavors {
    create("demo") {
      // Assigns this product flavor to the "mode" flavor dimension.
      dimension = "mode"
      ...
    }

    create("full") {
      dimension = "mode"
      ...
    }

    // Configurations in the "api" product flavors override those in "mode"
    // flavors and the defaultConfig block. Gradle determines the priority
    // between flavor dimensions based on the order in which they appear next
    // to the flavorDimensions property, with the first dimension having a higher
    // priority than the second, and so on.
    create("minApi24") {
      dimension = "api"
      minSdk = 24
      // To ensure the target device receives the version of the app with
      // the highest compatible API level, assign version codes in increasing
      // value with API level.
      versionCode = 30000 + (android.defaultConfig.versionCode ?: 0)
      versionNameSuffix = "-minApi24"
      ...
    }

    create("minApi23") {
      dimension = "api"
      minSdk = 23
      versionCode = 20000  + (android.defaultConfig.versionCode ?: 0)
      versionNameSuffix = "-minApi23"
      ...
    }

    create("minApi21") {
      dimension = "api"
      minSdk = 21
      versionCode = 10000  + (android.defaultConfig.versionCode ?: 0)
      versionNameSuffix = "-minApi21"
      ...
    }
  }
}
...

ग्रूवी

android {
  ...
  buildTypes {
    debug {...}
    release {...}
  }

  // Specifies the flavor dimensions you want to use. The order in which you
  // list the dimensions determines their priority, from highest to lowest,
  // when Gradle merges variant sources and configurations. You must assign
  // each product flavor you configure to one of the flavor dimensions.
  flavorDimensions "api", "mode"

  productFlavors {
    demo {
      // Assigns this product flavor to the "mode" flavor dimension.
      dimension "mode"
      ...
    }

    full {
      dimension "mode"
      ...
    }

    // Configurations in the "api" product flavors override those in "mode"
    // flavors and the defaultConfig block. Gradle determines the priority
    // between flavor dimensions based on the order in which they appear next
    // to the flavorDimensions property, with the first dimension having a higher
    // priority than the second, and so on.
    minApi24 {
      dimension "api"
      minSdkVersion 24
      // To ensure the target device receives the version of the app with
      // the highest compatible API level, assign version codes in increasing
      // value with API level.

      versionCode 30000 + android.defaultConfig.versionCode
      versionNameSuffix "-minApi24"
      ...
    }

    minApi23 {
      dimension "api"
      minSdkVersion 23
      versionCode 20000  + android.defaultConfig.versionCode
      versionNameSuffix "-minApi23"
      ...
    }

    minApi21 {
      dimension "api"
      minSdkVersion 21
      versionCode 10000  + android.defaultConfig.versionCode
      versionNameSuffix "-minApi21"
      ...
    }
  }
}
...

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

उदाहरण के तौर पर, पिछले बिल्ड कॉन्फ़िगरेशन का इस्तेमाल करके, Gradle कुल 12 बिल्ड वैरिएंट बनाता है. इनका नाम इस तरीके से रखा जाता है:

  • बिल्ड का वैरिएंट: [minApi24, minApi23, minApi21][Demo, Full][Debug, Release]
  • संबंधित APK: app-[minApi24, minApi23, minApi21]-[demo, full]-[debug, release].apk
  • उदाहरण के लिए,
    वैरिएंट बनाना: minApi24DemoDebug
    इससे मिलता-जुलता APK: app-minApi24-demo-debug.apk

हर प्रॉडक्ट के फ़्लेवर और वैरिएंट के हिसाब से सोर्स सेट डायरेक्ट्री बनाने के अलावा, प्रॉडक्ट के हर फ़्लेवर के कॉम्बिनेशन के लिए भी सोर्स सेट डायरेक्ट्री बनाई जा सकती हैं. उदाहरण के लिए, src/demoMinApi24/java/ डायरेक्ट्री में Java सोर्स बनाए और जोड़े जा सकते हैं. साथ ही, Gradle उन सोर्स का इस्तेमाल सिर्फ़ तब करता है, जब उन दो प्रॉडक्ट फ़्लेवर को मिलाकर कोई वैरिएंट बनाया जाता है.

प्रॉडक्ट फ़्लेवर के कॉम्बिनेशन के लिए बनाए गए सोर्स सेट, हर प्रॉडक्ट फ़्लेवर के सोर्स सेट की तुलना में ज़्यादा प्राथमिकता पाते हैं. सोर्स सेट और Gradle के ज़रिए संसाधनों को मर्ज करने के तरीके के बारे में ज़्यादा जानने के लिए, सोर्स सेट बनाने का तरीका बताने वाला सेक्शन पढ़ें.

वैरिएंट फ़िल्टर करना

Gradle, कॉन्फ़िगर किए गए प्रॉडक्ट के हर संभावित कॉम्बिनेशन के लिए, एक बिल्ड वैरिएंट बनाता है. हालांकि, ऐसा हो सकता है कि कुछ ऐसे बिल्ड वैरिएंट हों जिनकी आपको ज़रूरत न हो या जो आपके प्रोजेक्ट के कॉन्टेक्स्ट में काम के न हों. बिल्ड वैरिएंट के कुछ कॉन्फ़िगरेशन हटाने के लिए, अपने मॉड्यूल-लेवल की build.gradle.kts फ़ाइल में वैरिएंट फ़िल्टर बनाएं.

उदाहरण के लिए, पिछले सेक्शन में दिए गए बिल्ड कॉन्फ़िगरेशन का इस्तेमाल करके, मान लें कि आपको ऐप्लिकेशन के डेमो वर्शन के लिए, सिर्फ़ एपीआई लेवल 23 और उससे बाद के वर्शन का इस्तेमाल करना है. "minApi21" और "demo" प्रॉडक्ट फ़्लेवर को जोड़ने वाले सभी बिल्ड वैरिएंट कॉन्फ़िगरेशन को फ़िल्टर करने के लिए, variantFilter ब्लॉक का इस्तेमाल किया जा सकता है:

Kotlin

android {
  ...
  buildTypes {...}

  flavorDimensions += listOf("api", "mode")
  productFlavors {
    create("demo") {...}
    create("full") {...}
    create("minApi24") {...}
    create("minApi23") {...}
    create("minApi21") {...}
  }
}

androidComponents {
    beforeVariants { variantBuilder ->
        // To check for a certain build type, use variantBuilder.buildType == "<buildType>"
        if (variantBuilder.productFlavors.containsAll(listOf("api" to "minApi21", "mode" to "demo"))) {
            // Gradle ignores any variants that satisfy the conditions above.
            variantBuilder.enable = false
        }
    }
}
...

Groovy

android {
  ...
  buildTypes {...}

  flavorDimensions "api", "mode"
  productFlavors {
    demo {...}
    full {...}
    minApi24 {...}
    minApi23 {...}
    minApi21 {...}
  }

  variantFilter { variant ->
      def names = variant.flavors*.name
      // To check for a certain build type, use variant.buildType.name == "<buildType>"
      if (names.contains("minApi21") && names.contains("demo")) {
          // Gradle ignores any variants that satisfy the conditions above.
          setIgnore(true)
      }
  }
}
...

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

सोर्स सेट बनाएं

डिफ़ॉल्ट रूप से, Android Studio main/ सोर्स सेट और डायरेक्ट्री बनाता है. ऐसा उन सभी चीज़ों के लिए किया जाता है जिन्हें आपको अपने सभी बिल्ड वैरिएंट के बीच शेयर करना है. हालांकि, यह कंट्रोल करने के लिए नए सोर्स सेट बनाए जा सकते हैं कि Gradle कंपाइलेशन और खास बिल्ड टाइप के लिए कौनसे पैकेज, प्रॉडक्ट के फ़्लेवर, प्रॉडक्ट के फ़्लेवर के कॉम्बिनेशन (फ़्लेवर डाइमेंशन का इस्तेमाल करते समय), और वैरिएंट बनाएं.

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

Gradle को उम्मीद है कि सोर्स सेट की फ़ाइलों और डायरेक्ट्री को main/ सोर्स सेट की तरह ही व्यवस्थित किया गया हो. उदाहरण के लिए, Gradle के हिसाब से, "डीबग" बिल्ड टाइप के लिए खास तौर पर बनाई गई Kotlin या Java क्लास फ़ाइलें, src/debug/kotlin/ या src/debug/java/ डायरेक्ट्री में होनी चाहिए.

'Android Gradle प्लग इन', Gradle ऐप्लिकेशन का एक उपयोगी काम करता है, जिससे आपको हर तरह के बिल्ड टाइप, प्रॉडक्ट के फ़्लेवर और बिल्ड के वैरिएंट के लिए अपनी फ़ाइलों को व्यवस्थित करने का तरीका पता चलता है. उदाहरण के लिए, टास्क के आउटपुट से मिले इस सैंपल में बताया गया है कि Gradle को "डीबग" बिल्ड टाइप के लिए, कुछ फ़ाइलें कहां मिल सकती हैं:

------------------------------------------------------------
Project :app
------------------------------------------------------------

...

debug
----
Compile configuration: debugCompile
build.gradle name: android.sourceSets.debug
Java sources: [app/src/debug/java]
Kotlin sources: [app/src/debug/kotlin, app/src/debug/java]
Manifest file: app/src/debug/AndroidManifest.xml
Android resources: [app/src/debug/res]
Assets: [app/src/debug/assets]
AIDL sources: [app/src/debug/aidl]
RenderScript sources: [app/src/debug/rs]
JNI sources: [app/src/debug/jni]
JNI libraries: [app/src/debug/jniLibs]
Java-style resources: [app/src/debug/resources]

यह आउटपुट देखने के लिए, यह तरीका अपनाएं:

  1. टूल विंडो बार में, Gradle पर क्लिक करें.
  2. MyApplication > Tasks > android पर जाएं और sourceSets पर दो बार क्लिक करें.

    Tasks फ़ोल्डर देखने के लिए, आपको सिंक के दौरान Gradle को टास्क की सूची बनाने की अनुमति देनी होगी. ऐसा करने के लिए, यहां दिया गया तरीका अपनाएं:

    1. macOS पर, फ़ाइल > सेटिंग > एक्सपेरिमेंटल (Android Studio > सेटिंग > एक्सपेरिमेंटल) पर क्लिक करें.
    2. Gradle सिंक के दौरान, Gradle टास्क की सूची न बनाएं से चुने हुए का निशान हटाएं.
  3. Gradle के टास्क को पूरा करने के बाद, रन विंडो खुलती है, ताकि आउटपुट दिखाया जा सके.

ध्यान दें: टास्क के आउटपुट में, उन फ़ाइलों के लिए सोर्स सेट व्यवस्थित करने का तरीका भी दिखता है जिनका इस्तेमाल आपको अपने ऐप्लिकेशन की जांच करने के लिए करना है. जैसे, test/ और androidTest/ टेस्टिंग सोर्स सेट.

नया बिल्ड वैरिएंट बनाने पर, Android Studio आपके लिए सोर्स सेट डायरेक्ट्री नहीं बनाता. हालांकि, यह आपकी मदद के लिए कुछ विकल्प देता है. उदाहरण के लिए, अपने "डबग" बिल्ड टाइप के लिए सिर्फ़ java/ डायरेक्ट्री बनाने के लिए:

  1. प्रोजेक्ट पैनल खोलें और पैनल के सबसे ऊपर मौजूद मेन्यू से, प्रोजेक्ट व्यू चुनें.
  2. MyProject/app/src/ पर जाएं.
  3. src डायरेक्ट्री पर राइट क्लिक करें और नया > डायरेक्ट्री चुनें.
  4. Gradle सोर्स सेट में मौजूद मेन्यू से, full/java चुनें.
  5. Enter दबाएं.

Android Studio, डीबग बिल्ड टाइप के लिए सोर्स सेट डायरेक्ट्री बनाता है और फिर उसके अंदर java/ डायरेक्ट्री बनाता है. इसके अलावा, किसी खास बिल्ड वैरिएंट के लिए अपने प्रोजेक्ट में नई फ़ाइल जोड़ने पर, Android Studio आपके लिए डायरेक्ट्री बना सकता है.

उदाहरण के लिए, अपने "डीबग" बिल्ड टाइप के लिए वैल्यू एक्सएमएल फ़ाइल बनाने के लिए:

  1. प्रोजेक्ट पैनल में, src डायरेक्ट्री पर दायां क्लिक करें और नया > एक्सएमएल > वैल्यू एक्सएमएल फ़ाइल चुनें.
  2. एक्सएमएल फ़ाइल का नाम डालें या डिफ़ॉल्ट नाम ही रखें.
  3. टारगेट सोर्स सेट के बगल में मौजूद मेन्यू से, डीबग करें को चुनें.
  4. पूरा करें पर क्लिक करें.

"डीबग" बिल्ड टाइप को टारगेट सोर्स सेट के तौर पर बताया गया था. इसलिए, एक्सएमएल फ़ाइल बनाने पर, Android Studio अपने-आप ज़रूरी डायरेक्ट्री बना देता है. इससे बनने वाला डायरेक्ट्री स्ट्रक्चर, पहली इमेज में दिखाए गए स्ट्रक्चर जैसा दिखता है.

पहली इमेज. "डीबग" टाइप के बिल्ड के लिए, नया सोर्स सेट डायरेक्ट्री.

चालू सोर्स सेट के आइकॉन में हरे रंग का इंडिकेटर होता है, ताकि यह पता चल सके कि वे चालू हैं. debug के सोर्स सेट को [main] के साथ सफ़िक्स को जोड़ा गया है, ताकि यह दिखाया जा सके कि इसे main के सोर्स सेट में मर्ज कर दिया जाएगा.

इसी प्रोसेस का इस्तेमाल करके, src/demo/ जैसे प्रॉडक्ट फ़्लेवर के लिए सोर्स सेट डायरेक्ट्री भी बनाई जा सकती हैं. साथ ही, src/demoDebug/ जैसे वैरिएंट भी बनाए जा सकते हैं. इसके अलावा, टेस्टिंग सोर्स के ऐसे सेट बनाए जा सकते हैं जो खास बिल्ड वैरिएंट को टारगेट करते हैं, जैसे कि src/androidTestDemoDebug/. ज़्यादा जानने के लिए, सोर्स सेट की जांच करने के बारे में पढ़ें.

सोर्स सेट के डिफ़ॉल्ट कॉन्फ़िगरेशन बदलना

अगर आपके पास ऐसे सोर्स हैं जिन्हें डिफ़ॉल्ट सोर्स सेट फ़ाइल के स्ट्रक्चर में व्यवस्थित नहीं किया गया है, जैसा कि सोर्स सेट बनाने के बारे में पिछले सेक्शन में बताया गया है, तो sourceSets ब्लॉक का इस्तेमाल करके, यह बदला जा सकता है कि Gradle, सोर्स सेट के हर कॉम्पोनेंट के लिए फ़ाइलें कहां से इकट्ठा करे.

sourceSets ब्लॉक, android ब्लॉक में होना चाहिए. आपको सोर्स फ़ाइलों को कहीं और ले जाने की ज़रूरत नहीं है. आपको सिर्फ़ Gradle को मॉड्यूल-लेवल build.gradle.kts फ़ाइल के हिसाब से पाथ देना होगा, जहां Gradle हर सोर्स सेट कॉम्पोनेंट के लिए फ़ाइलें ढूंढ सकता है. यह जानने के लिए कि किन कॉम्पोनेंट को कॉन्फ़िगर किया जा सकता है और क्या उन्हें एक से ज़्यादा फ़ाइलों या डायरेक्ट्री पर मैप किया जा सकता है, Android Gradle प्लगिन एपीआई रेफ़रंस देखें.

नीचे दिया गया कोड सैंपल, app/other/ डायरेक्ट्री से सोर्स को main सोर्स सेट के कुछ कॉम्पोनेंट पर मैप करता है और androidTest सोर्स सेट की रूट डायरेक्ट्री को बदलता है:

Kotlin

android {
  ...
  // Encapsulates configurations for the main source set.
  sourceSets.getByName("main") {
    // Changes the directory for Java sources. The default directory is
    // 'src/main/java'.
    java.setSrcDirs(listOf("other/java"))

    // If you list multiple directories, Gradle uses all of them to collect
    // sources. Because Gradle gives these directories equal priority, if
    // you define the same resource in more than one directory, you receive an
    // error when merging resources. The default directory is 'src/main/res'.
    res.setSrcDirs(listOf("other/res1", "other/res2"))

    // Note: Avoid specifying a directory that is a parent to one
    // or more other directories you specify. For example, avoid the following:
    // res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings']
    // Specify either only the root 'other/res1' directory or only the
    // nested 'other/res1/layouts' and 'other/res1/strings' directories.

    // For each source set, you can specify only one Android manifest.
    // By default, Android Studio creates a manifest for your main source
    // set in the src/main/ directory.
    manifest.srcFile("other/AndroidManifest.xml")
    ...
  }

  // Create additional blocks to configure other source sets.
  sourceSets.getByName("androidTest") {
      // If all the files for a source set are located under a single root
      // directory, you can specify that directory using the setRoot property.
      // When gathering sources for the source set, Gradle looks only in locations
      // relative to the root directory you specify. For example, after applying the
      // configuration below for the androidTest source set, Gradle looks for Java
      // sources only in the src/tests/java/ directory.
      setRoot("src/tests")
      ...
  }
}
...

Groovy

android {
  ...
  sourceSets {
    // Encapsulates configurations for the main source set.
    main {
      // Changes the directory for Java sources. The default directory is
      // 'src/main/java'.
      java.srcDirs = ['other/java']

      // If you list multiple directories, Gradle uses all of them to collect
      // sources. Because Gradle gives these directories equal priority, if
      // you define the same resource in more than one directory, you receive an
      // error when merging resources. The default directory is 'src/main/res'.
      res.srcDirs = ['other/res1', 'other/res2']

      // Note: Avoid specifying a directory that is a parent to one
      // or more other directories you specify. For example, avoid the following:
      // res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings']
      // Specify either only the root 'other/res1' directory or only the
      // nested 'other/res1/layouts' and 'other/res1/strings' directories.

      // For each source set, you can specify only one Android manifest.
      // By default, Android Studio creates a manifest for your main source
      // set in the src/main/ directory.
      manifest.srcFile 'other/AndroidManifest.xml'
      ...
    }

    // Create additional blocks to configure other source sets.
    androidTest {

      // If all the files for a source set are located under a single root
      // directory, you can specify that directory using the setRoot property.
      // When gathering sources for the source set, Gradle looks only in locations
      // relative to the root directory you specify. For example, after applying the
      // configuration below for the androidTest source set, Gradle looks for Java
      // sources only in the src/tests/java/ directory.
      setRoot 'src/tests'
      ...
    }
  }
}
...

ध्यान दें कि सोर्स डायरेक्ट्री सिर्फ़ एक सोर्स सेट से जुड़ी हो सकती है. उदाहरण के लिए, test और androidTest, दोनों सोर्स सेट के साथ जांच के एक ही सोर्स को शेयर नहीं किया जा सकता. ऐसा इसलिए होता है, क्योंकि Android Studio हर सोर्स सेट के लिए अलग-अलग IntelliJ मॉड्यूल बनाता है. साथ ही, यह सोर्स सेट में डुप्लीकेट कॉन्टेंट रूट के साथ काम नहीं कर सकता.

सोर्स सेट की मदद से बनाएं

सोर्स सेट डायरेक्ट्री का इस्तेमाल करके, ऐसे कोड और संसाधन शामिल किए जा सकते हैं जिन्हें आपको सिर्फ़ कुछ कॉन्फ़िगरेशन के साथ पैकेज करना है. उदाहरण के लिए, अगर "demoDebug" बिल्ड वैरिएंट बनाया जा रहा है, जो "demo" प्रॉडक्ट फ़्लेवर और "debug" बिल्ड टाइप का क्रॉसप्रॉडक्ट है, तो Gradle इन डायरेक्ट्री को देखता है और उन्हें यह प्राथमिकता देता है:

  1. src/demoDebug/ (बिल्ड वैरिएंट का सोर्स सेट)
  2. src/debug/ (बिल्ड टाइप सोर्स सेट)
  3. src/demo/ (प्रॉडक्ट फ़्लेवर का सोर्स सेट)
  4. src/main/ (मुख्य सोर्स सेट)

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

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

प्राथमिकता के क्रम से यह तय होता है कि Gradle कोड और संसाधनों को जोड़ते समय, किस सोर्स सेट को ज़्यादा प्राथमिकता देगा. demoDebug/ सोर्स सेट डायरेक्ट्री में, उस बिल्ड वैरिएंट के हिसाब से फ़ाइलें होती हैं. अगर demoDebug/ में ऐसी फ़ाइल शामिल है जो debug/ में भी मौजूद है, तो Gradle demoDebug/ सोर्स सेट में मौजूद फ़ाइल का इस्तेमाल करता है. इसी तरह, Gradle, बिल्ड टाइप में फ़ाइलें देता है और प्रॉडक्ट के फ़्लेवर के लिए, main/ में मौजूद फ़ाइलों के मुकाबले, सोर्स को ज़्यादा प्राथमिकता दी जाती है. बिल्ड के इन नियमों को लागू करते समय, Gradle इस प्राथमिकता क्रम का इस्तेमाल करता है:

  • एक आउटपुट जनरेट करने के लिए, kotlin/ या java/ डायरेक्ट्री में मौजूद सभी सोर्स कोड को एक साथ इकट्ठा किया जाता है.

    ध्यान दें: किसी दिए गए बिल्ड वैरिएंट के लिए, Gradle एक गड़बड़ी दिखाता है. ऐसा तब होता है, जब उसे दो या उससे ज़्यादा सोर्स सेट डायरेक्ट्री मिलती हैं जिनमें एक ही Kotlin या Java क्लास तय की गई है. उदाहरण के लिए, डीबग ऐप्लिकेशन बनाते समय, src/debug/Utility.kt और src/main/Utility.kt, दोनों को तय नहीं किया जा सकता. ऐसा इसलिए, क्योंकि Gradle, बिल्ड प्रोसेस के दौरान इन दोनों डायरेक्ट्री को देखता है और "डुप्लीकेट क्लास" वाली गड़बड़ी दिखाता है. अगर आपको अलग-अलग तरह के बिल्ड के लिए, Utility.kt के अलग-अलग वर्शन चाहिए, तो हर बिल्ड टाइप के लिए फ़ाइल का अपना वर्शन तय करना होगा. साथ ही, उसे main/ सोर्स सेट में शामिल नहीं करना होगा.

  • मेनिफ़ेस्ट को एक साथ मिलाकर एक मेनिफ़ेस्ट बनाया जाता है. प्राथमिकता, पिछले उदाहरण में दी गई सूची के क्रम में दी जाती है. इसका मतलब है कि किसी बिल्ड टाइप के लिए मेनिफ़ेस्ट की सेटिंग, प्रॉडक्ट फ़्लेवर के लिए मेनिफ़ेस्ट की सेटिंग को बदल देती हैं. ज़्यादा जानने के लिए, मेनिफ़ेस्ट को मर्ज करने के बारे में पढ़ें.
  • values/ डायरेक्ट्री में मौजूद फ़ाइलों को एक साथ मर्ज कर दिया जाता है. अगर दो फ़ाइलों के नाम एक जैसे हैं, जैसे कि strings.xml की दो फ़ाइलें, तो प्राथमिकता उसी क्रम में दी जाएगी जिस क्रम में पिछले उदाहरण में सूची दी गई है. इसका मतलब है कि बिल्ड टाइप सोर्स सेट में मौजूद किसी फ़ाइल में तय की गई वैल्यू, प्रॉडक्ट फ़्लेवर में मौजूद उसी फ़ाइल में तय की गई वैल्यू को बदल देती हैं.
  • res/ और asset/ डायरेक्ट्री में मौजूद संसाधनों को एक साथ पैकेज किया जाता है. अगर दो या उससे ज़्यादा सोर्स सेट में एक ही नाम वाले संसाधन हैं, तो प्राथमिकता उसी क्रम में दी जाती है जिस क्रम में पिछले उदाहरण में सूची दी गई है.
  • ऐप्लिकेशन बनाते समय, Gradle लाइब्रेरी के मॉड्यूल डिपेंडेंसी के साथ शामिल किए गए संसाधनों और मेनिफ़ेस्ट को सबसे कम प्राथमिकता देता है.

डिपेंडेंसी का एलान करना

किसी खास बिल्ड वैरिएंट या टेस्टिंग सोर्स सेट के लिए डिपेंडेंसी कॉन्फ़िगर करने के लिए, Implementation कीवर्ड से पहले बिल्ड वैरिएंट या टेस्टिंग सोर्स सेट का नाम जोड़ें, जैसा कि इस उदाहरण में दिखाया गया है:

Kotlin

dependencies {
    // Adds the local "mylibrary" module as a dependency to the "free" flavor.
    "freeImplementation"(project(":mylibrary"))

    // Adds a remote binary dependency only for local tests.
    testImplementation("junit:junit:4.12")

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation("com.android.support.test.espresso:espresso-core:3.6.1")
}

Groovy

dependencies {
    // Adds the local "mylibrary" module as a dependency to the "free" flavor.
    freeImplementation project(":mylibrary")

    // Adds a remote binary dependency only for local tests.
    testImplementation 'junit:junit:4.12'

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.6.1'
}

डिपेंडेंसी कॉन्फ़िगर करने के बारे में ज़्यादा जानने के लिए, बिल्ड डिपेंडेंसी जोड़ना लेख पढ़ें.

वैरिएंट के हिसाब से डिपेंडेंसी मैनेजमेंट का इस्तेमाल करना

Android Gradle प्लग इन 3.0.0 और इसके बाद के वर्शन में, डिपेंडेंसी का एक नया तरीका शामिल है. यह लाइब्रेरी का इस्तेमाल करते समय, वैरिएंट से अपने-आप मैच हो जाता है. इसका मतलब है कि ऐप्लिकेशन का debug वैरिएंट, लाइब्रेरी के debug वैरिएंट का इस्तेमाल अपने-आप करता है. यह फ़्लेवर का इस्तेमाल करने पर भी काम करता है: ऐप्लिकेशन का freeDebug वैरिएंट, लाइब्रेरी के freeDebug वैरिएंट का इस्तेमाल करेगा.

प्लग इन वैरिएंट को सही तरीके से मैच कर सके, इसके लिए आपको नीचे दिए गए सेक्शन में बताए गए मिलते-जुलते फ़ॉलबैक देने होंगे. ऐसा उन मामलों में होगा जहां सीधे तौर पर मैच नहीं किया जा सकता.

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

Error:Failed to resolve: Could not resolve project :mylibrary.
Required by:
    project :app

वैरिएंट मैचिंग से जुड़ी बिल्ड गड़बड़ियां हल करना

इस प्लग इन में डीएसएल एलिमेंट शामिल हैं. इनकी मदद से, यह कंट्रोल किया जा सकता है कि Gradle उन स्थितियों को कैसे हल करता है जिनमें किसी ऐप्लिकेशन और डिपेंडेंसी के बीच सीधे वैरिएंट मैच नहीं हो पाता.

वैरिएंट-अवेयर डिपेंडेंसी मैचिंग से जुड़ी समस्याओं की सूची यहां दी गई है. साथ ही, यह भी बताया गया है कि डीएसएल प्रॉपर्टी का इस्तेमाल करके, उन्हें कैसे हल किया जा सकता है:

  • आपके ऐप्लिकेशन में ऐसा बिल्ड टाइप शामिल है जो लाइब्रेरी डिपेंडेंसी में नहीं है.

    उदाहरण के लिए, आपके ऐप्लिकेशन में "स्टेजिंग" बिल्ड टाइप शामिल है, लेकिन डिपेंडेंसी में सिर्फ़ "डीबग" और "रिलीज़" वाले बिल्ड टाइप ही शामिल हैं.

    ध्यान दें कि अगर लाइब्रेरी डिपेंडेंसी में ऐसा बिल्ड टाइप शामिल है जो आपके ऐप्लिकेशन में नहीं है, तो कोई समस्या नहीं होती. ऐसा इसलिए होता है, क्योंकि प्लग इन कभी भी डिपेंडेंसी से उस तरह का बिल्ड टाइप का अनुरोध नहीं करता.

    किसी खास बिल्ड टाइप के लिए वैकल्पिक मैच बताने के लिए, matchingFallbacks का इस्तेमाल करें, जैसा कि यहां दिखाया गया है:

    Kotlin

    // In the app's build.gradle.kts file.
    android {
        buildTypes {
            getByName("debug") {}
            getByName("release") {}
            create("staging") {
                // Specifies a sorted list of fallback build types that the
                // plugin can try to use when a dependency does not include a
                // "staging" build type. You may specify as many fallbacks as you
                // like, and the plugin selects the first build type that's
                // available in the dependency.
                matchingFallbacks += listOf("debug", "qa", "release")
            }
        }
    }

    Groovy

    // In the app's build.gradle file.
    android {
        buildTypes {
            debug {}
            release {}
            staging {
                // Specifies a sorted list of fallback build types that the
                // plugin can try to use when a dependency does not include a
                // "staging" build type. You may specify as many fallbacks as you
                // like, and the plugin selects the first build type that's
                // available in the dependency.
                matchingFallbacks = ['debug', 'qa', 'release']
            }
        }
    }
    
  • ऐप्लिकेशन और उसकी लाइब्रेरी डिपेंडेंसी, दोनों में मौजूद किसी फ़्लेवर डाइमेंशन के लिए, आपके ऐप्लिकेशन में ऐसे फ़्लेवर शामिल हैं जो लाइब्रेरी में नहीं हैं.

    उदाहरण के लिए, आपके ऐप्लिकेशन और उसकी लाइब्रेरी डिपेंडेंसी, दोनों में "टीयर" फ़्लेवर डाइमेंशन शामिल होता है. हालांकि, ऐप्लिकेशन के "टीयर" डाइमेंशन में "बिना शुल्क वाला" और "पैसे चुकाकर मिलने वाला" वर्शन शामिल होता है. हालांकि, किसी डिपेंडेंसी में एक ही डाइमेंशन के लिए सिर्फ़ "डेमो" और "पैसे चुकाकर मिलने वाला" वर्शन शामिल होता है.

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

    ऐप्लिकेशन के "मुफ़्त" प्रॉडक्ट फ़्लेवर के लिए, मिलते-जुलते विकल्प बताने के लिए matchingFallbacks का इस्तेमाल करें, जैसा कि यहां दिखाया गया है:

    Kotlin

    // In the app's build.gradle.kts file.
    android {
        defaultConfig{
        // Don't configure matchingFallbacks in the defaultConfig block.
        // Instead, specify fallbacks for a given product flavor in the
        // productFlavors block, as shown below.
      }
        flavorDimensions += "tier"
        productFlavors {
            create("paid") {
                dimension = "tier"
                // Because the dependency already includes a "paid" flavor in its
                // "tier" dimension, you don't need to provide a list of fallbacks
                // for the "paid" flavor.
            }
            create("free") {
                dimension = "tier"
                // Specifies a sorted list of fallback flavors that the plugin
                // can try to use when a dependency's matching dimension does
                // not include a "free" flavor. Specify as many
                // fallbacks as you like; the plugin selects the first flavor
                // that's available in the dependency's "tier" dimension.
                matchingFallbacks += listOf("demo", "trial")
            }
        }
    }
    

    Groovy

    // In the app's build.gradle file.
    android {
        defaultConfig{
        // Don't configure matchingFallbacks in the defaultConfig block.
        // Instead, specify fallbacks for a given product flavor in the
        // productFlavors block, as shown below.
      }
        flavorDimensions 'tier'
        productFlavors {
            paid {
                dimension 'tier'
                // Because the dependency already includes a "paid" flavor in its
                // "tier" dimension, you don't need to provide a list of fallbacks
                // for the "paid" flavor.
            }
            free {
                dimension 'tier'
                // Specifies a sorted list of fallback flavors that the plugin
                // can try to use when a dependency's matching dimension does
                // not include a "free" flavor. Specify as many
                // fallbacks as you like; the plugin selects the first flavor
                // that's available in the dependency's "tier" dimension.
                matchingFallbacks = ['demo', 'trial']
            }
        }
    }
    
  • लाइब्रेरी डिपेंडेंसी में ऐसा फ़्लेवर डाइमेंशन शामिल है जो आपके ऐप्लिकेशन में नहीं है.

    उदाहरण के लिए, किसी लाइब्रेरी डिपेंडेंसी में "minApi" डाइमेंशन के लिए फ़्लेवर शामिल होते हैं, लेकिन आपके ऐप्लिकेशन में सिर्फ़ "टीयर" डाइमेंशन के लिए फ़्लेवर शामिल होते हैं. जब आपको अपने ऐप्लिकेशन का "freeDebug" वर्शन बनाना हो, तो प्लग इन को यह पता नहीं चलता कि डिपेंडेंसी के "minApi23Debug" या "minApi18Debug" वर्शन में से किसका इस्तेमाल करना है.

    ध्यान दें कि अगर आपके ऐप्लिकेशन में कोई ऐसा फ़्लेवर डाइमेंशन शामिल है जो लाइब्रेरी डिपेंडेंसी में शामिल नहीं है, तो कोई समस्या नहीं होती. इसकी वजह यह है कि प्लगिन सिर्फ़ उन डाइमेंशन के फ़्लेवर से मैच करता है जो डिपेंडेंसी में मौजूद होते हैं. उदाहरण के लिए, अगर किसी डिपेंडेंसी में एबीआई के लिए डाइमेंशन शामिल नहीं है, तो आपके ऐप्लिकेशन का "freeX86Debug" वर्शन, डिपेंडेंसी के "freeडीबग" वर्शन का इस्तेमाल करेगा.

    defaultConfig ब्लॉक में missingDimensionStrategy का इस्तेमाल करके, प्लग इन के लिए डिफ़ॉल्ट फ़्लेवर तय करें, ताकि वह हर उस डाइमेंशन को चुन सके जो मौजूद नहीं है. इस बारे में, यहां दिए गए सैंपल में बताया गया है. productFlavors ब्लॉक में, अपने चुने गए विकल्पों को बदला भी जा सकता है, ताकि हर फ़्लेवर, मौजूद न होने वाले डाइमेंशन के लिए मैच करने की अलग रणनीति तय कर सके.

    Kotlin

    // In the app's build.gradle.kts file.
    android {
        defaultConfig{
        // Specifies a sorted list of flavors that the plugin can try to use from
        // a given dimension. This tells the plugin to select the "minApi18" flavor
        // when encountering a dependency that includes a "minApi" dimension.
        // You can include additional flavor names to provide a
        // sorted list of fallbacks for the dimension.
        missingDimensionStrategy("minApi", "minApi18", "minApi23")
        // Specify a missingDimensionStrategy property for each
        // dimension that exists in a local dependency but not in your app.
        missingDimensionStrategy("abi", "x86", "arm64")
        }
        flavorDimensions += "tier"
        productFlavors {
            create("free") {
                dimension = "tier"
                // You can override the default selection at the product flavor
                // level by configuring another missingDimensionStrategy property
                // for the "minApi" dimension.
                missingDimensionStrategy("minApi", "minApi23", "minApi18")
            }
            create("paid") {}
        }
    }
    

    ग्रूवी

    // In the app's build.gradle file.
    android {
        defaultConfig{
        // Specifies a sorted list of flavors that the plugin can try to use from
        // a given dimension. This tells the plugin to select the "minApi18" flavor
        // when encountering a dependency that includes a "minApi" dimension.
        // You can include additional flavor names to provide a
        // sorted list of fallbacks for the dimension.
        missingDimensionStrategy 'minApi', 'minApi18', 'minApi23'
        // Specify a missingDimensionStrategy property for each
        // dimension that exists in a local dependency but not in your app.
        missingDimensionStrategy 'abi', 'x86', 'arm64'
        }
        flavorDimensions 'tier'
        productFlavors {
            free {
                dimension 'tier'
                // You can override the default selection at the product flavor
                // level by configuring another missingDimensionStrategy property
                // for the 'minApi' dimension.
                missingDimensionStrategy 'minApi', 'minApi23', 'minApi18'
            }
            paid {}
        }
    }
    

ज़्यादा जानकारी के लिए, 'Android Gradle प्लग इन' डीएसएल रेफ़रंस में, matchingFallbacks और missingDimensionStrategy देखें.

साइनिंग सेटिंग कॉन्फ़िगर करें

Gradle, रिलीज़ बंडल के APK या AAB को तब तक साइन नहीं करता, जब तक कि आपने इस बंडल के लिए साइन करने का कॉन्फ़िगरेशन साफ़ तौर पर तय न कर दिया हो. अगर आपके पास अब तक साइनिंग पासकोड नहीं है, तो Android Studio का इस्तेमाल करके अपलोड पासकोड और पासकोड स्टोर जनरेट करें.

Gradle बिल्ड कॉन्फ़िगरेशन का इस्तेमाल करके, अपनी रिलीज़ के बिल्ड टाइप के लिए साइनिंग कॉन्फ़िगरेशन को मैन्युअल तरीके से कॉन्फ़िगर करने के लिए:

  1. कीस्टोर बनाएं. कीस्टोर एक बाइनरी फ़ाइल होती है, जिसमें निजी कुंजियों का एक सेट होता है. आपको अपने कीस्टोर को किसी सुरक्षित जगह पर रखना चाहिए.
  2. निजी कुंजी बनाएं. निजी कुंजी का इस्तेमाल, आपके ऐप्लिकेशन को डिस्ट्रिब्यूशन के लिए साइन करने के लिए किया जाता है. इसे कभी भी ऐप्लिकेशन में शामिल नहीं किया जाता या बिना अनुमति वाले तीसरे पक्षों के साथ शेयर नहीं किया जाता.
  3. मॉड्यूल-लेवल की build.gradle.kts फ़ाइल में, हस्ताक्षर करने का कॉन्फ़िगरेशन जोड़ें:

    Kotlin

    ...
    android {
        ...
        defaultConfig {...}
        signingConfigs {
            create("release") {
                storeFile = file("myreleasekey.keystore")
                storePassword = "password"
                keyAlias = "MyReleaseKey"
                keyPassword = "password"
            }
        }
        buildTypes {
            getByName("release") {
                ...
                signingConfig = signingConfigs.getByName("release")
            }
        }
    }

    ग्रूवी

    ...
    android {
        ...
        defaultConfig {...}
        signingConfigs {
            release {
                storeFile file("myreleasekey.keystore")
                storePassword "password"
                keyAlias "MyReleaseKey"
                keyPassword "password"
            }
        }
        buildTypes {
            release {
                ...
                signingConfig signingConfigs.release
            }
        }
    }

ध्यान दें: बिल्ड फ़ाइल में अपनी रिलीज़ कुंजी और कीस्टोर के पासवर्ड शामिल करना, सुरक्षा का अच्छा तरीका नहीं है. इसके बजाय, इन पासवर्ड को एनवायरमेंट वैरिएबल से पासवर्ड पाने के लिए बिल्ड फ़ाइल को कॉन्फ़िगर करें या इन पासवर्ड के लिए बिल्ड प्रोसेस से अनुरोध पाएं.

एनवायरमेंट वैरिएबल से ये पासवर्ड पाने के लिए:

Kotlin

storePassword = System.getenv("KSTOREPWD")
keyPassword = System.getenv("KEYPWD")

Groovy

storePassword System.getenv("KSTOREPWD")
keyPassword System.getenv("KEYPWD")

इसके अलावा, किसी स्थानीय प्रॉपर्टी फ़ाइल से भी पासकोड लोड किया जा सकता है. सुरक्षा से जुड़ी वजहों से, इस फ़ाइल को सोर्स कंट्रोल में न जोड़ें. इसके बजाय, इसे हर डेवलपर के लिए स्थानीय तौर पर सेट अप करें. ज़्यादा जानने के लिए, अपनी बिल्ड फ़ाइलों से हस्ताक्षर करने की जानकारी हटाना लेख पढ़ें.

इस प्रोसेस को पूरा करने के बाद, ऐप्लिकेशन को डिस्ट्रिब्यूट और Google Play पर पब्लिश किया जा सकता है.

चेतावनी: अपने कीस्टोर और निजी कुंजी को किसी सुरक्षित जगह पर रखें और पक्का करें कि आपके पास उनका सुरक्षित बैकअप हो. अगर Play ऐप्लिकेशन साइनिंग का इस्तेमाल किया जा रहा है और आपका अपलोड पासकोड खो जाता है, तो Play Console का इस्तेमाल करके रीसेट करने का अनुरोध किया जा सकता है. अगर अगस्त 2021 से पहले बनाए गए ऐप्लिकेशन को 'Play ऐप्लिकेशन साइनिंग' के बिना पब्लिश किया जा रहा है और आपका ऐप्लिकेशन साइनिंग पासकोड खो जाता है, तो आपके पास अपने ऐप्लिकेशन के लिए कोई अपडेट पब्लिश करने का विकल्प नहीं होगा. ऐसा इसलिए, क्योंकि ऐप्लिकेशन के सभी वर्शन को एक ही पासकोड से साइन करना ज़रूरी है.

Wear OS ऐप्लिकेशन को हस्ताक्षर करना

Wear OS ऐप्लिकेशन पब्लिश करते समय, स्मार्टवॉच के APK और फ़ोन के APK, दोनों पर एक ही कुंजी से हस्ताक्षर किए जाने चाहिए. हालांकि, फ़ोन के लिए APK बनाना ज़रूरी नहीं है. Wear OS ऐप्लिकेशन को पैकेज करने और उन पर हस्ताक्षर करने के बारे में ज़्यादा जानने के लिए, Wear ऐप्लिकेशन को पैकेज करना और उन्हें उपलब्ध कराना लेख पढ़ें.