Tài liệu này cung cấp hướng dẫn cho các tác giả trình bổ trợ về cách phát hiện, tương tác và định cấu hình chính xác chế độ thiết lập Kotlin Multiplatform (KMP), đặc biệt tập trung vào việc tích hợp với các mục tiêu Android trong một dự án KMP. Khi KMP tiếp tục phát triển, việc nắm được các hook và API phù hợp (chẳng hạn như các loại KotlinMultiplatformExtension, KotlinTarget và các giao diện tích hợp dành riêng cho Android) là điều cần thiết để tạo ra các công cụ mạnh mẽ và có khả năng thích ứng với tương lai, hoạt động liền mạch trên tất cả các nền tảng được xác định trong một dự án đa nền tảng.
Kiểm tra xem một dự án có sử dụng trình bổ trợ Kotlin Multiplatform hay không
Để tránh lỗi và đảm bảo rằng trình bổ trợ của bạn chỉ chạy khi có KMP, bạn phải kiểm tra xem dự án có sử dụng trình bổ trợ KMP hay không. Bạn nên sử dụng plugins.withId() để phản ứng với việc áp dụng trình bổ trợ KMP, thay vì kiểm tra ngay. Cách tiếp cận phản ứng này giúp ngăn plugin của bạn bị ảnh hưởng bởi thứ tự mà các plugin được áp dụng trong tập lệnh bản dựng của người dùng.
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.
}
}
}
Truy cập vào mô hình
Điểm truy cập cho tất cả cấu hình Kotlin Multiplatform là tiện ích 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)
}
}
}
React cho các mục tiêu Kotlin Multiplatform
Sử dụng vùng chứa targets để định cấu hình trình bổ trợ một cách phản ứng cho từng mục tiêu mà người dùng thêm.
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
}
}
}
}
Áp dụng logic dành riêng cho mục tiêu
Nếu chỉ cần áp dụng logic cho một số loại nền tảng nhất định, thì cách tiếp cận phổ biến là kiểm tra thuộc tính platformType. Đây là một enum phân loại mục tiêu một cách tổng quát.
Ví dụ: hãy sử dụng cách này nếu trình bổ trợ của bạn chỉ cần phân biệt một cách rộng rãi (ví dụ: chỉ chạy trên các mục tiêu tương tự như 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 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) */ }
}
}
}
}
}
Thông tin cụ thể về Android
Mặc dù tất cả các mục tiêu Android đều có chỉ báo platformType.androidJvm, nhưng KMP có 2 điểm tích hợp riêng biệt tuỳ thuộc vào trình bổ trợ Android cho Gradle được sử dụng: KotlinAndroidTarget cho các dự án sử dụng com.android.library hoặc com.android.application và KotlinMultiplatformAndroidLibraryTarget cho các dự án sử dụng com.android.kotlin.multiplatform.library.
API KotlinMultiplatformAndroidLibraryTarget được thêm vào AGP 8.8.0, vì vậy, nếu người dùng trình bổ trợ của bạn đang chạy trên phiên bản AGP thấp hơn, việc kiểm tra target is KotlinMultiplatformAndroidLibraryTarget có thể dẫn đến ClassNotFoundException. Để đảm bảo an toàn, hãy kiểm tra AndroidPluginVersion.getCurrent() trước khi kiểm tra loại mục tiêu.
Xin lưu ý rằng AndroidPluginVersion.getCurrent() yêu cầu AGP 7.1 trở lê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
}
}
}
}
}
Truy cập vào tiện ích KMP Android và các thuộc tính của tiện ích này
Trình bổ trợ của bạn chủ yếu sẽ tương tác với tiện ích Kotlin do trình bổ trợ Kotlin Multiplatform cung cấp và tiện ích Android do AGP cung cấp cho mục tiêu Android KMP. Khối android {} trong tiện ích Kotlin trong dự án KMP được biểu thị bằng giao diện KotlinMultiplatformAndroidLibraryTarget, cũng mở rộng KotlinMultiplatformAndroidLibraryExtension.
Điều này có nghĩa là bạn có thể truy cập cả các thuộc tính DSL dành riêng cho mục tiêu và dành riêng cho Android thông qua một đối tượng duy nhất này.
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
}
}
}
}
Không giống như các trình bổ trợ Android khác (chẳng hạn như com.android.library hoặc com.android.application), trình bổ trợ KMP Android không đăng ký tiện ích DSL chính ở cấp dự án. Nó nằm trong hệ thống phân cấp mục tiêu KMP để đảm bảo rằng nó chỉ áp dụng cho mục tiêu Android cụ thể được xác định trong chế độ thiết lập đa nền tảng.
Xử lý các bản biên dịch và nhóm tài nguyên
Thông thường, các trình bổ trợ cần hoạt động ở cấp độ chi tiết hơn so với chỉ mục tiêu – cụ thể là chúng cần hoạt động ở cấp độ biên dịch. KotlinMultiplatformAndroidLibraryTarget chứa các thực thể KotlinMultiplatformAndroidCompilation (ví dụ: main, hostTest, deviceTest). Mỗi lần biên dịch đều được liên kết với các tập hợp nguồn Kotlin. Các trình bổ trợ có thể tương tác với những trình bổ trợ này để thêm các nguồn, phần phụ thuộc hoặc định cấu hình các tác vụ biên dịch.
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 ->
}
}
}
}
}
}
Định cấu hình các bản biên dịch kiểm thử trong trình bổ trợ quy ước
Khi định cấu hình các giá trị mặc định cho quá trình biên dịch kiểm thử (chẳng hạn như targetSdk cho kiểm thử đo lường) trong một trình bổ trợ quy ước, bạn nên tránh sử dụng các phương thức hỗ trợ như withDeviceTest { } hoặc withHostTest { }. Việc gọi các phương thức này sẽ kích hoạt quá trình tạo các biến thể kiểm thử và bản biên dịch Android tương ứng cho mọi mô-đun áp dụng trình bổ trợ quy ước, điều này có thể không phù hợp. Hơn nữa, bạn không thể gọi các phương thức này lần thứ hai trong một mô-đun cụ thể để tinh chỉnh các chế độ cài đặt, vì làm như vậy sẽ gây ra lỗi cho biết quá trình biên dịch đã được tạo.
Thay vào đó, bạn nên sử dụng khối configureEach phản ứng trên vùng chứa các bản tổng hợp. Điều này cho phép bạn cung cấp các cấu hình mặc định chỉ áp dụng khi một mô-đun bật rõ ràng quá trình biên dịch kiểm thử:
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) }
}
}
}
}
}
Mẫu này đảm bảo rằng trình bổ trợ quy ước của bạn vẫn ở trạng thái trì hoãn và cho phép các mô-đun riêng lẻ gọi withDeviceTest { } để bật và tuỳ chỉnh thêm các kiểm thử của chúng mà không xung đột với các giá trị mặc định.
Tương tác với Variant API
Đối với những tác vụ yêu cầu cấu hình giai đoạn cuối, quyền truy cập vào cấu phần phần mềm (chẳng hạn như tệp kê khai hoặc mã byte) hoặc khả năng bật/tắt các thành phần cụ thể, bạn phải sử dụng Android Variant API. Trong các dự án KMP, tiện ích này thuộc loại KotlinMultiplatformAndroidComponentsExtension.
Tiện ích này được đăng ký ở cấp dự án khi trình bổ trợ Android KMP được áp dụng.
Sử dụng beforeVariants để kiểm soát việc tạo các biến thể hoặc thành phần kiểm thử lồng nhau của các biến thể đó (hostTests và deviceTests). Đây là vị trí phù hợp để tắt các kiểm thử theo phương thức lập trình hoặc thay đổi giá trị của các thuộc tính 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 }
}
}
}
}
Sử dụng onVariants để truy cập vào đối tượng biến thể cuối cùng (KotlinMultiplatformAndroidVariant). Đây là nơi bạn có thể kiểm tra các thuộc tính đã phân giải hoặc đăng ký các phép biến đổi trên các cấu phần phần mềm như tệp kê khai hợp nhất hoặc các lớp thư viện.
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)
}
}
}
}
Đề xuất cho bạn
- Lưu ý: văn bản có đường liên kết sẽ hiện khi JavaScript tắt
- Thiết lập môi trường
- Thêm mô-đun KMP vào dự án
- Thiết lập Trình bổ trợ thư viện Android cho Gradle cho KMP