Panduan ini menjelaskan cara mendeteksi, berinteraksi dengan, dan mengonfigurasi target Android dalam project Kotlin Multiplatform (KMP) dari plugin Gradle kustom. Gunakan API ini saat menulis plugin konvensi untuk build Anda atau memublikasikan plugin Gradle untuk project KMP.
Memeriksa apakah project menggunakan plugin Kotlin Multiplatform
Untuk menghindari error dan memastikan plugin Anda hanya berjalan saat KMP ada,
Anda harus memeriksa apakah project menggunakan plugin KMP. Sebaiknya gunakan
plugins.withId() untuk bereaksi terhadap plugin KMP yang diterapkan, daripada
langsung memeriksanya. Pendekatan reaktif ini mencegah plugin Anda
menjadi rentan terhadap urutan penerapan plugin dalam skrip build
pengguna.
import org.gradle.api.Plugin
import org.gradle.api.Project
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
// The KMP plugin is applied, you can now configure your KMP integration.
}
}
}
Mengakses model
Titik entri untuk semua konfigurasi Multiplatform Kotlin adalah
ekstensi KotlinMultiplatformExtension.
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
}
}
}
Bereaksi terhadap target Kotlin Multiplatform
Gunakan penampung targets untuk mengonfigurasi plugin secara reaktif untuk setiap target
yang ditambahkan pengguna.
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
kmpExtension.targets.configureEach { target ->
// 'target' is an instance of KotlinTarget
val targetName = target.name // for example, "android", "iosX64", "jvm"
val platformType = target.platformType // for example, androidJvm, jvm, native, js
}
}
}
}
Menerapkan logika khusus target
Jika plugin Anda perlu menerapkan logika hanya ke jenis platform tertentu, pendekatan yang umum
adalah memeriksa properti platformType. Ini adalah enum yang secara luas
mengategorikan target.
Misalnya, gunakan ini jika plugin Anda hanya perlu membedakan secara luas (seperti hanya berjalan pada target seperti JVM):
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
kmpExtension.targets.configureEach { target ->
when (target.platformType) {
KotlinPlatformType.jvm -> { /* Standard JVM */ }
KotlinPlatformType.androidJvm -> { /* Android */ }
KotlinPlatformType.js -> { /* JavaScript */ }
KotlinPlatformType.native -> { /* Any Native (iOS, Linux, Windows, etc.) */ }
KotlinPlatformType.wasm -> { /* WebAssembly */ }
KotlinPlatformType.common -> { /* Metadata target (rarely needs direct plugin interaction) */ }
}
}
}
}
}
Detail khusus Android
Meskipun semua target Android memiliki indikator platformType.androidJvm, KMP memiliki
dua titik integrasi yang berbeda, bergantung pada plugin Android Gradle yang digunakan:
KotlinAndroidTarget untuk project yang menggunakan com.android.library atau
com.android.application, dan KotlinMultiplatformAndroidLibraryTarget untuk
project yang menggunakan com.android.kotlin.multiplatform.library.
KotlinMultiplatformAndroidLibraryTarget API ditambahkan di AGP 8.8.0, jadi jika
konsumen plugin Anda berjalan di versi AGP yang lebih rendah, memeriksa
target is KotlinMultiplatformAndroidLibraryTarget mungkin akan menghasilkan
ClassNotFoundException. Agar aman, periksa
AndroidPluginVersion.getCurrent() sebelum memeriksa jenis penargetan.
AndroidPluginVersion.getCurrent() memerlukan AGP 8.3.1 atau yang lebih tinggi.
import com.android.build.api.AndroidPluginVersion
import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
kmpExtension.targets.configureEach { target ->
if (target is KotlinAndroidTarget) {
// Old kmp android integration using com.android.library or com.android.application
} else if (
// Check platformType first, so AGP classes load only for Android targets
target.platformType == KotlinPlatformType.androidJvm &&
AndroidPluginVersion.getCurrent() >= AndroidPluginVersion(8, 8) &&
target is KotlinMultiplatformAndroidLibraryTarget
) {
// New kmp android integration using com.android.kotlin.multiplatform.library
}
}
}
}
}
Mengakses ekstensi KMP Android dan propertinya
Plugin Anda terutama berinteraksi dengan ekstensi Kotlin yang disediakan
oleh plugin Multiplatform Kotlin dan ekstensi Android yang disediakan oleh AGP
untuk target Android KMP. Blok android {} dalam ekstensi Kotlin
di project KMP diwakili oleh antarmuka
KotlinMultiplatformAndroidLibraryTarget, yang juga memperluas KotlinMultiplatformAndroidLibraryExtension.
Artinya, Anda dapat mengakses properti DSL khusus target dan khusus Android
melalui satu objek ini.
import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("com.android.kotlin.multiplatform.library") {
val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
// Access the Android target, which also serves as the Android-specific DSL extension
kmpExtension.targets.withType(KotlinMultiplatformAndroidLibraryTarget::class.java).configureEach { androidTarget ->
// You can now access properties and methods from both
// KotlinMultiplatformAndroidLibraryTarget and KotlinMultiplatformAndroidLibraryExtension
androidTarget.compileSdk = 34
androidTarget.namespace = "com.example.myplugin.library"
androidTarget.withJava() // enable Java sources
}
}
}
}
Tidak seperti plugin Android lainnya (seperti com.android.library atau
com.android.application), plugin Android KMP tidak mendaftarkan ekstensi
DSL utamanya di level project. Plugin ini berada dalam hierarki target KMP
untuk memastikan plugin hanya berlaku untuk target Android tertentu yang ditentukan dalam
penyiapan multiplatform Anda.
Menangani kompilasi dan set sumber
Sering kali, plugin perlu bekerja pada tingkat yang lebih terperinci daripada sekadar target,
khususnya pada tingkat kompilasi. KotlinMultiplatformAndroidLibraryTarget berisi
instance KotlinMultiplatformAndroidCompilation (misalnya, main,
hostTest, deviceTest). Setiap kompilasi dikaitkan dengan set sumber
Kotlin. Plugin dapat berinteraksi dengan plugin ini untuk menambahkan sumber, dependensi, atau mengonfigurasi
tugas kompilasi.
import com.android.build.api.dsl.KotlinMultiplatformAndroidCompilation
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("com.android.kotlin.multiplatform.library") {
val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
kmpExtension.targets.configureEach { target ->
target.compilations.configureEach { compilation ->
// standard compilations are usually 'main' and 'test'
// android target has 'main', 'hostTest', 'deviceTest'
val compilationName = compilation.name
// Access the default source set for this compilation
val defaultSourceSet = compilation.defaultSourceSet
// Access the Android-specific compilation DSL
if (compilation is KotlinMultiplatformAndroidCompilation) {
}
// Access and configure the Kotlin compilation task
compilation.compileTaskProvider.configure { compileTask ->
}
}
}
}
}
}
Mengonfigurasi kompilasi pengujian di plugin konvensi
Saat mengonfigurasi nilai default untuk kompilasi pengujian (seperti targetSdk untuk uji instrumentasi) dalam plugin konvensi, hindari penggunaan metode pengaktif seperti withDeviceTest { } atau withHostTest { }. Memanggil metode ini secara langsung akan memicu pembuatan varian pengujian Android dan kompilasi yang sesuai untuk setiap modul yang menerapkan plugin konvensi, yang mungkin tidak sesuai. Metode ini juga tidak dapat dipanggil untuk kedua kalinya dalam modul tertentu untuk menyaring setelan, karena tindakan tersebut akan menampilkan error yang menyatakan bahwa kompilasi telah dibuat.
Sebagai gantinya, gunakan blok configureEach reaktif pada container kompilasi.
Dengan begitu, Anda dapat memberikan konfigurasi default yang hanya berlaku jika dan saat
modul secara eksplisit mengaktifkan kompilasi pengujian:
import com.android.build.api.dsl.KotlinMultiplatformAndroidDeviceTestCompilation
import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("com.android.kotlin.multiplatform.library") {
val kmpExtension =
project.extensions.getByType(KotlinMultiplatformExtension::class.java)
kmpExtension.targets.withType(KotlinMultiplatformAndroidLibraryTarget::class.java)
.configureEach { androidTarget ->
androidTarget.compilations.withType(
KotlinMultiplatformAndroidDeviceTestCompilation::class.java
).configureEach {
it.targetSdk { version = release(34) }
}
}
}
}
}
Pola ini memastikan bahwa plugin konvensi Anda tetap lambat dan memungkinkan
modul individual memanggil withDeviceTest { } untuk mengaktifkan dan menyesuaikan
pengujiannya lebih lanjut tanpa bertentangan dengan setelan default.
Berinteraksi dengan Variant API
Untuk tugas yang memerlukan konfigurasi tahap akhir, akses artefak (seperti
manifes atau byte-code), atau kemampuan untuk mengaktifkan atau menonaktifkan komponen
tertentu, Anda harus menggunakan Android Variant API. Dalam project KMP, ekstensi berjenis KotlinMultiplatformAndroidComponentsExtension.
Ekstensi ini didaftarkan di level project saat plugin Android KMP diterapkan.
Gunakan beforeVariants untuk mengontrol pembuatan varian atau komponen pengujian bertingkatnya (hostTests dan deviceTests). Ini adalah tempat yang tepat untuk
menonaktifkan pengujian secara terprogram atau mengubah nilai properti DSL.
import com.android.build.api.variant.KotlinMultiplatformAndroidComponentsExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("com.android.kotlin.multiplatform.library") {
val androidComponents = project.extensions.findByType(KotlinMultiplatformAndroidComponentsExtension::class.java)
androidComponents?.beforeVariants { variantBuilder ->
// Disable all tests for this module
variantBuilder.hostTests.values.forEach { it.enable = false }
variantBuilder.deviceTests.values.forEach { it.enable = false }
}
}
}
}
Gunakan onVariants untuk mengakses objek varian akhir
(KotlinMultiplatformAndroidVariant). Di sinilah Anda dapat memeriksa properti
yang di-resolve atau mendaftarkan transformasi pada artefak seperti manifes gabungan
atau class library.
import com.android.build.api.variant.KotlinMultiplatformAndroidComponentsExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("com.android.kotlin.multiplatform.library") {
val androidComponents = project.extensions.findByType(KotlinMultiplatformAndroidComponentsExtension::class.java)
androidComponents?.onVariants { variant ->
// 'variant' is a KotlinMultiplatformAndroidVariant
val variantName = variant.name
// Access the artifacts API
val manifest = variant.artifacts.get(com.android.build.api.artifact.SingleArtifact.MERGED_MANIFEST)
}
}
}
}
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Menyiapkan lingkungan Anda
- Menambahkan modul KMP ke project
- Menyiapkan Plugin Library Android Gradle untuk KMP