Thiết lập Trình bổ trợ thư viện Android cho Gradle cho KMP

Trình bổ trợ Gradle com.android.kotlin.multiplatform.library là công cụ được hỗ trợ chính thức để thêm mục tiêu Android vào mô-đun thư viện Kotlin Multiplatform (KMP). Việc này giúp đơn giản hoá cấu hình dự án, cải thiện hiệu suất bản dựng và mang đến khả năng tích hợp tốt hơn với Android Studio.

Phương pháp trước đây hiện không được dùng nữa, thay vào đó là trình bổ trợ (còn được gọi là trình bổ trợ Android-KMP). JetBrains sẽ không còn hỗ trợ việc tiếp tục sử dụng trình bổ trợ com.android.library cho KMP và trình bổ trợ này sẽ không được hưởng lợi từ các bản cập nhật và cải tiến trong tương lai.

Để áp dụng trình bổ trợ này, hãy tham khảo phần Áp dụng trình bổ trợ Android-KMP. Nếu bạn cần di chuyển từ các API cũ, hãy xem Hướng dẫn di chuyển.

Các tính năng và điểm khác biệt chính

Trình bổ trợ Android-KMP được thiết kế riêng cho các dự án KMP và khác với trình bổ trợ com.android.library tiêu chuẩn ở một số khía cạnh chính:

  • Cấu trúc một biến thể: Trình bổ trợ này sử dụng một biến thể duy nhất, loại bỏ việc hỗ trợ các phiên bản sản phẩm và loại bản dựng, giúp đơn giản hoá cấu hình và nâng cao hiệu suất bản dựng.

  • Được tối ưu hoá cho KMP: Trình bổ trợ này được thiết kế cho các thư viện KMP, tập trung vào mã Kotlin dùng chung và khả năng tương tác, bỏ qua việc hỗ trợ các bản dựng gốc dành riêng cho Android, AIDL và RenderScript.

  • Kiểm thử bị tắt theo mặc định: Cả kiểm thử đơn vị và kiểm thử thiết bị (đo lường) đều bị tắt theo mặc định để tăng tốc độ bản dựng. Bạn có thể bật các tính năng này nếu cần.

  • Không có tiện ích Android cấp cao nhất: Cấu hình được xử lý bằng khối androidLibrary trong DSL KMP của Gradle, duy trì cấu trúc dự án KMP nhất quán. Không có khối tiện ích android cấp cao nhất.

  • Chọn tham gia biên dịch Java: Theo mặc định, tính năng biên dịch Java sẽ bị tắt. Hãy sử dụng withJava() trong khối androidLibrary để bật tính năng này. Điều này giúp cải thiện thời gian tạo bản dựng khi không cần biên dịch Java.

Lợi ích của trình bổ trợ thư viện Android-KMP

Trình bổ trợ Android-KMP mang lại những lợi ích sau cho các dự án KMP:

  • Cải thiện hiệu suất và độ ổn định của bản dựng: Được thiết kế để tối ưu hoá tốc độ bản dựng và tăng cường độ ổn định trong các dự án KMP. Việc tập trung vào quy trình KMP góp phần tạo nên quy trình xây dựng hiệu quả và đáng tin cậy hơn.

  • Tích hợp IDE nâng cao: Tính năng này giúp hoàn thành mã, điều hướng, gỡ lỗi và mang lại trải nghiệm tổng thể tốt hơn cho nhà phát triển khi làm việc với các thư viện KMP Android.

  • Đơn giản hoá cấu hình dự án: Trình bổ trợ này đơn giản hoá cấu hình cho các dự án KMP bằng cách loại bỏ các điểm phức tạp dành riêng cho Android, chẳng hạn như các biến thể bản dựng. Điều này giúp các tệp bản dựng trở nên gọn gàng và dễ duy trì hơn. Trước đây, việc sử dụng trình bổ trợ com.android.library trong dự án KMP có thể tạo ra các tên tập hợp nguồn gây nhầm lẫn, chẳng hạn như androidAndroidTest. Quy ước đặt tên này ít trực quan hơn đối với những nhà phát triển quen thuộc với cấu trúc dự án KMP tiêu chuẩn.

Điều kiện tiên quyết

Để sử dụng trình bổ trợ com.android.kotlin.multiplatform.library, dự án của bạn phải được định cấu hình với các phiên bản tối thiểu sau đây trở lên:

  • Trình bổ trợ Android cho Gradle (AGP): 8.10.0
  • Trình bổ trợ Kotlin cho Gradle (KGP): 2.0.0

Áp dụng trình bổ trợ Android-KMP cho một mô-đun hiện có

