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 birbirine bağlama 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şlevselliğini genişletmesi için uzantı noktaları içerir. AGP'nin önceki sürümlerinde, resmi API'ler dahili uygulamalardan net bir şekilde ayrılmamıştı. AGP, 7.0 sürümünden itibaren 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: Herkese açık kullanım için tasarlanmamıştır.
  • Geliştirme aşamasında: Herkese açık olarak kullanılabilir ancak son sürüm değildir. Bu nedenle, son sürümde geriye dönük uyumlu olmayabilir.
  • Herkese açık: Herkesin kullanımına açık ve kararlı
  • Desteği sonlandırıldı: Artık desteklenmiyor ve yeni API'lerle değiştirildi.

Kullanımdan kaldırma politikası

AGP, eski API'lerin desteğinin sonlandırılması ve bunların yeni, kararlı API'ler ve yeni bir alana özgü dil (DSL) ile değiştirilmesiyle gelişiyor. Bu evrim, birden fazla AGP sürümünü kapsayacak. Bu konu hakkında daha fazla bilgiyi AGP API/DSL geçiş zaman çizelgesinde bulabilirsiniz.

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

Yaygın derleme özelleştirmelerinde kullanılan yeni API'lerin örneklerini görmek için Android Gradle eklentisi tariflerine göz atın. Sık karşılaşılan derleme özelleştirmeleriyle ilgili örnekler sunar. Yeni API'ler hakkında daha fazla bilgiyi referans belgelerimizde bulabilirsiniz.

Gradle derleme temelleri

Bu kılavuzda Gradle derleme sisteminin tamamı ele alınmamaktadır. Ancak, API'lerimize entegre olmanıza yardımcı olacak minimum gerekli kavramlar kümesini kapsar ve daha fazla bilgi için ana Gradle dokümanlarına bağlantılar içerir.

Gradle'ın işleyişiyle ilgili temel bilgilere (ör. projeleri yapılandırma, derleme dosyalarını düzenleme, eklentileri uygulama ve görevleri çalıştırma) sahip olduğunuzu varsayıyoruz. AGP ile ilgili olarak Gradle'ın temelleri hakkında bilgi edinmek için Derlemenizi yapılandırma başlıklı makaleyi incelemenizi öneririz. Gradle eklentilerini özelleştirme ile ilgili genel çerçeve hakkında bilgi edinmek için Özel Gradle Eklentileri Geliştirme başlıklı makaleyi inceleyin.

Gradle tembel türleri sözlüğü

Gradle,"tembel" davranan veya ağır hesaplamaları ya da Task oluşturmayı derlemenin sonraki aşamalarına ertelemeye 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ütme işleminde yer alan temel Gradle türleri ve bunların temel yöntemleri yer almaktadır.

Provider<T>
T türünde bir değer (burada "T" herhangi bir tür anlamına gelir) sağlar. 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 (burada "S" başka bir tür anlamına gelir) dönüştürülebilir. get()'nın yapılandırma aşamasında asla çağrılmaması gerektiğini unutmayın.
  • map(): Lambda kabul eder ve S türünde Provider oluşturur, Provider<S>. map() işlevinin lambda bağımsız değişkeni T değerini alır ve S değerini üretir. Lambda hemen yürütülmez. Bunun yerine, yürütülmesi, sonuçta elde edilen Provider<S> üzerinde get() çağrıldığında ertelenir ve tüm zincir tembel hale gelir.
  • flatMap(): Lambda işlevini de kabul eder ve Provider<S> değerini üretir ancak lambda işlevi T değerini alır ve Provider<S> değerini üretir (doğrudan S değerini üretmek yerine). S yapılandırma sırasında belirlenemediğinde ve yalnızca Provider<S> elde edebildiğinizde flatMap() işlevini kullanın. Pratik olarak konuşmak gerekirse map() kullandığınızda Provider<Provider<S>> sonuç türü elde ettiyseniz bunun nedeni muhtemelen flatMap() kullanmanız gerektiğidir.
  • zip(): İki Provider örneğini birleştirerek yeni bir Provider oluşturmanıza olanak tanır. Bu yeni Provider'ün değeri, iki giriş Providers örneğindeki değerleri birleştiren bir işlev kullanılarak hesaplanır.
