Gradle eklentileri yazma

Android Gradle eklentisi (AGP), Android uygulamaları için resmi derleme sistemidir. Çok sayıda farklı kaynak türünü derleyip bunları fiziksel bir Android cihazda veya emülatörde çalıştırabileceğiniz bir uygulamaya bağlamayı da destekler.

AGP, eklentilerin derleme girişlerini kontrol etmek ve standart derleme görevleriyle entegre edilebilen yeni adımlarla işlevselliğini genişletmek için uzantı noktaları içerir. AGP'nin önceki sürümleri, dahili uygulamalardan net bir şekilde ayrılmış resmi API'lere sahip değildi. 7.0 sürümünden itibaren AGP, güvenebileceğiniz bir dizi resmi ve kararlı API'ye sahiptir.

AGP API yaşam döngüsü

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

  • Dahili: Genel kullanıma yönelik değildir
  • Oluşturulma: Herkesin kullanımına açıktır ancak nihai değildir, yani nihai sürümde geriye dönük uyumlu olmayabilirler.
  • Herkese açık: Herkesin kullanımına açık ve kararlı sürüm
  • Kullanımdan kaldırıldı: Artık desteklenmiyor ve yeni API'lerle değiştirildi

Kullanımdan kaldırma politikası

AGP, eski API'lerin kullanımdan kaldırılmasıyla ve bunların yeni, kararlı API'ler ve yeni bir Alana Özgü Dil (DSL) ile değiştirilmesiyle birlikte gelişmektedir. Bu gelişme, birden fazla AGP sürümünü kapsayacaktır. 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 sırasında veya başka bir nedenle, mevcut ana sürümde kullanılmaya devam edecek ancak uyarı oluşturacaktır. Kullanımdan kaldırılan API'ler, bir sonraki ana sürümde AGP'den tamamen kaldırılacaktır. Örneğin, AGP 7.0'da bir API kullanımdan kaldırılırsa bu sürümde kullanılabilir olur ve uyarılar oluşturur. Bu API artık AGP 8.0'da kullanılamayacaktır.

Sık kullanılan derleme özelleştirmelerinde kullanılan yeni API'lerin örneklerini görmek için Android Gradle eklentisi tariflerine göz atın. Bunlar, yaygın derleme özelleştirmelerine ilişkin örnekler sağlar. Yeni API'ler hakkında daha fazla bilgiyi referans belgelerimizde de bulabilirsiniz.

Gradle derlemeyle ilgili temel bilgiler

Bu kılavuz, Gradle derleme sisteminin tamamını kapsamaz. Bununla birlikte, API'lerimizle entegrasyon gerçekleştirmenize yardımcı olmak için gereken minimum kavram kümesini kapsıyor ve daha fazla bilgi edinebilmeniz için ana Gradle belgelerine bağlantı veriyor.

Projelerin yapılandırılması, derleme dosyalarının düzenlenmesi, eklentilerin uygulanması ve görevlerin çalıştırılması da dahil olmak üzere, Gradle'ın nasıl çalıştığıyla ilgili temel bilgilere sahip olduğumuzu varsayıyoruz. AGP ile ilgili Gradle temelleri hakkında bilgi edinmek için Derlemenizi yapılandırma konusuna göz atmanızı öneririz. Gradle eklentilerini özelleştirmeye yönelik genel çerçeve hakkında bilgi edinmek için Custom Gradle Eklentileri Geliştirme bölümüne bakın.

Gradle tembel türler sözlüğü

Gradle, "tembel" davranan veya ağır hesaplamaların ya da Task oluşturma işleminin, derlemenin sonraki aşamalarına ertelenmesine yardımcı olan çeşitli türler sunar. Bu türler, birçok Gradle ve AGP API'sinin temelini oluşturur. Aşağıdaki listede, geç yürütmede yer alan ana Gradle türleri ve bunların temel yöntemleri bulunmaktadır.

Provider<T>
T türünde bir değer sağlar ("T" herhangi bir tür anlamına gelir). Bu değer, yürütme aşamasında get() kullanılarak okunabilir veya map(), flatMap() ve zip() yöntemleri kullanılarak yeni bir Provider<S> türüne ("S" farklı bir tür anlamına gelir) dönüştürülebilir. get() hizmetinin, 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 Provider üretir,Provider<S>. map() için lambda bağımsız değişkeni, T değerini alır ve S değerini verir. Lambda hemen yürütülmez. Bunun yerine, yürütme işlemi, sonuçta elde edilen Provider<S> üzerinde get() çağrıldığı ana ertelenerek tüm zincirin geç çalışmasını sağlar.
  • flatMap(): Ayrıca lambda kabul eder ve Provider<S> üretir ancak lambda T değerini alır ve Provider<S> değerini üretir (S değerini doğrudan oluşturmak yerine). S, yapılandırma zamanında belirlenemediğinde ve yalnızca Provider<S> elde edebileceğiniz durumlarda highMap() kullanın. Pratikte, map() kullandıysanız ve Provider<Provider<S>> sonuç türünü bulduysanız muhtemelen bunun yerine flatMap() kullanmanız gerekirdi.
  • zip(): İki Provider örneğini birleştirerek yeni bir Provider oluşturmanızı sağlar. Bu örnekte, iki giriş Providers örneğindeki değerleri birleştiren bir işlev kullanılarak hesaplanan bir değer kullanılır.
Property<T>
Provider<T> işlevini uyguladığı için T türünde bir değer de sağlar. Salt okunur olan Provider<T> özelliğinden farklı olarak, Property<T> için de bir değer ayarlayabilirsiniz. Bunu yapmanın iki yolu vardır:
  • Kullanılabilir olduğunda, ertelenmiş hesaplamalara gerek kalmadan doğrudan T türünde bir değer ayarlayın.
  • Property<T> değerinin kaynağı olarak başka bir Provider<T> belirleyin. Bu durumda, T değeri yalnızca Property.get() çağrıldığında somutlaştırılır.
TaskProvider
Provider<Task> öğesini uygular. TaskProvider oluşturmak için görevlerin yalnızca ihtiyaç duyulduğunda geç örneklendiğinden emin olmak amacıyla tasks.create() yerine tasks.register() kullanın. Task oluşturulmadan önce bir Task öğesinin çıkışlarına erişmek için flatMap() kullanabilirsiniz. Bu, çıkışları diğer Task örneklerine giriş olarak kullanmak istediğinizde faydalı olabilir.

Sağlayıcılar ve dönüştürme yöntemleri, görevlerin girdi ve çıktılarını tembel bir şekilde, yani tüm görevleri önceden oluşturmaya ve değerleri çözmeye gerek kalmadan ayarlamak için çok önemlidir.

Sağlayıcılar görev bağımlılığı bilgilerini de taşır. Task çıkışını dönüştürerek bir Provider oluşturduğunuzda bu Task, Provider öğesinin örtülü bir bağımlılığı haline gelir ve Provider değeri her çözümlendiğinde (örneğin başka bir Task için gerekli olduğunda) oluşturulup çalıştırılır.

GitVersionTask ve ManifestProducerTask adlı iki görevi kaydederken Task örneklerinin oluşturulmasını, gerçekten gerekli oluncaya kadar ertelemeyle ilgili bir örneği aşağıda bulabilirsiniz. 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 istenirse yürütülür. Bu durum, örneğin ./gradlew debugManifestProducer çalıştırdığınızda veya ManifestProducerTask çıkışı başka bir göreve bağlanıp değeri gerekli hale gelirse bir Gradle çağrısı kapsamında gerçekleşebilir.

Girdilerden yararlanan ve/veya çıktı üreten özel görevler yazsanız da AGP kendi görevlerine doğrudan genel erişim sunmaz. Bunlar, sürümden sürüme değişebilen bir uygulama ayrıntılarıdır. Bunun yerine AGP, Variant API sunar ve görevlerin çıkışına erişim sağlar veya okuyabileceğiniz yapılar oluşturun. Daha fazla bilgi için bu belgedeki Variant API, Artifacts ve Tasks'a bakın.

Gradle derleme aşamaları

