Gradle प्लग इन लिखना

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

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

AGP API का लाइफ़साइकल

एजीपी अपने एपीआई की स्थिति तय करने के लिए, Gradle सुविधा के लाइफ़साइकल का पालन करता है:

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

बंद करने की नीति

AGP में बदलाव किए जा रहे हैं. इसके तहत, पुराने एपीआई और उनके एपीआई बंद किए जा रहे हैं को नए, स्टेबल एपीआई और नए डोमेन स्पेसिफ़िक लैंग्वेज (DSL) से बदला जा सकता है. इस बदलाव में, एजीपी के कई रिलीज़ शामिल होंगे. साथ ही, इसके बारे में ज़्यादा जाना जा सकता है AGP API/DSL माइग्रेशन टाइमलाइन पर जाएं.

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

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

Gradle बिल्ड की बुनियादी बातें

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

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

Gradle लेज़ी टाइप शब्दावली

Gradle, कई तरह की सुविधाएं देता है और ये "आलसी" व्यवहार करते हैं या भारी सामान को टालने में मदद करें कंप्यूटेशन या Task बाद के चरणों में किया जा सकता है. ये ऑडियंस सेगमेंट, Gradle और AGP API. इस सूची में, Gradle के मुख्य टाइप शामिल हैं लेज़ी एक्ज़ीक्यूशन और उनके मुख्य तरीकों में किया जा सकता है.

Provider<T>
T टाइप की वैल्यू देता है (जहां "T" का मतलब किसी भी टाइप से है) होता है, ताकि इसे पढ़ा जा सके यह प्रोसेस को लागू करने के लिए, get() या नए Provider<S> में बदल जाए (जहां "S" का मतलब किसी और तरह का है) map(), flatMap(), और zip()इन तरीकों का इस्तेमाल करके. ध्यान दें कि get() को यह करना चाहिए कॉन्फ़िगरेशन चरण के दौरान कभी भी कॉल नहीं किया जा सकता.
  • map(): lambda और S टाइप का Provider जनरेट करता है, Provider<S>. map() का लैम्डा आर्ग्युमेंट T मान लेता है और वैल्यू S. Lambda फ़ंक्शन को तुरंत एक्ज़ीक्यूट नहीं किया जाता है; इसके बजाय, इसका इस्तेमाल करके नतीजे के तौर पर मिलने वाले Provider<S> पर, get() को कॉल करने के समय टाल दिया जाता है, इससे पूरी चेन को लेज़ी बनाने में मदद मिलती है.
  • flatMap(): लैम्डा खाता भी स्वीकार करता है और Provider<S> बनाता है, लेकिन Lambda फ़ंक्शन T वैल्यू लेता है और Provider<S> जनरेट करता है, न कि वैल्यू S सीधे तौर पर). जब S पता तय नहीं किया जा सकता हो, तो चौड़ा मैप() इस्तेमाल करें कॉन्फ़िगरेशन समय पर सेट है और आप सिर्फ़ Provider<S> पा सकते हैं. व्यावहारिक रूप से हां, अगर आपने map() का इस्तेमाल किया और Provider<Provider<S>> पर विज़िट किया नतीजे का टाइप चुनें, तो इसका मतलब है कि आपको इसके बजाय flatMap() का इस्तेमाल करना चाहिए था.
  • zip(): इससे आपको दो Provider इंस्टेंस को मिलाकर, नया बनाने में मदद मिलती है Provider, इन सभी वैल्यू को जोड़ने वाले फ़ंक्शन का इस्तेमाल करके, इस वैल्यू की गणना की जाती है दो इनपुट Providers इंस्टेंस से.
Property<T>
Provider<T> को लागू करता है, इसलिए यह T टाइप की वैल्यू भी देता है. इससे नापसंद करें Provider<T>, जो सिर्फ़ पढ़ने के लिए है, आप इसके लिए मान भी सेट कर सकते हैं: Property<T>. ऐसा करने के दो तरीके हैं:
  • इसकी ज़रूरत के बिना, उपलब्ध होने पर ही T टाइप की वैल्यू सेट करें डिफ़र्ड कंप्यूटेशन वगैरह.
  • Property<T> की वैल्यू के सोर्स के तौर पर एक और Provider<T> सेट करें. तय सीमा में इस मामले में, T वैल्यू सिर्फ़ तब लागू होती है, जब Property.get() कॉल किया गया.
TaskProvider
Provider<Task> लागू करता है. TaskProvider जनरेट करने के लिए, इसका इस्तेमाल करें tasks.create() के बजाय tasks.register() का इस्तेमाल करें. इससे यह पक्का किया जा सकेगा कि टास्क सिर्फ़ इंस्टैंशिएट किए गए हैं ज़रूरत पड़ने पर बेफ़िक्र होकर. flatMap() का इस्तेमाल करके, Task बनाने से पहले, एक Task. इसका इस्तेमाल करना तब काम आ सकता है, जब आउटपुट को अन्य Task इंस्टेंस में इनपुट के तौर पर दिखाता है.

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

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

यहां दो टास्क को रजिस्टर करने का उदाहरण दिया गया है, GitVersionTask और ManifestProducerTask, Task इंस्टेंस बनाने की इस तारीख तक टाल दिया जाएगा उनकी ज़रूरत होती है. ManifestProducerTask की इनपुट वैल्यू को इस पर सेट किया गया है Provider को GitVersionTask के आउटपुट से लिया जाता है, इसलिए ManifestProducerTask निश्चित तौर पर GitVersionTask पर निर्भर है.

// Register a task lazily to get its TaskProvider.
val gitVersionProvider: TaskProvider =
    project.tasks.register("gitVersionProvider", GitVersionTask::class.java) {
        it.gitVersionOutputFile.set(
            File(project.buildDir, "intermediates/gitVersionProvider/output")
        )
    }

...

/**
 * Register another task in the configuration block (also executed lazily,
 * only if the task is required).
 */
val manifestProducer =
    project.tasks.register(variant.name + "ManifestProducer", ManifestProducerTask::class.java) {
        /**
         * Connect this task's input (gitInfoFile) to the output of
         * gitVersionProvider.
         */
        it.gitInfoFile.set(gitVersionProvider.flatMap(GitVersionTask::gitVersionOutputFile))
    }

ये दोनों टास्क सिर्फ़ तब लागू होंगे, जब इनके लिए साफ़ तौर पर अनुरोध किया गया हो. यह काम कर सकता है यह Gradle शुरू करने की प्रक्रिया में होता है. उदाहरण के लिए, अगर ./gradlew debugManifestProducer चलाया जाता है या ManifestProducerTask का आउटपुट कनेक्ट होता है किया जा सकता है और उसका मान आवश्यक हो जाता है.

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

Gradle बिल्ड फ़ेज़

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

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

कॉन्फ़िगरेशन का चरण

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

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

प्लान लागू करने का चरण

लागू किए जाने के चरण में, अनुरोध किए गए टास्क और उनसे जुड़े डिपेंडेंट टास्क हैं लागू किया गया. खास तौर पर, @TaskAction से मार्क किए गए क्लास के Task तरीके लागू किया गया. टास्क के चलने के दौरान, आपको इनपुट से (जैसे कि फ़ाइलें) डाउनलोड करें और Provider<T>.get() को कॉल करके लेज़ी प्रोवाइडर से संपर्क करें. आलसी की समस्या दूर करना इस तरह, सेवा देने वाली कंपनियों के साथ, फ़ॉलो किए जाने वाले map() या flatMap() कॉल का क्रम भी शुरू हो जाता है सेवा देने वाली कंपनी में मौजूद टास्क डिपेंडेंसी से जुड़ी जानकारी. टास्क चलाए जा रहे हैं ज़रूरी वैल्यू को पूरा करने के लिए धीरे-धीरे काम करें.

वैरिएंट एपीआई, आर्टफ़ैक्ट, और टास्क

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

Android बिल्ड फ़्लो और एक्सटेंशन पॉइंट

AGP के साथ इंटरैक्ट करते समय, खास तौर पर बनाए गए एक्सटेंशन पॉइंट का इस्तेमाल करें सामान्य Gradle लाइफ़साइकल कॉलबैक (जैसे कि afterEvaluate()) को रजिस्टर करने पर या साफ़ तौर पर Task डिपेंडेंसी सेट अप की जा रही है. एजीपी ने जो टास्क बनाए हैं उन्हें लागू करने से जुड़ी जानकारी दी जाती है. साथ ही, इन्हें सार्वजनिक एपीआई के तौर पर नहीं दिखाया जाता. आपको इनसे बचना चाहिए Task ऑब्जेक्ट के इंस्टेंस पाने या Task के नामों का अनुमान लगाने की कोशिश करना उन Task ऑब्जेक्ट में, सीधे कॉलबैक या डिपेंडेंसी जोड़ना.

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

  1. DSL पार्सिंग: यह तब होता है, जब बिल्ड स्क्रिप्ट का आकलन किया जाता है. साथ ही, android ब्लॉक से Android DSL ऑब्जेक्ट की अलग-अलग प्रॉपर्टी बनाई जाती हैं और सेट करें. नीचे दिए गए सेक्शन में बताए गए वैरिएंट API कॉलबैक भी इस दौरान रजिस्टर किया गया.
  2. finalizeDsl(): इस कॉलबैक की मदद से, डीएसएल ऑब्जेक्ट को उनके पहुंचने से पहले ही बदला जा सकता है कॉम्पोनेंट (वैरिएंट) बनाने के लिए लॉक किया गया है. VariantBuilder ऑब्जेक्ट बनाए गए जो DSL ऑब्जेक्ट में मौजूद डेटा के हिसाब से तय होती है.

  3. DSL लॉक करना: DSL अब लॉक हो गया है और इसमें अब बदलाव नहीं किए जा सकते.

  4. beforeVariants(): यह कॉलबैक इस बात पर असर डाल सकता है कि कौनसे कॉम्पोनेंट बनाए जाएं, और उनकी कुछ प्रॉपर्टी को VariantBuilder से अपलोड किया है. यह अब भी काम करेगा बनाने के तरीके और आर्टफ़ैक्ट के डेटा में बदलाव कर सकते हैं.

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

  6. onVariants(): इस कॉलबैक में, आपको बनाए गए Variant का ऐक्सेस मिलता है ऑब्जेक्ट हैं और आप Property मानों के लिए मान या कंपनी सेट कर सकते हैं जिसे लेज़ी तरीके से कैलकुलेट किया जाना है.

  7. वैरिएंट को लॉक करना: वैरिएंट ऑब्जेक्ट अब लॉक हो गए हैं और उनमें किए गए बदलाव भी अब लॉक हो गए हैं किया जा सकता है.

  8. बनाए गए टास्क: Variant ऑब्जेक्ट और उनकी Property वैल्यू का इस्तेमाल इन कामों के लिए किया जाता है बिल्ड करने के लिए ज़रूरी Task इंस्टेंस बनाएं.

AGP ने पेश किया AndroidComponentsExtension जो आप finalizeDsl(), beforeVariants(), और onVariants() के लिए कॉलबैक रजिस्टर करते हैं. यह एक्सटेंशन, androidComponents ब्लॉक के दौरान बिल्ड स्क्रिप्ट में उपलब्ध है:

// This is used only for configuring the Android build through DSL.
android { ... }

// The androidComponents block is separate from the DSL.
androidComponents {
   finalizeDsl { extension ->
      ...
   }
}

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

abstract class ExamplePlugin: Plugin<Project> {

    override fun apply(project: Project) {
        val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)
        androidComponents.finalizeDsl { extension ->
            ...
        }
    }
}

आइए, उपलब्ध कॉलबैक और इस्तेमाल के टाइप पर नज़र डालते हैं कि आपका प्लग इन इनमें से हर एक में समर्थन कर सकता है:

finalizeDsl(callback: (DslExtensionT) -> Unit)

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

abstract class ExamplePlugin: Plugin<Project> {

    override fun apply(project: Project) {
        val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)
        androidComponents.finalizeDsl { extension ->
            extension.buildTypes.create("extra").let {
                it.isJniDebuggable = true
            }
        }
    }
}

beforeVariants()

बिल्ड के इस चरण में, आपको VariantBuilder ऑब्जेक्ट का ऐक्सेस मिलता है, जो बनाए जाने वाले वैरिएंट और उनकी प्रॉपर्टी तय करता है. उदाहरण के लिए, आपके पास प्रोग्राम बनाकर, कुछ वैरिएंट, उनके टेस्ट को बंद करने या किसी मौजूदा वैरिएंट को सिर्फ़ चुने गए वैरिएंट के लिए, प्रॉपर्टी की वैल्यू (उदाहरण के लिए, minSdk). इसके समान finalizeDsl(), आपकी ओर से दी गई सभी वैल्यू, कॉन्फ़िगरेशन के दौरान हल होनी चाहिए समय की गणना करते हैं और बाहरी इनपुट पर निर्भर नहीं होते. VariantBuilder ऑब्जेक्ट beforeVariants() कॉलबैक पूरा होने के बाद, डेटा में बदलाव किया जाता है.

androidComponents {
    beforeVariants { variantBuilder ->
        variantBuilder.minSdk = 23
    }
}

विकल्प के तौर पर, beforeVariants() कॉलबैक VariantSelector का इस्तेमाल करता है. इसे selector() तरीके से androidComponentsExtension से डाउनलोड करें. आप कॉलबैक इनकार में भाग लेने वाले कॉम्पोनेंट को इसके आधार पर फ़िल्टर करने के लिए इसका इस्तेमाल करें उनके नाम, बिल्ड टाइप या प्रॉडक्ट का फ़्लेवर शामिल किया जाता है.

androidComponents {
    beforeVariants(selector().withName("adfree")) { variantBuilder ->
        variantBuilder.minSdk = 23
    }
}

onVariants()

onVariants() के कॉल होने तक, वे सभी आर्टफ़ैक्ट जो बनाएंगे एजीपी ने पहले ही फ़ैसला ले लिया है, इसलिए अब उन्हें बंद नहीं किया जा सकता. हालांकि, आपके पास ये काम करने का विकल्प भी है टास्क के लिए इस्तेमाल की जाने वाली कुछ वैल्यू में बदलाव करें. इसके लिए, Variant ऑब्जेक्ट में Property एट्रिब्यूट. क्योंकि Property वैल्यू एजीपी के टास्क पूरे होने के बाद ही वे रिज़ॉल्व हो सकते हैं. साथ ही, उन्हें सुरक्षित तरीके से जोड़कर, सेवा देने वाली ऐसी कंपनियां जो आपके हिसाब से बनाए गए टास्क में शामिल की गई हैं, जो सभी ज़रूरी काम करेंगी कंप्यूटेशन (कंप्यूटेशन) जिनमें फ़ाइलें या नेटवर्क जैसे बाहरी इनपुट से ली गई जानकारी शामिल होती है.

// onVariants also supports VariantSelectors:
onVariants(selector().withBuildType("release")) { variant ->
    // Gather the output when we are in single mode (no multi-apk).
    val mainOutput = variant.outputs.single { it.outputType == OutputType.SINGLE }

    // Create version code generating task
    val versionCodeTask = project.tasks.register("computeVersionCodeFor${variant.name}", VersionCodeTask::class.java) {
        it.outputFile.set(project.layout.buildDirectory.file("${variant.name}/versionCode.txt"))
    }
    /**
     * Wire version code from the task output.
     * map() will create a lazy provider that:
     * 1. Runs just before the consumer(s), ensuring that the producer
     * (VersionCodeTask) has run and therefore the file is created.
     * 2. Contains task dependency information so that the consumer(s) run after
     * the producer.
     */
    mainOutput.versionCode.set(versionCodeTask.map { it.outputFile.get().asFile.readText().toInt() })
}

बिल्ड में जनरेट किए गए सोर्स का योगदान दें

आपका प्लगिन, जनरेट किए गए कुछ टाइप के सोर्स में योगदान दे सकता है, जैसे:

जोड़े जा सकने वाले सोर्स की पूरी सूची देखने के लिए, यहां जाएं: Sources API.

यह कोड स्निपेट, addStaticSourceDirectory() का इस्तेमाल करके ${variant.name} को Java सोर्स सेट पर सेट करें फ़ंक्शन का इस्तेमाल करना होगा. इसके बाद, Android टूलचेन इस फ़ोल्डर को प्रोसेस करता है.

onVariants { variant ->
    variant.sources.java?.let { java ->
        java.addStaticSourceDirectory("custom/src/kotlin/${variant.name}")
    }
}

addJavaSource रेसिपी देखें देखें.

इस कोड स्निपेट में, Android के संसाधनों के साथ डायरेक्ट्री जोड़ने का तरीका बताया गया है कस्टम टास्क से res सोर्स सेट में जनरेट किया गया. यह प्रक्रिया स्रोत प्रकार.

onVariants(selector().withBuildType("release")) { variant ->
    // Step 1. Register the task.
    val resCreationTask =
       project.tasks.register<ResCreatorTask>("create${variant.name}Res")

    // Step 2. Register the task output to the variant-generated source directory.
    variant.sources.res?.addGeneratedSourceDirectory(
       resCreationTask,
       ResCreatorTask::outputDirectory)
    }

...

// Step 3. Define the task.
abstract class ResCreatorTask: DefaultTask() {
   @get:OutputFiles
   abstract val outputDirectory: DirectoryProperty

   @TaskAction
   fun taskAction() {
      // Step 4. Generate your resources.
      ...
   }
}

addCustomAsset रेसिपी देखें देखें.

आर्टफ़ैक्ट ऐक्सेस करना और उनमें बदलाव करना

Variant ऑब्जेक्ट पर आसान प्रॉपर्टी में बदलाव करने की अनुमति देने के साथ-साथ, एजीपी इसमें एक एक्सटेंशन मैकेनिज़्म भी होता है, जो आपको पढ़ने या रूपांतरण की अनुमति देता है निर्माण के दौरान तैयार किए गए इंटरमीडिएट और फ़ाइनल आर्टफ़ैक्ट. उदाहरण के लिए, आपके पास कस्टम Task में मर्ज की गई AndroidManifest.xml फ़ाइल का फ़ाइनल कॉन्टेंट पढ़ें, ताकि इसका विश्लेषण करें या इसके कॉन्टेंट को पूरी तरह से मेनिफ़ेस्ट फ़ाइल से बदला जा सकता है आपके कस्टम Task से जनरेट हुआ है.

आपको उन आर्टफ़ैक्ट की सूची मिलेगी जो फ़िलहाल रेफ़रंस में काम करते हैं Artifact क्लास के लिए दस्तावेज़. हर तरह के आर्टफ़ैक्ट में कुछ ऐसी प्रॉपर्टी होती हैं जिनके बारे में जानकारी होना उपयोगी होता है:

एलिमेंट की संख्या

Artifact के एलिमेंट की संख्या, FileSystemLocation की संख्या दिखाती है इंस्टेंस या आर्टफ़ैक्ट टाइप की फ़ाइलों या डायरेक्ट्री की संख्या. आप आर्टफ़ैक्ट के एलिमेंट की संख्या के बारे में जानने के लिए, उसके पैरंट एलिमेंट की जांच करें क्लास: एक FileSystemLocation वाली कलाकृतियां, इसकी सब-क्लास होगी Artifact.Single; एक से ज़्यादा FileSystemLocation इंस्टेंस वाले आर्टफ़ैक्ट Artifact.Multiple की सब-क्लास होनी चाहिए.

FileSystemLocation तरह का

Artifact में फ़ाइलों या डायरेक्ट्री के बारे में जानकारी होती है. इसके लिए, पैरामीटर वाला FileSystemLocation टाइप, जो RegularFile या Directory.

काम करने वाली कार्रवाइयां

हर Artifact क्लास, नीचे दिए गए इंटरफ़ेस में से किसी भी इंटरफ़ेस को लागू कर सकती है. यह किन कार्रवाइयों में मदद करता है:

  • Transformable: इसकी मदद से, Artifact को इनपुट के तौर पर Task में इस्तेमाल किया जा सकता है उस पर आर्बिट्रेरी ट्रांसफ़ॉर्मेशन करता है और Artifact.
  • Appendable: सिर्फ़ उन आर्टफ़ैक्ट पर लागू होता है जो इसकी सब-क्लास हैं Artifact.Multiple. इसका मतलब है कि Artifact को जोड़ा जा सकता है, यानी कि कस्टम Task, इस Artifact टाइप के नए इंस्टेंस बना सकता है. इन्हें जोड़ दिया जाएगा मौजूदा सूची से लिंक करें.
  • Replaceable: सिर्फ़ उन आर्टफ़ैक्ट पर लागू होता है जो इसकी सब-क्लास हैं Artifact.Single. बदले जा सकने वाले Artifact को जिसे Task के आउटपुट के तौर पर बनाया गया है.

तीन आर्टफ़ैक्ट-मॉडिफ़ाइंग ऑपरेशन के अलावा, हर आर्टफ़ैक्ट get() (या getAll()) ऑपरेशन, जो आर्टफ़ैक्ट के आखिरी वर्शन के साथ Provider दिखाता है (उस पर सभी कार्रवाइयां पूरी हो जाने के बाद).

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

रजिस्टर करने की प्रक्रिया में इस्तेमाल होने वाला एंट्री पॉइंट, Artifacts क्लास है. नीचे दिया गया कोड स्निपेट दिखाता है कि आप onVariants() में, Variant ऑब्जेक्ट की प्रॉपर्टी से Artifacts कॉलबैक.

इसके बाद, अपनी पसंद के मुताबिक TaskProvider पास करके, TaskBasedOperation ऑब्जेक्ट (1) को कॉपी कर सकता है. साथ ही, इसका इस्तेमाल अपने इनपुट और आउटपुट को कनेक्ट करने के लिए, इनमें से किसी एक wiredWith* तरीके (2).

आपको चुनने का सटीक तरीका, एलिमेंट की संख्या और Artifact के ज़रिए लागू किया गया FileSystemLocation टाइप, जिसे आपको बदलना है.

आखिर में, आपको चुने गए विकल्प के तौर पर Artifact टाइप में पास करना होगा *OperationRequest ऑब्जेक्ट पर की गई कार्रवाई, जो बदले में आपको मिलती है. उदाहरण के लिए, toAppendTo(), toTransform() , या toCreate() (3).

androidComponents.onVariants { variant ->
    val manifestUpdater = // Custom task that will be used for the transform.
            project.tasks.register(variant.name + "ManifestUpdater", ManifestTransformerTask::class.java) {
                it.gitInfoFile.set(gitVersionProvider.flatMap(GitVersionTask::gitVersionOutputFile))
            }
    // (1) Register the TaskProvider w.
    val variant.artifacts.use(manifestUpdater)
         // (2) Connect the input and output files.
        .wiredWithFiles(
            ManifestTransformerTask::mergedManifest,
            ManifestTransformerTask::updatedManifest)
        // (3) Indicate the artifact and operation type.
        .toTransform(SingleArtifact.MERGED_MANIFEST)
}

इस उदाहरण में, MERGED_MANIFEST एक SingleArtifact है और यह RegularFile. इस वजह से, हमें wiredWithFiles तरीके का इस्तेमाल करना होगा, इनपुट के लिए एक RegularFileProperty रेफ़रंस स्वीकार करता है और आउटपुट के लिए RegularFileProperty. इस पर अन्य wiredWith* तरीके भी मौजूद हैं TaskBasedOperation क्लास, जो Artifact के अन्य कॉम्बिनेशन के लिए काम करेगी एलिमेंट की संख्या और FileSystemLocation टाइप.

एजीपी की पहुंच बढ़ाने के बारे में ज़्यादा जानने के लिए, हमारा सुझाव है कि आप ये सेक्शन पढ़ें यह जानकारी Gradle बिल्ड सिस्टम मैन्युअल से ली गई है: