Gradle eklentileri yazma

Android Gradle eklentisi (AGP), Android uygulamaları için resmi derleme sistemidir. Birçok farklı kaynak türünü derleme ve bunları fiziksel bir Android cihazda veya emülatörde çalıştırabileceğiniz bir uygulamada bir araya getirme desteği içerir.

AGP, eklentilerin derleme girişlerini kontrol etmesi ve standart derleme görevleriyle entegre edilebilen yeni adımlar aracılığıyla işlevini genişletmesi için uzantı noktaları içerir. AGP'nin önceki sürümlerinde, resmi API'ler dahili uygulamalardan net bir şekilde ayrılmış değildi. AGP'nin 7.0 sürümünden itibaren güvenebileceğiniz bir dizi resmi, kararlı API vardır.

AGP API yaşam döngüsü

AGP, API'lerinin durumunu belirlemek için Gradle özelliği yaşam döngüsünü izler:

  • Dahili: Herkese açık kullanım için tasarlanmamıştır
  • Oluşturma: Herkese açık olarak kullanılabilir ancak nihai değil, yani nihai sürümde geriye dönük uyumlu olmayabilecekleri
  • Herkese açık: Herkese açık ve kararlı olarak kullanılabilir.
  • Desteği sonlandırıldı: Artık desteklenmiyor ve yeni API'lerle değiştirildi

Kullanımdan kaldırma politikası

Eski API'lerin kullanımdan kaldırılması ve bunların yerini yeni, kararlı API'ler ve yeni bir Alana Özel Dil (DSL) ile birlikte AGP'de geliştirmeler yapmaktayız. Bu gelişme, birden fazla AGP sürümünü kapsayacak. Bu konu hakkında daha fazla bilgiyi AGP API/DSL taşıma zaman çizelgesinde bulabilirsiniz.

AGP API'leri kullanımdan kaldırıldığında, bu taşıma işlemi veya başka bir işlem için mevcut büyük sürümde kullanılmaya devam edecek ancak uyarı oluşturacaktır. Desteği sonlandırılan API'ler, sonraki büyük sürümde AGP'den tamamen kaldırılacaktır. Örneğin, AGP 7.0'da desteği sonlandırılan bir API, bu sürümde kullanılabilir ve uyarı oluşturur. Bu API, AGP 8.0'da artık kullanılamayacaktır.

Yaygın derleme özelleştirmelerinde kullanılan yeni API'lerin örneklerini görmek için Android Gradle eklentisi tariflerine göz atın. Bu makalelerde, yaygın derleme özelleştirmelerine örnekler verilmiştir. Yeni API'ler hakkında daha fazla bilgiyi referans belgelerimizde de bulabilirsiniz.

Gradle derlemeyle ilgili temel bilgiler

Bu kılavuzda Gradle derleme sisteminin tamamı ele alınmamaktadır. Ancak API'lerimizle entegrasyon yapmanıza yardımcı olacak minimum düzeyde gerekli kavramları kapsar ve daha fazla okuma için ana Gradle dokümanlarına bağlantılar içerir.

Projelerin nasıl yapılandırılacağı, derleme dosyalarının nasıl düzenleneceği, eklentilerin nasıl uygulanacağı ve görevlerin nasıl çalıştırılacağı da dahil olmak üzere Gradle'ın nasıl çalıştığıyla ilgili temel bilgilerin olduğunu varsayarız. AGP ile ilgili Gradle'in temelleri hakkında bilgi edinmek için Derlemenizi yapılandırma başlıklı makaleyi incelemenizi öneririz. Gradle eklentilerini özelleştirmeyle ilgili genel çerçeve hakkında bilgi edinmek için Özel Gradle Eklentileri Geliştirme başlıklı makaleyi inceleyin.

Gradle'da yavaş türler sözlüğü

Gradle,"tembel" davranan veya ağır hesaplamaları ya da Task oluşturma işlemlerini derlemenin sonraki aşamalarına ertelemeye yardımcı olan çeşitli türler sunar. Bu türler, birçok Gradle ve AGP API'sinin temelinde yer alır. Aşağıdaki listede, yavaş yürütmeyle ilgili ana Gradle türleri ve bunların temel yöntemleri yer almaktadır.