Proje oluşturmak, doğası gereği karmaşık ve kaynak gerektiren bir süreçtir. Görev yapılandırmasından kaçınma, güncel kontroller ve yeniden oluşturulabilir ya da gereksiz hesaplamalarda harcanan zamanı en aza indiren yapılandırma önbelleğe alma özelliği gibi çeşitli özellikler bulunur.

Bu optimizasyonların bazılarını uygulamak için Gradle komut dosyaları ve eklentilerinin, ayrı 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 oluşturma 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ümlenir. Bu aşama, derlemeyi DSL nesneleri kullanarak yapılandırmak ve görevler ile girişlerini geç kaydetmek için kullanılmalıdır.

Yapılandırma aşaması hangi görevin çalıştırılması istense de her zaman çalıştığından, bu aşamayı minimumda tutmak ve derleme komut dosyaları dışındaki girişlere bağlı hesaplamaları kısıtlamak özellikle önemlidir. Yani harici programlar yürütmemeniz veya ağdan okumamanız ya da uygun Task örnekleri olarak yürütme aşamasına ertelenebilen uzun hesaplamalar yapmamanız gerekir.

Yürütme aşaması

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ütme sırasında girişlerden (ör. dosyalar) okuma yapmanıza ve Provider<T>.get() yöntemini çağırarak geç sağlayıcıları çözümlemenize izin verilir. Geç sağlayıcıların bu şekilde çözümlenmesi, sağlayıcıda bulunan görev bağımlılığı bilgilerini takip eden bir map() veya flatMap() çağrısı dizisi başlatır. Görevler, gerekli değerleri gerçeğe dönüştürmek için geç çalıştırılır.

Variant API, Artifacts ve Görevler

Variant API, Android Gradle eklentisinde bulunan ve Android derlemesini etkileyen normalde derleme yapılandırma dosyalarında DSL kullanılarak ayarlanan çeşitli seçenekleri değiştirmenize olanak tanıyan bir uzantı mekanizmasıdır. Variant API'si aynı zamanda derleme tarafından oluşturulan sınıf dosyaları, birleştirilmiş manifest veya APK/AAB dosyaları gibi ara ve son yapılara erişmenizi sağlar.

Android derleme akışı ve uzantı noktaları

AGP ile etkileşim kurarken tipik Gradle yaşam döngüsü geri çağırmalarını kaydetmek (afterEvaluate() gibi) veya açık Task bağımlılıkları ayarlamak 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 API olarak sunulmaz. Task nesnelerinin örneklerini almaya çalışmaktan veya Task adlarını tahmin etmekten ve bu Task nesnelerine doğrudan geri çağırma ya da bağımlılık eklemekten kaçınmalısınız.

AGP, Task örneklerini oluşturup yürütmek için aşağıdaki adımları tamamlar. Bu örnekler de derleme yapıları üretir. Variant nesnesinin oluşturulmasındaki ana adımların ardından, derlemenin parçası olarak oluşturulan belirli nesnelerde değişiklik yapmanızı sağlayan geri çağırmalar bulunur. Tüm geri çağırma işlemlerinin yapılandırma aşamasında (bu sayfada açıklanmıştır) gerçekleştiği ve karmaşık çalışmaların yürütme aşamasında uygun Task örneklerine ertelenerek hızlı bir şekilde çalışmaları gerektiği unutulmamalıdır.

  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ğırmaları da bu aşamada kaydedilir.
  2. finalizeDsl(): DSL nesnelerini bileşen (varyant) oluşturma için kilitlenmeden önce değiştirmenizi sağlayan geri çağırma. VariantBuilder nesneleri, DSL nesnelerinde bulunan verilere göre oluşturulur.

  3. DSL kilitleme: DSL artık kilitli olduğundan değişiklik yapılamaz.

  4. beforeVariants(): Bu geri çağırma işlemi, VariantBuilder aracılığıyla hangi bileşenlerin ve bazı özelliklerinin oluşturulduğunu etkileyebilir. Yine de derleme akışında ve oluşturulan yapılarda değişiklik yapılmasına izin verir.

  5. Varyant oluşturma: Oluşturulacak bileşenlerin ve yapıların listesi kesinleşti ve değiştirilemez.

  6. onVariants(): Bu geri çağırma işleminde, oluşturulan Variant nesnelerine erişim elde edersiniz ve geç hesaplama için içerdikleri Property değerleri için değerler veya sağlayıcılar ayarlayabilirsiniz.

  7. Varyant kilitleme: Varyant nesneleri kilitlenir ve değişiklik yapılamaz.

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

AGP; finalizeDsl(), beforeVariants() ve onVariants() için geri çağırmaları kaydetmenize olanak tanıyan AndroidComponentsExtension özelliğini sunar. Uzantı, derleme komut dosyalarında androidComponents bloğu aracılığıyla 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 kullanan bildirimli yapılandırma için tutmanızı ve özel zorunluluk mantığını buildSrc öğesine veya harici eklentilere taşımanızı öneririz. Projenizde eklenti oluşturmayı öğrenmek için Gradle tarifleri GitHub depomuzdaki buildSrc örneklerine de göz atabilirsiniz. Eklenti kodundan geri çağırmaları kaydetmeyle ilgili bir örneği burada bulabilirsiniz:

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 bunların her birinde destekleyebileceği kullanım alanı türlerine daha yakından bakalım:

finalizeDsl(callback: (DslExtensionT) -> Unit)

Bu geri çağırmada, derleme dosyalarındaki android bloğundaki bilgileri ayrıştırarak oluşturulmuş 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, programatik 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ümlenmesi gerektiğini ve bu nedenle, herhangi bir harici girişe bağlı olmamaları gerektiğini unutmayın. Bu geri çağırma işleminin yürütülmesi bittikten sonra, DSL nesneleri artık kullanılamaz ve bunlara yönelik referansları tutmamanız veya değerlerini değiştirmeniz gerekir.

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şim elde edersiniz. Örneğin, programatik olarak belirli varyantları ve bunların testlerini devre dışı bırakabilir veya bir mülkün değerini (ör. minSdk) yalnızca seçilen bir varyant için değiştirebilirsiniz. finalizeDsl() özelliğine benzer şekilde, sağladığınız tüm değerler yapılandırma sırasında çözümlenmeli ve harici girişlere bağlı olmamalıdır. beforeVariants() geri çağırma işleminin yürütülmesi tamamlandıktan sonra VariantBuilder nesneleri değiştirilmemelidir.

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

beforeVariants() geri çağırması isteğe bağlı olarak bir VariantSelector alır. Bu adımı androidComponentsExtension üzerindeki selector() yöntemiyle edinebilirsiniz. Geri çağırma çağrısına katılan bileşenleri adlarına, yapı türlerine veya ürün çeşitlerine göre filtrelemek için bunu kullanabilirsiniz.

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

onVariants()

onVariants() çağrıldığında, AGP tarafından oluşturulacak tüm yapılara zaten karar verilmiş olduğundan bunları artık devre dışı bırakamazsınız. Bununla birlikte, görevler için kullanılan değerlerden bazılarını Variant nesnelerinde Property özellikleri için ayarlayarak değiştirebilirsiniz. Property değerleri yalnızca AGP görevleri yürütüldüğünde çözümleneceğinden bunları dosyalar veya ağ gibi harici girişlerden okuma da dahil gerekli tüm hesaplamaları gerçekleştirecek olan kendi özel görevlerinizden sağlayıcılara güvenle 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 aşağıdakiler gibi birkaç türde oluşturulmuş kaynağa katkıda bulunabilir:

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

Bu kod snippet'i, addStaticSourceDirectory() işlevini kullanarak Java kaynak kümesine ${variant.name} adlı özel kaynak klasörün nasıl ekleneceğini göstermektedir. 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 ayrıntı için addJavaSource tarifine bakın.

Bu kod snippet'i, özel bir görevden oluşturulmuş Android kaynakları içeren bir dizinin res kaynak grubuna nasıl ekleneceğini gösterir. Bu süreç diğer kaynak türleri için de benzer şekilde işler.

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 fazla ayrıntı için addCustomAsset tarifine bakın.

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

AGP, Variant nesnelerindeki basit özellikleri değiştirmenize izin vermenin yanı sıra derleme sırasında üretilen ara ve son yapıları okumanıza veya dönüştürmenize olanak tanıyan bir uzantı mekanizması da içerir. Örneğin, analiz etmek üzere son, birleştirilmiş AndroidManifest.xml dosya içeriğini özel bir Task içinde okuyabilir veya içeriğinin tamamını özel Task ürününüz 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 belgelerinde bulabilirsiniz. Her yapı türünün bilinmesi yararlı olan belirli özellikleri vardır:

Kardinalite

Bir Artifact öğesinin kardinalitesi, FileSystemLocation örnek sayısını veya yapı türündeki dosya ya da dizin sayısını temsil eder. Bir yapının üst sınıfını kontrol ederek kardinalitesi hakkında bilgi edinebilirsiniz: Tek bir FileSystemLocation değerine sahip yapılar Artifact.Single, birden fazla FileSystemLocation örneğine sahip yapılar Artifact.Multiple alt sınıfı olur.

FileSystemLocation tür

Artifact öğesinin, parametreleştirilmiş FileSystemLocation türüne (RegularFile veya Directory olabilir) bakarak dosya veya dizinleri temsil edip etmediğini kontrol edebilirsiniz.

Desteklenen işlemler

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

  • Transformable: Artifact öğesinin, üzerinde rastgele dönüşümler gerçekleştiren ve yeni bir Artifact sürümü oluşturan Task için girdi olarak kullanılmasına izin verir.
  • Appendable: Yalnızca Artifact.Multiple alt sınıfları olan yapılar için geçerlidir. Bu, Artifact öğesinin eklenebileceği anlamına gelir. Bir başka deyişle, özel bir Task, bu Artifact türü için mevcut listeye eklenecek yeni örnekler oluşturabilir.
  • Replaceable: Yalnızca Artifact.Single alt sınıfları olan yapılar için geçerlidir. Değiştirilebilir bir Artifact, Task çıkışı olarak üretilen tamamen yeni bir örnek ile değiştirilebilir.

Yapı değiştiren üç işleme ek olarak, her yapı bir get() (veya getAll()) işlemini destekler. Bu işlem, (üzerindeki tüm işlemler bittikten sonra) yapının son sürümüyle bir Provider döndürür.

Birden fazla eklenti, onVariants() geri çağırma işlevinden ardışık düzene istediğiniz sayıda işlem ekleyebilir. Ayrıca AGP, tüm görevlerin doğru zamanda çalışması ve yapıların doğru şekilde üretilip güncellenmesi için bunların düzgün bir şekilde zincirlenmesini sağlar. Bu, bir işlem bunları ekleyerek, değiştirerek veya dönüştürerek herhangi bir çıktıyı değiştirdiğinde, bir sonraki işlemde bu yapıların güncellenmiş sürümünü giriş olarak görür ve bu şekilde devam eder.

Kayıt işlemlerine giriş noktası Artifacts sınıfıdır. Aşağıdaki kod snippet'i, onVariants() geri çağırmadaki Variant nesnesinde bulunan bir özellikten Artifacts örneğine nasıl erişebileceğinizi gösterir.

Daha sonra, özel TaskProvider öğenizi bir TaskBasedOperation nesnesi (1) almak için iletebilir ve bunu wiredWith* yöntemlerinden (2) birini kullanarak giriş ve çıkışlarını bağlamak için kullanabilirsiniz.

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

Son olarak, Artifact türünü, karşılığında aldığınız *OperationRequest nesnesinde seçilen işlemi temsil eden bir yönteme geçirirsiniz; örneğin, toAppendTo(), toTransform() veya 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)
}

Bu örnekte MERGED_MANIFEST bir SingleArtifact ve bir RegularFile'dir. Bu nedenle, giriş için tek bir RegularFileProperty referansı ve çıkış için tek bir RegularFileProperty referansı kabul eden wiredWithFiles yöntemini kullanmamız gerekir. TaskBasedOperation sınıfında, diğer Artifact kardinalite ve FileSystemLocation türü kombinasyonlarında ç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ılavuzunun aşağıdaki bölümlerini okumanızı öneririz: