Bu doküman, eklenti yazarlarına Kotlin Multiplatform (KMP) kurulumunu doğru şekilde algılama, kurulumla etkileşim kurma ve kurulumu yapılandırma konusunda rehberlik eder. KMP projesindeki Android hedefleriyle entegrasyona özellikle odaklanılır. KMP gelişmeye devam ederken KotlinMultiplatformExtension, KotlinTarget türleri ve Android'e özgü entegrasyon arayüzleri gibi uygun kancaları ve API'leri anlamak, çok platformlu bir projede tanımlanan tüm platformlarda sorunsuz bir şekilde çalışan sağlam ve geleceğe hazır araçlar oluşturmak için çok önemlidir.
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 hemen tepki vermek yerine plugins.withId() kullanmak en iyi uygulamadır. Bu reaktif yaklaşım, eklentinizin kullanıcının derleme komut dosyalarında eklentilerin uygulanma sırasına göre kırılgan olmasını engeller.
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 mantığı yalnızca belirli platform türlerine 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 geniş kapsamlı bir şekilde ayrım yapması gerekiyorsa (ör. yalnızca JVM benzeri hedeflerde çalışması) 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 or Android */ }
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, com.android.kotlin.multiplatform.library kullanan projeler için KotlinMultiplatformAndroidLibraryTarget.
KotlinMultiplatformAndroidLibraryTarget API'si AGP 8.8.0'da eklendi. Bu nedenle, eklentinizin tüketicileri daha eski bir AGP sürümünde çalışı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() işaretini kontrol edin.
AndroidPluginVersion.getCurrent() için AGP 7.1 veya sonraki bir sürümün gerektiğini unutmayın.
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.mpp.KotlinAndroidTarget
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 ->
if (target is KotlinAndroidTarget) {
// Old kmp android integration using com.android.library or com.android.application
}
if (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, öncelikle KMP Android hedefi için Kotlin Multiplatform eklentisi tarafından sağlanan Kotlin uzantısı ve AGP tarafından sağlanan Android uzantısıyla etkileşimde bulunur. KMP projesindeki Kotlin uzantısındaki android {} bloğu, KotlinMultiplatformAndroidLibraryExtension'yi de genişleten KotlinMultiplatformAndroidLibraryTarget arayüzüyle temsil edilir.
Bu sayede, hem hedefe özgü hem de Android'e özgü 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
}
}
}
}
Diğer Android eklentilerinin (ör. com.android.library veya com.android.application) aksine, KMP Android eklentisi ana DSL uzantısını proje düzeyinde kaydetmez. Bu özellik, yalnızca çok platformlu kurulumunuzda tanımlanan belirli Android hedefi için geçerli olduğundan emin olmak amacıyla KMP hedef hiyerarşisi içinde yer alır.
Derlemeleri ve kaynak kümelerini işleme
Eklentilerin genellikle yalnızca hedefle değil, daha ayrıntılı bir düzeyde, özellikle de derleme düzeyinde çalışması gerekir. KotlinMultiplatformAndroidLibraryTarget, KotlinMultiplatformAndroidCompilation örnekleri (ör. main, hostTest, deviceTest) içerir. Her derleme, Kotlin kaynak kümeleriyle ilişkilendirilir. Eklentiler, kaynak eklemek, bağımlılıkları yönetmek veya derleme görevlerini yapılandırmak için bunlarla etkileşimde bulunabilir.
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 ->
}
}
}
}
}
}
Test derlemelerini kural eklentilerinde yapılandırma
Bir kural eklentisinde test derlemeleri (ör. targetSdk enstrümanlı testler için) için varsayılan değerleri yapılandırırken withDeviceTest { } veya withHostTest { } gibi etkinleştirici yöntemleri kullanmaktan kaçınmalısınız. Bu yöntemlerin erken çağrılması, kural eklentisini uygulayan her modül için karşılık gelen Android test varyantlarının ve derlemelerinin oluşturulmasını tetikler. Bu durum uygun olmayabilir. Ayrıca, bu yöntemler ayarları hassaslaştırmak için belirli bir modülde ikinci kez çağrılamaz. Aksi takdirde, derlemenin zaten oluşturulduğunu belirten bir hata verilir.
Bunun yerine, derleme kapsayıcısında reaktif bir configureEach blok kullanmanızı öneririz. Bu, yalnızca bir modül test derlemesini açıkça etkinleştirdiğinde geçerli olan varsayılan yapılandırmalar sağlamanıza olanak tanır:
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 {
targetSdk { version = release(34) }
}
}
}
}
}
Bu kalıp, kural eklentinizin tembel kalmasını sağlar ve varsayılanlarla çakışmadan testlerini etkinleştirmek ve daha fazla özelleştirmek için tek tek modüllerin withDeviceTest { }'yı çağırmasına olanak tanır.
Variant API ile etkileşim kurma
Geç aşamada yapılandırma, yapı erişimi (manifestler veya bayt kodu gibi) ya da belirli bileşenleri etkinleştirme veya devre dışı bırakma olanağı gerektiren görevler için Android Variant API'yi kullanmanız gerekir. KMP projelerinde uzantı türü KotlinMultiplatformAndroidComponentsExtension'dır.
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 }
}
}
}
}
Son varyant nesnesine (KotlinMultiplatformAndroidVariant) erişmek için onVariants kullanın. Burada, çözümlenmiş özellikleri inceleyebilir veya birleştirilmiş manifest ya da kitaplık sınıfları gibi yapılarda 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.variant.SingleArtifact.MERGED_MANIFEST)
}
}
}
}
Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir.
- Ortamınızı ayarlama
- Projeye KMP modülü ekleme
- KMP için Android Gradle Library Plugin'i ayarlama