Để áp dụng trình bổ trợ Android-KMP cho một mô-đun thư viện KMP hiện có, hãy làm theo các bước sau:

  1. Khai báo trình bổ trợ trong danh mục phiên bản. Mở tệp TOML của danh mục phiên bản (thường là gradle/libs.versions.toml) rồi thêm phần định nghĩa trình bổ trợ:

    # 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. Áp dụng khai báo trình bổ trợ trong tệp bản dựng gốc. Mở tệp build.gradle.kts nằm trong thư mục gốc của dự án. Thêm các bí danh trình bổ trợ vào khối plugins bằng cách sử dụng apply false. Điều này giúp mọi dự án con đều có thể sử dụng các bí danh trình bổ trợ mà không cần áp dụng logic trình bổ trợ cho chính dự án gốc.

    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. Áp dụng trình bổ trợ trong tệp bản dựng mô-đun thư viện KMP. Mở tệp build.gradle.kts trong mô-đun thư viện KMP và áp dụng trình bổ trợ ở đầu tệp trong khối 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. Định cấu hình mục tiêu KMP của Android. Định cấu hình khối Kotlin Multiplatform (kotlin) để xác định mục tiêu Android. Trong khối kotlin, hãy chỉ định mục tiêu Android bằng cách sử dụng androidLibrary:

    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. Áp dụng thay đổi. Sau khi áp dụng trình bổ trợ và định cấu hình khối kotlin, hãy đồng bộ hoá dự án Gradle để áp dụng các thay đổi.

Di chuyển từ trình bổ trợ cũ

Hướng dẫn này giúp bạn di chuyển từ trình bổ trợ com.android.library cũ sang trình bổ trợ com.android.kotlin.multiplatform.library.

1. Khai báo phần phụ thuộc

Một tác vụ thường gặp là khai báo các phần phụ thuộc cho các nhóm tài nguyên dành riêng cho Android. Không giống như khối dependencies chung được dùng trước đây, trình bổ trợ mới yêu cầu bạn phải đặt rõ ràng những khối này trong khối sourceSets.

Android-KMP

Trình bổ trợ mới này giúp cấu trúc rõ ràng hơn bằng cách nhóm các phần phụ thuộc Android trong nhóm tài nguyên androidMain. Ngoài nhóm tài nguyên chính, còn có 2 nhóm tài nguyên kiểm thử được tạo theo yêu cầu: androidDeviceTestandroidHostTest (hãy xem phần định cấu hình các bài kiểm thử trên thiết bị và máy chủ lưu trữ để biết thêm thông tin).

// 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")
        }
    }
}

Các tập hợp nguồn có các bản biên dịch Kotlin tương ứng có tên là main, deviceTesthostTest. Bạn có thể định cấu hình các tập hợp nguồn và quá trình biên dịch trong tập lệnh bản dựng như sau:

// build.gradle.kts

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

Trình bổ trợ cũ

Với trình bổ trợ cũ, bạn có thể khai báo các phần phụ thuộc dành riêng cho Android trong khối phần phụ thuộc cấp cao nhất. Đôi khi, điều này có thể gây nhầm lẫn trong mô-đun đa nền tảng.

// 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. Bật tài nguyên Android

Theo mặc định, trình bổ trợ mới không bật tính năng hỗ trợ Tài nguyên Android (thư mục res) để tối ưu hoá hiệu suất bản dựng. Bạn phải chọn sử dụng các tính năng này. Thay đổi này giúp đảm bảo rằng những dự án không yêu cầu tài nguyên dành riêng cho Android sẽ không bị ảnh hưởng bởi chi phí xây dựng liên quan.

Android-KMP

Bạn phải bật rõ ràng quy trình xử lý tài nguyên Android. Các tài nguyên phải được đặt trong 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

Trình bổ trợ cũ

Tính năng xử lý tài nguyên được bật theo mặc định. Bạn có thể thêm ngay một thư mục res trong src/main và bắt đầu thêm các đối tượng có thể vẽ, giá trị XML, v.v.

// 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. Định cấu hình các kiểm thử trên máy chủ lưu trữ và thiết bị

Một thay đổi đáng kể trong trình bổ trợ mới là các kiểm thử phía máy chủ lưu trữ (đơn vị) và phía thiết bị (được đo lường) trên Android sẽ bị tắt theo mặc định. Bạn phải chọn tạo các cấu hình và nhóm tài nguyên kiểm thử một cách rõ ràng, trong khi trình bổ trợ cũ sẽ tự động tạo các cấu hình và nhóm tài nguyên này.

Mô hình chọn sử dụng này giúp xác minh rằng dự án của bạn vẫn tinh gọn và chỉ bao gồm logic bản dựng cũng như các nhóm tài nguyên mà bạn đang sử dụng.

Android-KMP

Trong trình bổ trợ mới, bạn có thể bật và định cấu hình các kiểm thử bên trong khối kotlin.android. Điều này giúp việc thiết lập trở nên rõ ràng hơn và tránh tạo các thành phần kiểm thử không dùng đến. Nhóm tài nguyên test sẽ trở thành androidHostTestandroidTest sẽ trở thành 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

Trình bổ trợ cũ

Theo mặc định, trình bổ trợ com.android.library sẽ tạo các nhóm tài nguyên testandroidTest. Bạn sẽ định cấu hình hành vi của các thành phần này bên trong khối android, thường là bằng cách dùng DSL testOptions.

// 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. Bật tính năng biên dịch nguồn Java

Nếu thư viện KMP của bạn cần biên dịch các nguồn Java cho mục tiêu Android, bạn phải bật rõ ràng chức năng này bằng trình bổ trợ mới. Xin lưu ý rằng thao tác này cho phép biên dịch các tệp Java nằm ngay trong dự án của bạn, chứ không phải cho các phần phụ thuộc của dự án. Phương thức đặt phiên bản mục tiêu JVM của trình biên dịch Java và Kotlin cũng thay đổi.

Android-KMP

Bạn phải chọn biên dịch Java bằng cách gọi withJava(). Mục tiêu JVM hiện được định cấu hình ngay bên trong khối kotlin { androidLibrary {} } để có một chế độ thiết lập hợp nhất hơn. Việc thiết lập jvmTarget ở đây sẽ áp dụng cho cả quá trình biên dịch Kotlin và Java cho mục tiêu Android.

// 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

Trình bổ trợ cũ

Chế độ biên dịch Java được bật theo mặc định. Mục tiêu JVM cho cả nguồn Java và Kotlin được đặt trong khối android bằng 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. Tương tác với các biến thể bản dựng bằng cách sử dụng androidComponents

Tiện ích androidComponents vẫn có sẵn để tương tác với các cấu phần phần mềm bản dựng theo phương thức lập trình. Mặc dù phần lớn API Variant vẫn giữ nguyên, nhưng giao diện AndroidKotlinMultiplatformVariant mới sẽ bị hạn chế hơn vì trình bổ trợ chỉ tạo ra một biến thể duy nhất.

Do đó, các thuộc tính liên quan đến loại bản dựng và phiên bản sản phẩm sẽ không còn có trên đối tượng biến thể nữa.

Android-KMP

Khối onVariants hiện lặp lại trên một biến thể duy nhất. Bạn vẫn có thể truy cập vào các thuộc tính chung như nameartifacts, nhưng không thể truy cập vào các thuộc tính dành riêng cho loại bản dựng.

// build.gradle.kts

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

Trình bổ trợ cũ

Với nhiều biến thể, bạn có thể truy cập vào các thuộc tính dành riêng cho loại bản dựng để định cấu hình các tác vụ.

// build.gradle.kts

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

6. Chọn các biến thể của phần phụ thuộc thư viện Android

Thư viện KMP của bạn tạo ra một biến thể duy nhất cho Android. Tuy nhiên, bạn có thể phụ thuộc vào một thư viện Android tiêu chuẩn (com.android.library) có nhiều biến thể (ví dụ: free/paid phiên bản sản phẩm). Kiểm soát cách dự án của bạn chọn một biến thể từ phần phụ thuộc đó là một yêu cầu phổ biến.

Android-KMP

Trình bổ trợ mới này tập trung và làm rõ logic này trong khối kotlin.android.localDependencySelection. Điều này giúp bạn biết rõ hơn những biến thể của các phần phụ thuộc bên ngoài sẽ được chọn cho thư viện KMP một biến thể.

// 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"))
      }
    }
  }
}

Trình bổ trợ cũ

Bạn đã định cấu hình các chiến lược chọn phần phụ thuộc bên trong các khối buildTypes and productFlavors. Điều này thường liên quan đến việc sử dụng missingDimensionStrategy để cung cấp một nhóm phiên bản mặc định cho một phương diện mà thư viện của bạn không có, hoặc matchingFallbacks trong một nhóm phiên bản cụ thể để xác định thứ tự tìm kiếm.

Hãy tham khảo bài viết Giải quyết lỗi so khớp để biết thêm thông tin chi tiết về cách sử dụng API.

Tài liệu tham khảo về Plugin API

Trình bổ trợ mới có một nền tảng API khác với com.android.library. Để biết thông tin chi tiết về DSL và giao diện mới, hãy xem tài liệu tham khảo về API: