Bu kılavuzda, özel bir Gradle eklentisinden Kotlin Multiplatform (KMP) projesindeki Android hedefini nasıl algılayacağınız, yapılandıracağınız ve bu hedefle nasıl etkileşim kuracağınız açıklanmaktadır. Derlemeniz için kural eklentileri yazarken veya KMP projeleri için Gradle eklentileri yayınlarken bu API'leri kullanın.
Bir projenin Kotlin Multiplatform eklentisini kullanıp kullanmadığını kontrol etme
Hataları önlemek ve eklentinizin yalnızca KMP mevcut olduğunda çalışmasını sağlamak için projenin KMP eklentisini kullanıp kullanmadığını kontrol etmeniz gerekir. KMP eklentisinin uygulanmasına tepki vermek için eklentiyi hemen kontrol etmek yerine plugins.withId() kullanmak en iyi uygulamadır. Bu reaktif yaklaşım, eklentinizin kullanıcının derleme komut dosyalarında eklentilerin uygulandığı sıraya karşı hassas olmasını önler.
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.
}
}
}
Modele erişme
Tüm Kotlin Multiplatform yapılandırmalarının giriş noktası KotlinMultiplatformExtension uzantısıdır.
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)
}
}
}
Kotlin Multiplatform hedeflerine tepki verme
Kullanıcının eklediği her hedef için eklentinizi reaktif olarak yapılandırmak üzere targets kapsayıcısını kullanın.
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
}
}
}
}
Hedefe özel mantık uygulama
Eklentinizin yalnızca belirli platform türlerine mantık uygulaması gerekiyorsa yaygın bir yaklaşım, platformType özelliğini kontrol etmektir. Bu, hedefi genel olarak kategorize eden bir enum'dur.
Örneğin, eklentinizin yalnızca genel olarak ayırt etmesi gerekiyorsa (yalnızca JVM benzeri hedeflerde çalışmak gibi) bunu kullanın:
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) */ }
}
}
}
}
}
Android'e özgü ayrıntılar
Tüm Android hedeflerinde platformType.androidJvm göstergesi bulunurken KMP'de, kullanılan Android Gradle eklentisine bağlı olarak iki farklı entegrasyon noktası vardır: com.android.library veya com.android.application kullanan projeler için KotlinAndroidTarget ve com.android.kotlin.multiplatform.library kullanan projeler için KotlinMultiplatformAndroidLibraryTarget.
KotlinMultiplatformAndroidLibraryTarget API'si AGP 8.8.0'da eklendi. Bu nedenle, eklentinizin kullanıcıları AGP'nin daha eski bir sürümünü kullanıyorsa target is KotlinMultiplatformAndroidLibraryTarget kontrolü ClassNotFoundException ile sonuçlanabilir. Bunu güvenli hale getirmek için hedef türünü kontrol etmeden önce AndroidPluginVersion.getCurrent() değerini kontrol edin.
AndroidPluginVersion.getCurrent() için AGP 8.3.1 veya sonraki sürümler gerekir.
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
}
}
}
}
}
Android KMP uzantısına ve özelliklerine erişme
Eklentiniz, Kotlin Multiplatform eklentisi tarafından sağlanan Kotlin uzantısıyla ve KMP Android hedefi için AGP tarafından sağlanan Android uzantısıyla etkileşim kurar. KMP projesindeki Kotlin uzantısının içindeki android {} bloğu, KotlinMultiplatformAndroidLibraryExtension'yi de genişleten KotlinMultiplatformAndroidLibraryTarget arayüzüyle temsil edilir.
Bu sayede, hem hedefe özel hem de Android'e özel DSL özelliklerine bu tek nesne üzerinden erişebilirsiniz.
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
}
}
}
}
KMP Android eklentisi, diğer Android eklentilerinin (ör. com.android.library veya com.android.application) aksine ana DSL uzantısını proje düzeyinde kaydetmez. Bu, çoklu platform kurulumunuzda tanımlanan belirli Android hedefine uygulandığından emin olmak için KMP hedef hiyerarşisinde yer alır.
Derlemeleri ve kaynak gruplarını işleme
Eklentilerin genellikle yalnızca hedef düzeyinde değil, daha ayrıntılı bir düzeyde, özellikle de derleme düzeyinde çalışması gerekir. KotlinMultiplatformAndroidLibraryTarget, KotlinMultiplatformAndroidCompilation örnek (ör. main, hostTest, deviceTest) içerir. Her derleme, Kotlin kaynak gruplarıyla ilişkilendirilir. Eklentiler, kaynak ve bağımlılık eklemek veya derleme görevlerini yapılandırmak için bunlarla etkileşim kurabilir.
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 ->
}
}
}
}
}
}
Kural eklentilerinde test derlemelerini yapılandırma
Bir kural eklentisinde test derlemeleri için varsayılan değerleri (ör. enstrümantasyon testleri için targetSdk) yapılandırırken withDeviceTest { } veya withHostTest { } gibi etkinleştirici yöntemleri kullanmaktan kaçının. Bu yöntemleri çağırmak, kural eklentisini uygulayan her modül için ilgili Android test varyantlarının ve derlemelerinin oluşturulmasını tetikler. Bu durum uygun olmayabilir. Bu yöntemler, ayarları hassaslaştırmak için belirli bir modülde ikinci kez çağrılamaz. Bunun yapılması, derlemenin zaten oluşturulduğunu belirten bir hataya neden olur.
Bunun yerine, derleme kapsayıcısında reaktif bir configureEach bloğu kullanın.
Bu sayede, yalnızca bir modül test derlemesini açıkça etkinleştirdiğinde geçerli olan varsayılan yapılandırmalar sağlayabilirsiniz:
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) }
}
}
}
}
}
Bu kalıp, kural eklentinizin geç yüklenmesini sağlar ve her modülün, varsayılanlarla çakışmadan testlerini etkinleştirmek ve daha fazla özelleştirmek için withDeviceTest { } yöntemini çağırmasına olanak tanır.
Variant API ile etkileşim kurma
Geç aşama yapılandırması, yapı erişimi (ör. manifest dosyaları veya bayt kodu) ya da belirli bileşenleri etkinleştirme veya devre dışı bırakma özelliği gerektiren görevler için Android Variant API'yi kullanmanız gerekir. KMP projelerinde uzantı, KotlinMultiplatformAndroidComponentsExtension türündedir.
KMP Android eklentisi uygulandığında uzantı, proje düzeyinde kaydedilir.
Varyantların veya iç içe yerleştirilmiş test bileşenlerinin (hostTests ve deviceTests) oluşturulmasını kontrol etmek için beforeVariants kullanın. Testleri programatik olarak devre dışı bırakmak veya DSL özelliklerinin değerlerini değiştirmek için doğru yer burasıdır.
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 }
}
}
}
}
Nihai değişken nesnesine (KotlinMultiplatformAndroidVariant) erişmek için onVariants kullanın. Çözümlenen özellikleri inceleyebilir veya birleştirilmiş manifest ya da kitaplık sınıfları gibi yapıtlarda dönüşümleri kaydedebilirsiniz.
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)
}
}
}
}
Sizin için önerilenler
- Not: JavaScript devre dışı bırakıldığında bağlantı metni gösterilir.
- Ortamınızı ayarlama
- Projeye KMP modülü ekleme
- KMP için Android Gradle Kitaplığı Eklentisi'ni ayarlama