Property<T>
Uygulandığı için Provider<T> türünde bir değer de sağlar.T Salt okunur olan Provider<T>'nın aksine Property<T> için de bir değer ayarlayabilirsiniz. Bunu yapmanın iki yolu vardır:
  • T türünde bir değer, kullanılabilir olduğunda doğrudan ayarlanır. Bu işlem için ertelenmiş hesaplamalar gerekmez.
  • 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 oluşturulur.
TaskProvider
UygulamaProvider<Task> TaskProvider oluşturmak için tasks.register() kullanın. Görevlerin yalnızca gerektiğinde geç başlatıldığından emin olmak için tasks.create() kullanmayın. Task oluşturulmadan önce flatMap() kullanarak Task çıkışlarına erişebilirsiniz. Bu, çıkışları diğer Task örneklerine giriş olarak kullanmak istediğinizde faydalı olabilir.

Sağlayıcılar ve bunların dönüştürme yöntemleri, görevlerin giriş ve çıkışlarını geç yükleme şeklinde ayarlamak için gereklidir. Bu sayede, tüm görevleri önceden oluşturup değerleri çözmeye gerek kalmaz.

Sağlayıcılar, görev bağımlılığı bilgilerini de taşır. Task çıkışını dönüştürerek Provider oluşturduğunuzda bu Task, Provider'nın örtülü bağımlılığı haline gelir ve Provider'nın değeri çözümlendiğinde (ör. başka bir Task tarafından gerektiğinde) oluşturulup çalıştırılır.

Aşağıda, GitVersionTask ve ManifestProducerTask olmak üzere iki görevin kaydedildiği, Task örneklerinin oluşturulmasının ise gerçekten ihtiyaç duyulana kadar ertelendiği bir örnek verilmiştir. ManifestProducerTask giriş değeri, GitVersionTask çıkışından elde edilen bir Provider olarak ayarlanır. Bu nedenle ManifestProducerTask, GitVersionTask'ye örtülü olarak 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 komutunu çalıştırdığınızda veya ManifestProducerTask komutunun çıkışı başka bir göreve bağlanıp değeri gerekli hale geldiğinde Gradle çağrısı kapsamında gerçekleşebilir.

Girişleri kullanan ve/veya çıkışlar üreten özel görevler yazsanız da AGP, kendi görevlerine doğrudan herkese açık erişim sunmaz. Bunlar, sürümler arasında değişebilen bir uygulama ayrıntısıdır. Bunun yerine AGP, okuyup dönüştürebileceğiniz Variant API'yi ve görevlerinin çıkışına (veya build artifacts) erişimi sunar. Daha fazla bilgi için bu belgedeki Varyant API'si, Yapılar ve Görevler bölümüne bakın.

Gradle derleme aşamaları

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

Bu optimizasyonlardan bazılarını uygulamak için Gradle komut dosyaları ve eklentileri, her bir ayrı Gradle derleme aşamasında (başlatma, yapılandırma ve yürütme) katı kurallara uymalıdır. 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ü rehberinde 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 geç kaydetmek için kullanılmalıdır.

Yapılandırma aşaması, hangi görevin çalıştırılması istendiğinden bağımsız olarak her zaman çalıştığından bu aşamayı yalın tutmak ve hesaplamaların, derleme komut dosyalarının kendisi dışındaki girişlere bağlı olmasını kısıtlamak özellikle önemlidir. Yani harici programlar yürütmemeli, ağdan okuma yapmamalı veya uygun Task örnekleri olarak yürütme aşamasına ertelenebilecek uzun hesaplamalar yapmamalısınız.

özel dikkat gösterilmesi halinde geçerlidir.

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şaretlenmiş 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() işlevini çağırarak geç yüklenen sağlayıcıları çözmenize izin verilir. Lazy sağlayıcıları bu şekilde çözmek, sağlayıcıda bulunan görev bağımlılığı bilgilerini izleyen bir dizi map() veya flatMap() çağrısını başlatır. Görevler, gerekli değerleri oluşturmak için geç çalıştırılır.

Varyant API'si, yapılar ve görevler

Variant API, Android Gradle eklentisindeki bir uzantı mekanizmasıdır. Bu mekanizma, Android derlemesini etkileyen ve normalde derleme yapılandırma dosyalarında DSL kullanılarak ayarlanan çeşitli seçenekleri değiştirmenize olanak tanır. Variant API, derleme tarafından oluşturulan ara ve nihai yapıtlara (ör. sınıf dosyaları, birleştirilmiş manifest veya APK/AAB dosyaları) da erişmenizi sağlar.

Android derleme akışı ve uzantı noktaları

AGP ile etkileşimde bulunurken, normal Gradle yaşam döngüsü geri çağırmalarını (ör. afterEvaluate()) kaydetmek 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ğırmalar ya da bağımlılıklar eklemekten kaçınmanız gerekir.

AGP, Task örneklerini oluşturup yürütmek için aşağıdaki adımları tamamlar. Bu örnekler de derleme yapılarını üretir. Variant Nesne oluşturmayla ilgili temel adımların ardından, derleme kapsamında oluşturulan belirli nesnelerde değişiklik yapmanıza olanak tanıyan geri çağırmalar gelir. Tüm geri çağırmaların yapılandırma aşamasında (bu sayfada açıklanmıştır) gerçekleştiğini ve hızlı çalışması gerektiğini, karmaşık işlemlerin ise yürütme aşamasında uygun Task örneklerine ertelenmesi gerektiğini unutmayın.

  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 nesnelerinin bileşen (varyant) oluşturma için kilitlenmeden önce değiştirilmesine olanak tanıyan geri çağırma. VariantBuilder nesneleri, DSL nesnelerinde bulunan verilere göre oluşturulur.

  3. DSL kilitleme: DSL artık kilitli ve 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ıtlar üzerinde değişiklik yapılmasına yine de izin verilir.

  5. Varyant oluşturma: Oluşturulacak bileşen ve yapıt listesi artık kesinleşti ve değiştirilemez.

  6. onVariants(): Bu geri çağırmada, oluşturulan Variant nesnelerine erişebilir ve içerdikleri Property değerleri için değerler veya sağlayıcılar ayarlayabilirsiniz. Bu değerler geç hesaplanır.

  7. Varyant kilitleme: Varyant nesneleri artık kilitlendi ve değişiklik yapılamıyor.

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

AGP, finalizeDsl(), beforeVariants() ve onVariants() için geri çağırmaları 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 bildirim temelli yapılandırma için tutmanızı ve tüm özel zorunlu mantığı buildSrc veya harici eklentilere taşımanızı öneririz. Projenizde eklenti oluşturmayı öğrenmek için Gradle tarifleri GitHub deposundaki buildSrc örneklere 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ılabilen geri çağırmalara ve eklentinizin her birinde destekleyebileceği kullanım alanlarına daha yakından bakalım:

finalizeDsl(callback: (DslExtensionT) -> Unit)

Bu geri çağırmada, derleme dosyalarındaki android bloğundan alınan bilgilerin ayrıştırılmasıyla oluşturulan DSL nesnelerine erişebilir ve bunları 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 dayanmaması gerektiğini unutmayın. Bu geri çağırma işlemi yürütmeyi tamamladıktan sonra DSL nesneleri artık kullanılamaz ve bunlara yönelik referansları tutmamalı ya da 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()

Oluşturma işleminin bu aşamasında, oluşturulacak varyantları ve bunların özelliklerini belirleyen VariantBuilder nesnelerine erişebilirsiniz. Örneğin, belirli varyantları ve bunların testlerini programatik olarak devre dışı bırakabilir veya bir özelliğin değerini (ör. minSdk) yalnızca seçilen bir varyant için değiştirebilirsiniz. finalizeDsl()'ya benzer şekilde, sağladığınız tüm değerler yapılandırma sırasında çözülmeli ve harici girişlere bağlı olmamalıdır. VariantBuilder nesneleri, beforeVariants() geri çağırma işlevi yürütülmeyi tamamladıktan sonra değiştirilmemelidir.

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

beforeVariants() geri çağırması isteğe bağlı olarak VariantSelector alır. Bu değeri androidComponentsExtension üzerindeki selector() yöntemiyle elde edebilirsiniz. Geri çağırma işlemine katılan bileşenleri adlarına, derleme türlerine veya ürün aromalarına göre filtrelemek için kullanabilirsiniz.

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

onVariants()

onVariants() çağrıldığında, AGP tarafından oluşturulacak tüm yapılar zaten belirlenmiş olduğundan bunları artık devre dışı bırakamazsınız. Ancak, görevler için kullanılan değerlerden bazılarını Variant nesnelerindeki 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 olmak üzere gerekli tüm hesaplamaları yapacak kendi özel görevlerinizdeki 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 ekleme

Eklentiniz aşağıdaki gibi birkaç türde oluşturulmuş kaynak sağlayabilir:

Ekleyebileceğiniz kaynakların tam listesi için Kaynaklar API'si'ne bakın.

Bu kod snippet'i, addStaticSourceDirectory() işlevini kullanarak Java kaynak kümesine ${variant.name} adlı özel bir kaynak klasörünün nasıl ekleneceğini gösterir. Android araç zinciri daha sonra 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'i, özel bir görevden oluşturulan Android kaynaklarını içeren bir dizinin res kaynak kümesine nasıl ekleneceğini gösterir. Diğer kaynak türleri için de benzer bir süreç uygulanır.

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

Yapılara erişme ve bunları değiştirme

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

Şu anda desteklenen yapıtların listesini Artifact sınıfının referans belgelerinde bulabilirsiniz. Her yapay nesne türünün bilinmesi gereken belirli özellikleri vardır:

Kardinalite

Bir Artifact öğesinin kardinalitesi, FileSystemLocation örneklerinin sayısını veya yapıt türündeki dosya ya da dizinlerin sayısını gösterir. Bir yapının kardinalitesi hakkında bilgi edinmek için üst sınıfını kontrol edebilirsiniz: Tek bir FileSystemLocation içeren yapılar Artifact.Single sınıfının alt sınıfı olur. Birden fazla FileSystemLocation örneği içeren yapılar ise Artifact.Multiple sınıfının alt sınıfı olur.

FileSystemLocation tür

Bir Artifact öğesinin 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: Artifact öğesinin, üzerinde rastgele dönüşümler gerçekleştiren ve Artifact öğesinin yeni bir sürümünü çıkış olarak veren bir Task öğesine giriş olarak kullanılmasına olanak tanır.
  • Appendable: Yalnızca Artifact.Multiple sınıfının alt sınıfları olan öğeler için geçerlidir. Bu, Artifact öğesine ekleme yapılabileceği anlamına gelir. Yani özel bir Task, bu Artifact türünün yeni örneklerini oluşturabilir ve bu örnekler mevcut listeye eklenir.
  • Replaceable: Yalnızca Artifact.Single sınıfının alt sınıfları olan öğeler için geçerlidir. Değiştirilebilir bir Artifact, Task çıkışı olarak üretilen tamamen yeni bir örnekle değiştirilebilir.

Üç öğe değiştirme işlemine ek olarak her öğe, öğenin son sürümünü içeren bir get() (veya getAll()) işlemini destekler. Bu işlem, öğe üzerindeki tüm işlemler tamamlandıktan sonra gerçekleştirilir.Provider

Birden fazla eklenti, onVariants() geri çağırmasından itibaren işlem hattına herhangi bir sayıda işlem ekleyebilir. AGP, tüm görevlerin doğru zamanda çalışması ve yapıtların doğru şekilde üretilip güncellenmesi için bunların uygun şekilde zincirlenmesini sağlar. Yani bir işlem, çıktıları ekleyerek, değiştirerek veya dönüştürerek değiştirdiğinde sonraki işlem, bu öğelerin güncellenmiş sürümünü giriş olarak görür.

Kayıt işlemlerine giriş noktası Artifacts sınıfıdır. Aşağıdaki kod snippet'inde, onVariants() geri çağırmasında Variant nesnesindeki bir özellikten Artifacts örneğine nasıl erişebileceğiniz gösterilmektedir.

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

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

Son olarak, döndürülen *OperationRequest nesnesinde seçilen işlemi temsil eden bir yönteme Artifact türünü iletirsiniz. Ö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 RegularFile öğesidir. Bu nedenle, giriş için tek bir RegularFileProperty referansını, çıkış için ise tek bir RegularFileProperty referansını kabul eden wiredWithFiles yöntemini kullanmamız gerekir. wiredWith* sınıfında, Artifact kardinalite ve FileSystemLocation türlerinin diğer kombinasyonları için çalışacak başka TaskBasedOperation yöntemler 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: