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

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

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

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

उदाहरण के लिए, "डेमो" ऐप्लिकेशन टाइप में कुछ सुविधाओं और डिवाइस से जुड़ी ज़रूरी शर्तों के बारे में बताया जा सकता है. जैसे, कस्टम सोर्स कोड, संसाधन, और कम से कम एपीआई लेवल. वहीं, "डीबग" बिल्ड टाइप में, बिल्ड और पैकेजिंग की अलग-अलग सेटिंग लागू होती हैं. जैसे, डीबग करने के विकल्प और साइनिंग पासकोड. इन दोनों को मिलाकर बनने वाला बिल्ड वैरिएंट, आपके ऐप्लिकेशन का "demoDebug" वर्शन होता है. इसमें "डेमो" ऐप्लिकेशन टाइप, "डीबग" बिल्ड टाइप, और 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 प्लग इन, मॉड्यूल के सभी फ़्लेवर को उस डाइमेंशन में अपने-आप असाइन कर देता है.

यहां दिए गए कोड सैंपल से, "version" नाम का एक फ़्लेवर डाइमेंशन बनता है. साथ ही, "demo" और "full" ऐप्लिकेशन टाइप जुड़ते हैं. इन फ़्लेवर में, खुद के 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 पर एक से ज़्यादा APK के साथ काम करने की सुविधा का इस्तेमाल करके, अपने ऐप्लिकेशन को उपलब्ध कराने के लिए, सभी वैरिएंट को एक ही applicationId वैल्यू असाइन करें. साथ ही, हर वैरिएंट को अलग-अलग versionCode दें. Google Play पर अपने ऐप्लिकेशन के अलग-अलग वैरिएंट को अलग-अलग ऐप्लिकेशन के तौर पर उपलब्ध कराने के लिए, आपको हर वैरिएंट को एक अलग applicationId असाइन करना होगा.

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

  • demoDebug
  • demoRelease
  • fullDebug
  • fullRelease

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

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

जब अपने ऐप्लिकेशन के लिए APK या एएबी बनाया जाता है, तो बिल्ड टूल, ऐप्लिकेशन को ऐप्लिकेशन आईडी के साथ टैग करते हैं. यह आईडी, 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, ऐप्लिकेशन टाइप के बाद बिल्ड टाइप कॉन्फ़िगरेशन लागू करता है. इसलिए, "free debug" बिल्ड वैरिएंट के लिए ऐप्लिकेशन आईडी, "com.example.myapp.free.debug" है. यह तब काम आता है, जब आपको एक ही डिवाइस पर डीबग और रिलीज़ के लिए तैयार बिल्ड, दोनों को रखना हो. ऐसा इसलिए, क्योंकि दो ऐप्लिकेशन का ऐप्लिकेशन आईडी एक जैसा नहीं हो सकता.

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

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

फ़्लेवर डाइमेंशन की मदद से, एक से ज़्यादा ऐप्लिकेशन टाइप को जोड़ना

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

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

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

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"
      ...
    }
  }
}
...

Groovy

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 और इसके बाद के वर्शन के साथ काम करने की सुविधा देनी है. variantFilter ब्लॉक का इस्तेमाल करके, बिल्ड के वैरिएंट के उन सभी कॉन्फ़िगरेशन को फ़िल्टर किया जा सकता है जिनमें "minApi21" और "demo" ऐप्लिकेशन टाइप को जोड़ा गया है:

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/ source set में बुनियादी फ़ंक्शन तय किए जा सकते हैं. साथ ही, अलग-अलग क्लाइंट के लिए अपने ऐप्लिकेशन की ब्रैंडिंग बदलने के लिए, ऐप्लिकेशन टाइप के source set का इस्तेमाल किया जा सकता है. इसके अलावा, सिर्फ़ उन बिल्ड का वैरिएंट के लिए खास अनुमतियां और लॉगिंग फ़ंक्शन शामिल किए जा सकते हैं जो डीबग के लिए बिल्ड का तरीका का इस्तेमाल करते हैं.

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 पर दो बार क्लिक करें.

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

    1. File > Settings > Experimental पर क्लिक करें (macOS पर, Android Studio > Settings > Experimental पर क्लिक करें).
    2. Gradle सिंक के दौरान Gradle टास्क की सूची न बनाएं से चुने हुए का निशान हटाएं.
  3. Gradle के टास्क पूरा करने के बाद, आउटपुट दिखाने के लिए Run विंडो खुलती है.

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

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

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

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

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

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

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

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

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

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

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

अगर आपके पास ऐसे सोर्स हैं जो Gradle के मुताबिक, डिफ़ॉल्ट सोर्स सेट फ़ाइल स्ट्रक्चर में व्यवस्थित नहीं हैं, तो 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" बिल्ड का वैरिएंट बनाया जा रहा है, जो "डेमो" ऐप्लिकेशन टाइप और "डीबग" बिल्ड का तरीका का क्रॉस प्रॉडक्ट है, तो 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 को किसी बिल्ड के वैरिएंट के लिए, दो या इससे ज़्यादा ऐसी source set डायरेक्ट्री मिलती हैं जिनमें एक ही 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 को कंट्रोल किया जा सकता है. इससे 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" वर्शन, डिपेंडेंसी के "freeDebug" वर्शन का इस्तेमाल करेगा.

    missingDimensionStrategy का इस्तेमाल defaultConfig ब्लॉक में करें, ताकि प्लगिन के लिए डिफ़ॉल्ट फ़्लेवर तय किया जा सके. इससे हर उस डाइमेंशन को चुना जा सकेगा जो मौजूद नहीं है. इसके बारे में यहां दिए गए सैंपल में बताया गया है. 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") {}
        }
    }

    Groovy

    // 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")
            }
        }
    }

    Groovy

    ...
    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 का इस्तेमाल करके पासकोड को रीसेट करने का अनुरोध किया जा सकता है. अगर आपने Play ऐप्लिकेशन साइनिंग का इस्तेमाल किए बिना कोई ऐप्लिकेशन पब्लिश किया है (अगस्त 2021 से पहले बनाए गए ऐप्लिकेशन के लिए) और आपके ऐप्लिकेशन साइनिंग पासकोड खो जाता है, तो आपके ऐप्लिकेशन के लिए कोई भी अपडेट पब्लिश नहीं किया जा सकेगा. ऐसा इसलिए, क्योंकि आपको अपने ऐप्लिकेशन के सभी वर्शन को हमेशा एक ही पासकोड से साइन करना होगा.

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

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