Provider<T>
get() kullanılarak yürütme aşamasında okunabilen veya map(), flatMap() ve zip() yöntemleri kullanılarak yeni bir Provider<S>'e dönüştürülebilen T türündeki bir değer sağlar ("T" herhangi bir türü ifade eder). get() işlevinin yapılandırma aşamasında hiçbir zaman çağrılmaması gerektiğini unutmayın.
  • map(): Lambda kabul eder ve S türünde bir Provider oluşturur,Provider<S>. map() işlevinin lambda bağımsız değişkeni, T değerini alır ve S değerini döndürür. Lambda hemen yürütülmez. Bunun yerine, yürütülmesi, elde edilen Provider<S> üzerinde get() çağrılana kadar ertelenir. Bu da zincirin tamamını tembel hale getirir.
  • flatMap(): Ayrıca lambda kabul eder ve Provider<S> üretir ancak lambda, T değerini alır ve Provider<S> üretir (doğrudan S değerini üretmek yerine). S, yapılandırma sırasında belirlenemediğinde ve yalnızca Provider<S> elde edilebildiğinde flatMap() işlevini kullanın. Pratikte map() kullandıysanız ve bir Provider<Provider<S>> sonuç türü elde ettiyseniz muhtemelen flatMap() sonuç türünü kullanmanız gerekirdi.
  • zip(): İki Provider örneğini birleştirerek yeni bir Provider oluşturmanıza olanak tanır. Bu Provider, iki giriş Providers örneğindeki değerleri birleştiren bir işlev kullanılarak hesaplanır.
Property<T>
Provider<T> uyguladığından, T türünde bir değer de sağlar. Salt okunur olan Provider<T>'in aksine Property<T> için de değer ayarlayabilirsiniz. Bunu yapmanın iki yolu vardır:
  • Ertelenen hesaplamalara gerek kalmadan, T türündeki bir değeri doğrudan kullanılabilir olduğunda ayarlayın.
  • Property<T> değerinin kaynağı olarak başka bir Provider<T> ayarlayın. Bu durumda, T değeri yalnızca Property.get() çağrıldığında gerçekleşir.
TaskProvider
Provider<Task> uygular. Bir TaskProvider oluşturmak için görevlerin yalnızca ihtiyaç duyulduğunda geç başlatılmasını sağlamak amacıyla tasks.create() yerine tasks.register() kullanın. Task oluşturulmadan önce Task'ın çıkışlarına erişmek için flatMap()'ü kullanabilirsiniz. Bu, çıkışları diğer Task örneklerine giriş olarak kullanmak istiyorsanız yararlı olabilir.

Sağlayıcılar ve dönüşüm yöntemleri, görevlerin giriş ve çıkışlarını tembel bir şekilde ayarlamak için gereklidir. Yani tüm görevleri önceden oluşturmak ve değerleri çözmek gerekmez.

Sağlayıcılar, görev bağımlılık bilgilerini de taşır. Bir Task çıkışını dönüştürerek Provider oluşturduğunuzda, bu Task Provider'nin gizli bir bağımlılığı haline gelir ve Provider'nin değeri çözüldüğünde (ör. başka bir Task bunu gerektirdiğinde) oluşturulur ve çalıştırılır.

Aşağıda, GitVersionTask ve ManifestProducerTask adlı iki görevi kaydederken Task örneklerini gerçekten gerekli olana kadar oluşturmayı erteleyen bir örnek verilmiştir. ManifestProducerTask giriş değeri, GitVersionTask çıkışından elde edilen Provider olarak ayarlanır. Bu nedenle ManifestProducerTask, dolaylı olarak GitVersionTask değerine bağlıdır.

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

Bu iki görev, yalnızca açıkça istenmeleri durumunda yürütülür. Bu durum, Gradle çağrısı kapsamında gerçekleşebilir. Örneğin, ./gradlew debugManifestProducer çalıştırırsanız veya ManifestProducerTask işlevinin çıkışı başka bir göreve bağlanırsa ve değeri gerekli hale gelirse bu durum gerçekleşebilir.

Giriş kullanan ve/veya çıkış üreten özel görevler yazarsınız ancak AGP, kendi görevlerine doğrudan herkese açık erişim sağlamaz. Bunlar, sürümden sürüme değişiklik gösterebilen bir uygulama ayrıntısıdır. Bunun yerine AGP, Variant API'yi ve görevlerin çıktısına veya okuyup dönüştürebileceğiniz derleme yapılarına erişim sunar. Daha fazla bilgi için bu dokümanda Variant API, Yapılar ve Görevler bölümüne bakın.

Gradle derleme aşamaları

Proje oluşturma işlemi, doğası gereği karmaşık ve kaynak gerektiren bir süreçtir. Yinelenebilir veya gereksiz hesaplamalara harcanan zamanı en aza indirmeye yardımcı olan görev yapılandırmasından kaçınma, güncel kontroller ve yapılandırma önbelleğe alma gibi çeşitli özellikler vardır.

Bu optimizasyonlardan bazılarını uygulamak için Gradle komut dosyaları ve eklentilerinin, farklı Gradle derleme aşamalarının her birinde (başlatma, yapılandırma ve yürütme) katı kurallara uyması gerekir. Bu kılavuzda, yapılandırma ve yürütme aşamalarına odaklanacağız. Tüm aşamalar hakkında daha fazla bilgiyi Gradle derleme yaşam döngüsü kılavuzunda bulabilirsiniz.

Yapılandırma aşaması

Yapılandırma aşamasında, derlemenin parçası olan tüm projelerin derleme komut dosyaları değerlendirilir, eklentiler uygulanır ve derleme bağımlılıkları çözülür. Bu aşama, DSL nesnelerini kullanarak derlemeyi yapılandırmak ve görevleri ile girişlerini yavaşça kaydetmek için kullanılmalıdır.

Yapılandırma aşaması, hangi görevin çalıştırılmasının istendiğine bakılmaksızın her zaman çalıştığından, bu aşamanın basit tutulması ve tüm hesaplamaların derleme komut dosyalarının kendisinden başka girişlere bağlı olmasının kısıtlanması özellikle önemlidir. Yani harici programları çalıştırmamalı, ağdan veri okumamalı veya uygun Task örnekleri olarak yürütme aşamasına ertelenebilir uzun hesaplamalar yapmamalısınız.

Yürütme aşamasında

Yürütme aşamasında, istenen görevler ve bunlara bağlı görevler yürütülür. Özellikle, @TaskAction ile işaretlenen Task sınıf yöntemleri yürütülür. Görev yürütülürken girişlerden (ör. dosyalar) okumanıza ve Provider<T>.get()'ü çağırarak tembel sağlayıcıları çözmenize izin verilir. Tembel sağlayıcıları bu şekilde çözmek, sağlayıcıda bulunan görev bağımlılık bilgilerini izleyen bir dizi map() veya flatMap() çağrısı başlatır. Görevler, gerekli değerleri gerçekleştirmek için geç çalıştırılır.

Varyant API'si, Yapılar ve Görevler

Variant API, Android Gradle eklentisinde bulunan ve genellikle yapılandırma dosyaları için DSL kullanılarak ayarlanan ve Android derlemesini etkileyen çeşitli seçenekleri değiştirmenize olanak tanıyan bir uzantı mekanizmasıdır. Variant API, derleme tarafından oluşturulan sınıf dosyaları, birleştirilmiş manifest veya APK/AAB dosyaları gibi ara ve nihai yapı öğelerine de erişim sağlar.

Android derleme akışı ve uzantı noktaları

AGP ile etkileşimde bulunurken, tipik Gradle yaşam döngüsü geri çağırmalarını (ör. afterEvaluate()) kaydetme veya açık Task bağımlılıkları ayarlama yerine özel olarak oluşturulmuş uzantı noktalarını kullanın. AGP tarafından oluşturulan görevler, uygulama ayrıntıları olarak kabul edilir ve herkese açık bir API olarak sunulmaz. Task nesnelerinin örneklerini almaya çalışmamalı, Task adlarını tahmin etmemeli ve bu Task nesnelerine doğrudan geri çağırma veya bağımlılık eklememelidir.

AGP, Task örneklerini oluşturup yürütmek için aşağıdaki adımları tamamlar. Bu adımlar da derleme yapılarını oluşturur. Variant öğesi oluşturma ile ilgili ana adımlardan sonra, derleme kapsamında oluşturulan belirli öğelerde değişiklik yapmanıza olanak tanıyan geri çağırma işlevleri gelir. Tüm geri çağırma çağrılarının yapılandırma aşamasında (bu sayfada açıklanmıştır) gerçekleştiğini ve hızlı bir şekilde çalıştığını, karmaşık tüm işlemlerin yürütme aşamasında uygun Task örneklerine ertelendiğine dikkat etmek önemlidir.

  1. DSL ayrıştırma: Bu aşamada derleme komut dosyaları değerlendirilir ve android bloğundaki Android DSL nesnelerinin çeşitli özellikleri oluşturulup ayarlanır. Aşağıdaki bölümlerde açıklanan Variant API geri çağırma işlevleri de bu aşamada kaydedilir.
  2. finalizeDsl(): DSL nesnelerini bileşen (varyant) oluşturma için kilitlenmeden önce değiştirmenize olanak tanıyan geri çağırma işlevi. VariantBuilder nesneleri, DSL nesnelerinde bulunan verilere göre oluşturulur.

  3. DSL kilitleme: DSL kilitlendi ve artık değişiklik yapılamaz.

  4. beforeVariants(): Bu geri çağırma, VariantBuilder aracılığıyla hangi bileşenlerin oluşturulacağını ve bazı özelliklerini etkileyebilir. Derleme akışında ve üretilen yapılarda değişikliklere izin vermeye devam eder.

  5. Varyant oluşturma: Oluşturulacak bileşen ve yapıların listesi artık tamamlanmıştır ve değiştirilemez.

  6. onVariants(): Bu geri çağırma işlevinde, oluşturulan Variant nesnelerine erişirsiniz ve içerdikleri Property değerleri için değerleri veya sağlayıcıları ayarlayarak değerlerin yavaşça hesaplanmasını sağlayabilirsiniz.

  7. Varyant kilitleme: Varyant nesneleri artık kilitlenmiştir ve değişiklikler yapılamaz.

  8. Oluşturulan görevler: Derlemeyi gerçekleştirmek için gerekli olan Task örneklerini oluşturmak amacıyla Variant nesneleri ve bunların Property değerleri kullanılır.

AGP, finalizeDsl(), beforeVariants() ve onVariants() için geri çağırma işlevleri kaydetmenize olanak tanıyan bir AndroidComponentsExtension sunar. Uzantı, androidComponents bloğu aracılığıyla derleme komut dosyalarında kullanılabilir:

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

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

Ancak, derleme komut dosyalarını yalnızca android bloğunun DSL'sini kullanarak açıklayıcı yapılandırma için kullanmanızı ve özel zorunlu mantığı buildSrc veya harici eklentilere taşımanızı öneririz. Projenizde nasıl eklenti oluşturacağınızı öğrenmek için Gradle tarifleri GitHub depomuzda bulunan buildSrcörneklerine de göz atabilirsiniz. Aşağıda, geri çağırma işlevlerini eklenti kodundan kaydetme örneği verilmiştir:

abstract class ExamplePlugin: Plugin<Project> {

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

Kullanılabilir geri çağırmalara ve eklentinizin her birinde destekleyebileceği kullanım alanı türlerine daha yakından bakalım:

finalizeDsl(callback: (DslExtensionT) -> Unit)

Bu geri çağırma işlevinde, derleme dosyalarındaki android bloğundaki bilgileri ayrıştırarak oluşturulan DSL nesnelerine erişebilir ve bu nesneleri değiştirebilirsiniz. Bu DSL nesneleri, derlemenin sonraki aşamalarında varyantları başlatmak ve yapılandırmak için kullanılır. Örneğin, programlı olarak yeni yapılandırmalar oluşturabilir veya özellikleri geçersiz kılabilirsiniz. Ancak tüm değerlerin yapılandırma sırasında çözülmesi gerektiğini ve bu nedenle harici girişlere ihtiyaç duymaması gerektiğini unutmayın. Bu geri çağırma işlevi tamamlandıktan sonra DSL nesneleri artık yararlı değildir ve bu nesnelere referans vermemeli veya değerlerini değiştirmemelisiniz.

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()

Derlemenin bu aşamasında, oluşturulacak varyantları ve bunların özelliklerini belirleyen VariantBuilder nesnelerine erişebilirsiniz. Örneğin, belirli varyantları ve testlerini programatik olarak devre dışı bırakabilir veya bir mülkün değerini (ör. minSdk) yalnızca seçili bir varyant için değiştirebilirsiniz. finalizeDsl()'e benzer şekilde, sağladığınız tüm değerlerin yapılandırma sırasında çözülmesi ve harici girişlere bağlı olmaması gerekir. beforeVariants() geri çağırma işlevinin yürütülmesi sona erdiğinde VariantBuilder nesneleri değiştirilmemelidir.

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

beforeVariants() geri çağırma işlevi isteğe bağlı olarak bir VariantSelector alır. androidComponentsExtension üzerindeki selector() yöntemini kullanarak bu değeri elde edebilirsiniz. Geri çağırma çağrısına katılan bileşenleri adlarına, derleme türüne veya ürün çeşidine göre filtrelemek için kullanabilirsiniz.

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

onVariants()

onVariants() çağrıldığı zaman, AGP tarafından oluşturulacak tüm yapıların ne olacağına karar verilmiş olur. Bu nedenle, artık bunları devre dışı bırakamazsınız. Ancak görevler için kullanılan değerlerin bazılarını Variant nesnelerindeki Property özellikleri için ayarlayarak değiştirebilirsiniz. Property değerleri yalnızca AGP'nin görevleri yürütüldüğünde çözüleceğinden, bunları dosya veya ağ gibi harici girişlerden okuma da dahil olmak üzere gerekli tüm hesaplamaları yapacak olan kendi özel görevlerinizden sağlayıcılara güvenli bir şekilde bağlayabilirsiniz.

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

Oluşturulan kaynakları derlemeye katkıda bulunma

Eklentiniz, oluşturulan birkaç türde kaynağa katkıda bulunabilir. Örneğin:

Ekleyebileceğiniz kaynakların tam listesi için Sources API'ye bakın.

Bu kod snippet'inde, addStaticSourceDirectory() işlevi kullanılarak Java kaynak grubuna ${variant.name} adlı özel bir kaynak klasörünün nasıl ekleneceği gösterilmektedir. Ardından, Android araç zinciri bu klasörü işler.

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

Daha fazla bilgi için addJavaSource tarifine bakın.

Bu kod snippet'inde, özel bir görevden oluşturulan Android kaynaklarını içeren bir dizinin res kaynak grubuna nasıl ekleneceği gösterilmektedir. Diğer kaynak türleri için de benzer bir süreç geçerlidir.

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

Daha ayrıntılı bilgi için addCustomAsset tarifine bakın.

Yapılara erişim ve yapıları değiştirme

AGP, Variant nesnelerindeki basit özellikleri değiştirmenize olanak tanımanın yanı sıra derleme sırasında üretilen ara ve nihai yapıları okumanıza veya dönüştürmenize olanak tanıyan bir uzantı mekanizması da içerir. Örneğin, birleştirilmiş nihai AndroidManifest.xml dosya içeriğini özel bir Task'da okuyarak analiz edebilir veya içeriğini tamamen özel Task'unuz tarafından oluşturulan bir manifest dosyasının içeriğiyle değiştirebilirsiniz.

Şu anda desteklenen yapıların listesini Artifact sınıfının referans dokümanlarında bulabilirsiniz. Her yapı türü, bilinmesi yararlı olan belirli özelliklere sahiptir:

Kardinalite

Bir Artifact öğesinin kardinalitesi, FileSystemLocation örneğinin sayısını veya yapı türündeki dosya ya da dizin sayısını gösterir. Bir yapının üst sınıfını kontrol ederek bu yapının kardinalitesi hakkında bilgi edinebilirsiniz: Tek bir FileSystemLocation öğesine sahip yapılar Artifact.Single alt sınıfı olur; birden fazla FileSystemLocation örneği olan yapılar Artifact.Multiple alt sınıfı olur.

FileSystemLocation tür

Bir Artifact değerinin dosyaları mı yoksa dizinleri mi temsil ettiğini, parametrelendirilmiş FileSystemLocation türüne bakarak kontrol edebilirsiniz. Bu tür, RegularFile veya Directory olabilir.

Desteklenen işlemler

Her Artifact sınıfı, hangi işlemleri desteklediğini belirtmek için aşağıdaki arayüzlerden herhangi birini uygulayabilir:

  • Transformable: Bir Artifact'ın, üzerinde rastgele dönüşümler gerçekleştiren ve Artifact'ın yeni bir sürümünü yayınlayan bir Task'e giriş olarak kullanılmasına olanak tanır.
  • Appendable: Yalnızca Artifact.Multiple alt sınıfı olan yapı taşlarında geçerlidir. Bu, Artifact öğesinin eklenebilir olduğu anlamına gelir. Yani özel bir Task, mevcut listeye eklenecek bu Artifact türüne ait yeni örnekler oluşturabilir.
  • Replaceable: Yalnızca Artifact.Single alt sınıfı olan yapı taşlarında geçerlidir. Değiştirilebilir bir Artifact, Task çıkışı olarak üretilen tamamen yeni bir örnekle değiştirilebilir.

Her yapı, yapıyı değiştiren üç işleme ek olarak bir get() (veya getAll()) işlemini destekler. Bu işlem, yapının nihai sürümünü (yapıdaki tüm işlemler tamamlandıktan sonra) içeren bir Provider döndürür.

Birden fazla eklenti, onVariants() geri çağırma işlevinden ardışık düzene öğelerle ilgili herhangi bir sayıda işlem ekleyebilir. AGP, tüm görevlerin doğru zamanda çalıştırılması ve öğelerin doğru şekilde üretilip güncellenmesi için bunların düzgün bir şekilde zincirlendiğinden emin olur. Bu, bir işlem herhangi bir çıktıyı ekleyerek, değiştirerek veya dönüştürerek değiştirdiğinde bir sonraki işlemin bu yapıların güncellenmiş sürümünü giriş olarak göreceği anlamına gelir.

Kayıt işlemlerinin giriş noktası Artifacts sınıfıdır. Aşağıdaki kod snippet'i, onVariants() geri çağırma işlevinde Variant nesnesindeki bir mülkten Artifacts örneğine nasıl erişim sağlayabileceğinizi gösterir.

Ardından, özel TaskProvider öğenizi göndererek TaskBasedOperation nesnesi (1) elde edebilir ve wiredWith* yöntemlerinden birini kullanarak girişlerini ve çıkışlarını bağlamak için bu nesneyi kullanabilirsiniz (2).

Seçmeniz gereken tam yöntem, dönüştürmek istediğiniz Artifact tarafından uygulanan kardinaliteye ve FileSystemLocation türüne bağlıdır.

Son olarak, Artifact türünü, karşılığında aldığınız *OperationRequest nesnesi üzerinde seçilen işlemi temsil eden bir yönteme (örneğin, toAppendTo(), toTransform() veya toCreate() (3)) iletirsiniz.

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

Bu örnekte MERGED_MANIFEST hem SingleArtifact hem de RegularFile öğesidir. Bu nedenle, giriş için tek bir RegularFileProperty referansı ve çıkış için tek bir RegularFileProperty kabul eden wiredWithFiles yöntemini kullanmamız gerekir. TaskBasedOperation sınıfında, diğer Artifact kardinalite ve FileSystemLocation türü kombinasyonları için çalışacak başka wiredWith* yöntemleri vardır.

AGP'yi genişletme hakkında daha fazla bilgi edinmek için Gradle derleme sistemi kılavuzundaki aşağıdaki bölümleri okumanızı öneririz: