為 KMP 設定 Android Gradle 程式庫外掛程式

com.android.kotlin.multiplatform.library Gradle 外掛程式是官方支援的工具,可將 Android 目標新增至 Kotlin Multiplatform (KMP) 程式庫模組。可簡化專案設定、提升建構效能,並與 Android Studio 整合。

我們已淘汰先前的做法,改用外掛程式 (也稱為 Android-KMP 外掛程式)。JetBrains 不再支援繼續使用 KMP 外掛程式,且該外掛程式不會再有更新和改良。com.android.library

如要套用此外掛程式,請參閱「套用 Android-KMP 外掛程式」一節。如要從舊版 API 遷移,請參閱遷移指南

主要功能與差異

Android-KMP 外掛程式專為 KMP 專案量身打造,與標準 com.android.library 外掛程式在幾個重要方面有所不同:

  • 單一變數架構:外掛程式會使用單一變數,移除對變種版本和建構類型的支援,簡化設定並提升建構效能。

  • 專為 KMP 最佳化:這個外掛程式專為 KMP 程式庫設計,著重於共用的 Kotlin 程式碼和互通性,省略對 Android 專用原生建構作業、AIDL 和 RenderScript 的支援。

  • 預設停用測試:為提升建構速度,單元測試和裝置 (檢測設備) 測試預設都會停用。如有需要,可以啟用這些功能。

  • 沒有頂層 Android 擴充功能:設定是在 Gradle KMP DSL 內的 androidLibrary 區塊中處理,可維持一致的 KMP 專案結構。沒有頂層 android 擴充功能區塊。

  • 選擇啟用 Java 編譯:Java 編譯功能預設為停用。請在 androidLibrary 區塊中使用 withJava() 啟用這項功能。這樣一來,就不需要進行 Java 編譯,可縮短建構時間。

Android-KMP 程式庫外掛程式的優點

Android-KMP 外掛程式可為 KMP 專案提供下列優點:

  • 提升建構效能和穩定性:專為最佳化建構速度而設計,可提升 KMP 專案的穩定性。這項功能著重於 KMP 工作流程,有助於提升建構程序的效率和可靠性。

  • 強化 IDE 整合:使用 KMP Android 程式庫時,可提供更優質的程式碼完成、導覽、偵錯和整體開發人員體驗。

  • 簡化專案設定:這個外掛程式可移除建構變數等 Android 專屬的複雜項目,簡化 KMP 專案的設定。這樣一來,建構檔案就會更乾淨,也更容易維護。先前在 KMP 專案中使用 com.android.library 外掛程式時,可能會建立令人困惑的來源集名稱,例如 androidAndroidTest。對於熟悉標準 KMP 專案結構的開發人員來說,這個命名慣例較不直覺。

必要條件

如要使用 com.android.kotlin.multiplatform.library 外掛程式,專案必須設定為下列最低版本或更新版本:

  • Android Gradle 外掛程式 (AGP):8.10.0
  • Kotlin Gradle 外掛程式 (KGP):2.0.0

將 Android-KMP 外掛程式套用至現有模組

如要將 Android-KMP 外掛程式套用至現有的 KMP 程式庫模組,請按照下列步驟操作:

  1. 在版本目錄中聲明外掛程式。開啟版本目錄 TOML 檔案 (通常為 gradle/libs.versions.toml),然後新增外掛程式定義區段:

    # To check the version number of the latest Kotlin release, go to
    # https://kotlinlang.org/docs/releases.html
    
    [versions]
    androidGradlePlugin = "8.13.0"
    kotlin = "KOTLIN_VERSION"
    
    [plugins]
    kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
    android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "androidGradlePlugin" }
    
  2. 在根層級建構檔案中套用外掛程式宣告。開啟專案根目錄中的 build.gradle.kts 檔案。使用 apply false 將外掛程式別名新增至 plugins 區塊。這樣一來,所有子專案都能使用外掛程式別名,不必將外掛程式邏輯套用至根專案本身。

    Kotlin

    // Root build.gradle.kts file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform) apply false
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library) apply false
    }

    Groovy

    // Root build.gradle file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform) apply false
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library) apply false
    }
  3. 在 KMP 程式庫模組建構檔案中套用外掛程式。開啟 KMP 程式庫模組中的 build.gradle.kts 檔案,並在 plugins 區塊內的檔案頂端套用外掛程式:

    Kotlin

    // Module-specific build.gradle.kts file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform)
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library)
    }

    Groovy

    // Module-specific build.gradle file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform)
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library)
    }
  4. 設定 Android KMP 目標。設定 Kotlin Multiplatform 區塊 (kotlin) 來定義 Android 目標。在 kotlin 區塊中,使用 androidLibrary 指定 Android 目標:

    Kotlin

    kotlin {
       androidLibrary {
           namespace = "com.example.kmpfirstlib"
           compileSdk = 33
           minSdk = 24
    
           withJava() // enable java compilation support
           withHostTestBuilder {}.configure {}
           withDeviceTestBuilder {
               sourceSetTreeName = "test"
           }
    
           compilations.configureEach {
               compilerOptions.configure {
                   jvmTarget.set(
                       org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
                   )
               }
           }
       }
    
       sourceSets {
           androidMain {
               dependencies {
                   // Add Android-specific dependencies here
               }
           }
           getByName("androidHostTest") {
               dependencies {
               }
           }
    
           getByName("androidDeviceTest") {
               dependencies {
               }
           }
       }
       // ... other targets (JVM, iOS, etc.) ...
    }

    Groovy

    kotlin {
       androidLibrary {
           namespace = "com.example.kmpfirstlib"
           compileSdk = 33
           minSdk = 24
    
           withJava() // enable java compilation support
           withHostTestBuilder {}.configure {}
           withDeviceTestBuilder {
               it.sourceSetTreeName = "test"
           }
    
           compilations.configureEach {
               compilerOptions.options.jvmTarget.set(
                   org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
               )
           }
       }
    
       sourceSets {
           androidMain {
               dependencies {
               }
           }
           androidHostTest {
               dependencies {
               }
           }
           androidDeviceTest {
               dependencies {
               }
           }
       }
       // ... other targets (JVM, iOS, etc.) ...
    }
  5. 套用變更。套用外掛程式並設定 kotlin 區塊後,請同步處理 Gradle 專案以套用變更。

從舊版外掛程式遷移

本指南可協助您從舊版 com.android.library 外掛程式遷移至 com.android.kotlin.multiplatform.library 外掛程式。

1. 宣告依附元件

常見工作是為 Android 專屬來源集宣告依附元件。新外掛程式要求這些項目必須明確放在 sourceSets 區塊中,不像先前使用的通用 dependencies 區塊。

Android-KMP

新外掛程式會將 Android 依附元件歸類在 androidMain 來源集中,讓結構更簡潔。除了主要來源集,還有兩個測試來源集 (視需要建立):androidDeviceTestandroidHostTest (詳情請參閱設定主機和裝置測試)。

// build.gradle.kts

kotlin {
    android {}
    //... other targets

    sourceSets {
        commonMain.dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
        }

        // Dependencies are now scoped to the specific Android source set
        androidMain.dependencies {
            implementation("androidx.appcompat:appcompat:1.7.0")
            implementation("com.google.android.material:material:1.11.0")
        }
    }
}

來源集有對應的 Kotlin 編譯,分別命名為 maindeviceTesthostTest。您可以在建構指令碼中設定來源集和編譯,如下所示:

// build.gradle.kts

kotlin {
    androidLibrary {
        compilations.getByName("deviceTest") {
            kotlinOptions.languageVersion = "2.0"
        }
    }
}

舊版外掛程式

使用舊版外掛程式時,您可以在頂層依附元件區塊中宣告 Android 專屬依附元件,這有時可能會造成多平台模組混淆。

// build.gradle.kts

kotlin {
  androidTarget()
  //... other targets
}

// Dependencies for all source sets were often mixed in one block
dependencies {
  // Common dependencies
  commonMainImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")

  // Android-specific dependencies
  implementation("androidx.appcompat:appcompat:1.7.0")
  implementation("com.google.android.material:material:1.11.0")
}

2. 啟用 Android 資源

為提升建構效能,新版外掛程式預設不會啟用 Android 資源 (res 資料夾) 支援功能。您必須選擇採用,才能使用這些功能。這項變更可確保不需要 Android 專屬資源的專案,不會受到相關建構負擔的影響。

Android-KMP

您必須明確啟用 Android 資源處理功能。資源應放在 src/androidMain/res 中。

// build.gradle.kts

kotlin {
  android {
    // ...
    // Enable Android resource processing
    androidResources {
      enable = true
    }
  }
}

// Project Structure
// └── src
//     └── androidMain
//         └── res
//             ├── values
//             │   └── strings.xml
//             └── drawable
//                 └── icon.xml

舊版外掛程式

資源處理功能預設為啟用。您可以立即在 src/main 中新增 res 目錄,並開始新增 XML 可繪項目、值等。

// build.gradle.kts

android {
    namespace = "com.example.library"
    compileSdk = 34
    // No extra configuration was needed to enable resources.
}

// Project Structure
// └── src
//     └── main
//         └── res
//             ├── values
//             │   └── strings.xml
//             └── drawable
//                 └── icon.xml

3. 設定主機和裝置測試

新外掛程式的一項重大變更,就是預設會停用 Android 主機端 (單元) 和裝置端 (檢測設備) 測試。您必須明確選擇加入,才能建立測試來源集和設定,而舊版外掛程式會自動建立這些項目。

這個選擇加入模式有助於確保專案保持精簡,只包含您主動使用的建構邏輯和來源集。

Android-KMP

在新外掛程式中,您可以在 kotlin.android 區塊內啟用及設定測試。這樣一來,設定會更加明確,且不會建立未使用的測試元件。test 來源集會變成 androidHostTest,而 androidTest 會變成 androidDeviceTest

// build.gradle.kts

kotlin {
  android {
    // ...

    // Opt-in to enable and configure host-side (unit) tests
    withHostTest {
      isIncludeAndroidResources = true
    }

    // Opt-in to enable and configure device-side (instrumented) tests
    withDeviceTest {
      instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
      execution = "ANDROIDX_TEST_ORCHESTRATOR"
    }
  }
}

// Project Structure (After Opt-in)
// └── src
//     ├── androidHostTest
//     └── androidDeviceTest

舊版外掛程式

使用 com.android.library 外掛程式時,系統會預設建立 testandroidTest 來源集。您會在 android 區塊內設定其行為,通常是使用 testOptions DSL。

// build.gradle.kts

android {
  defaultConfig {
    // Runner was configured in defaultConfig
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
  }

  testOptions {
    // Configure unit tests (for the 'test' source set)
    unitTests.isIncludeAndroidResources = true

    // Configure device tests (for the 'androidTest' source set)
    execution = "ANDROIDX_TEST_ORCHESTRATOR"
  }
}

// Project Structure (Defaults)
// └── src
//     ├── test
//     └── androidTest

4. 啟用 Java 來源編譯

如果 KMP 程式庫需要為 Android 目標編譯 Java 來源,您必須使用新外掛程式明確啟用這項功能。請注意,這項設定會啟用專案中 Java 檔案的編譯作業,而非專案的依附元件。設定 Java 和 Kotlin 編譯器 JVM 目標版本的方法也會有所不同。

Android-KMP

您必須呼叫 withJava(),選擇啟用 Java 編譯。現在,JVM 目標直接在 kotlin { androidLibrary {} } 區塊內設定,設定方式更加統一。這裡的 jvmTarget 設定會同時套用至 Android 目標的 Kotlin 和 Java 編譯作業。

// build.gradle.kts

kotlin {
  android {
    //  Opt-in to enable Java source compilation
    withJava()
    // Configure the JVM target for both Kotlin and Java sources
    compilerOptions {
      jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8)
    }
  }
  // ...
}

// Project Structure:
// └── src
//     └── androidMain
//         ├── kotlin
//         │   └── com/example/MyKotlinClass.kt
//         └── java
//             └── com.example/MyJavaClass.java

舊版外掛程式

Java 編譯功能預設為啟用。Java 和 Kotlin 來源的 JVM 目標是在 android 區塊中,使用 compileOptions 設定。

// build.gradle.kts

android {
  // ...
  compileOptions {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
  }
}

kotlin {
  androidTarget {
    compilations.all {
      kotlinOptions.jvmTarget = "1.8"
    }
  }
}

5. 使用 androidComponents 與建構變數互動

您仍可使用 androidComponents 擴充功能,以程式輔助方式與建構構件互動。雖然 Variant API 的大部分內容都維持不變,但由於外掛程式只會產生單一變體,因此新版 AndroidKotlinMultiplatformVariant 介面的限制較多。

因此,與建構類型和變種版本相關的屬性不再適用於變體物件。

Android-KMP

onVariants 區塊現在會疊代單一變數。您仍可存取 nameartifacts 等常見屬性,但無法存取建構類型專屬屬性。

// build.gradle.kts

androidComponents {
  onVariants { variant ->
      val artifacts = variant.artifacts
  }
}

舊版外掛程式

使用多個變體時,您可以存取建構類型專屬的屬性,藉此設定工作。

// build.gradle.kts

androidComponents {
  onVariants(selector().withBuildType("release")) { variant ->
    // ...
  }
}

6. 選取 Android 程式庫依附元件的變體

您的 KMP 程式庫會產生單一 Android 變體。不過,您可能依附於具有多個變數的標準 Android 程式庫 (com.android.library),例如 free/paid 變種版本)。控管專案如何從該依附元件選取變體,是常見的需求。

Android-KMP

新外掛程式會集中處理這項邏輯,並在 kotlin.android.localDependencySelection 區塊中清楚說明。這樣一來,您就能更清楚瞭解單一變數 KMP 程式庫會選取哪些外部依附元件變數。

// build.gradle.kts
kotlin {
  android {
    localDependencySelection {
      // For dependencies with multiple build types, select 'debug' first, and 'release' in case 'debug' is missing
      selectBuildTypeFrom.set(listOf("debug", "release"))

      // For dependencies with a 'type' flavor dimension...
      productFlavorDimension("type") {
        // ...select the 'typeone' flavor.
        selectFrom.set(listOf("typeone"))
      }
    }
  }
}

舊版外掛程式

您在 buildTypes and productFlavors 區塊中設定了依附元件選取策略。這通常需要使用 missingDimensionStrategy 為程式庫沒有的維度提供預設版本,或在特定版本中使用 matchingFallbacks 定義搜尋順序。

如要進一步瞭解 API 用法,請參閱「解決比對錯誤」。

外掛程式 API 參考資料

新外掛程式的 API 介面與 com.android.library 不同。如要詳細瞭解新的 DSL 和介面,請參閱下列 API 參考資料: