ตั้งค่าปลั๊กอินไลบรารี Android Gradle สำหรับ KMP

com.android.kotlin.multiplatform.libraryปลั๊กอิน Gradle เป็นเครื่องมือที่ได้รับการสนับสนุนอย่างเป็นทางการ สำหรับการเพิ่มเป้าหมาย Android ลงในโมดูลไลบรารี Kotlin Multiplatform (KMP) ซึ่งช่วยลดความซับซ้อนในการกำหนดค่าโปรเจ็กต์ ปรับปรุง ประสิทธิภาพของบิลด์ และผสานรวมกับ Android Studio ได้ดียิ่งขึ้น

ตอนนี้เราเลิกใช้แนวทางก่อนหน้านี้แล้วและแนะนำให้ใช้ปลั๊กอินแทน ซึ่งเราเรียกอีกอย่างว่าปลั๊กอิน Android-KMP JetBrains จะไม่รองรับการใช้com.android.library ปลั๊กอินสำหรับ KMP อีกต่อไป และคุณจะไม่ได้รับประโยชน์จากการอัปเดตและการปรับปรุงในอนาคต

หากต้องการใช้ปลั๊กอินนี้ โปรดดูส่วนใช้ปลั๊กอิน Android-KMP หากต้องการย้ายข้อมูลจาก API เดิม โปรดดูคำแนะนำ ในการย้ายข้อมูล

ฟีเจอร์หลักและความแตกต่าง

ปลั๊กอิน Android-KMP ได้รับการปรับแต่งมาสำหรับโปรเจ็กต์ KMP โดยเฉพาะ และแตกต่างจากปลั๊กอิน com.android.library มาตรฐานในหลายๆ ด้านที่สำคัญ ดังนี้

  • สถาปัตยกรรมแบบตัวแปรเดียว: ปลั๊กอินใช้ตัวแปรเดียว ซึ่งจะนำการรองรับ รสชาติของผลิตภัณฑ์และประเภทบิลด์ออก ซึ่งจะช่วยลดความซับซ้อนในการกำหนดค่า และเพิ่มประสิทธิภาพการบิลด์

  • เพิ่มประสิทธิภาพสำหรับ KMP: ปลั๊กอินได้รับการออกแบบมาสำหรับไลบรารี KMP โดยเน้นที่ โค้ด Kotlin ที่ใช้ร่วมกันและความสามารถในการทำงานร่วมกัน โดยไม่รองรับ บิลด์แบบเนทีฟเฉพาะ Android, AIDL และ RenderScript

  • การทดสอบที่ปิดใช้โดยค่าเริ่มต้น: ทั้งการทดสอบหน่วยและการทดสอบอุปกรณ์ (การวัด) จะปิดใช้โดยค่าเริ่มต้นเพื่อเพิ่มความเร็วในการสร้าง คุณสามารถเปิดใช้ได้หากจำเป็น

  • ไม่มีส่วนขยาย Android ระดับบนสุด: การกำหนดค่าจะได้รับการจัดการด้วยบล็อก androidLibrary ภายใน KMP DSL ของ Gradle ซึ่งจะรักษาโครงสร้างโปรเจ็กต์ KMP ที่สอดคล้องกัน ไม่มีการบล็อกส่วนขยาย android ระดับบนสุด

  • เลือกใช้การคอมไพล์ Java: ระบบจะปิดใช้การคอมไพล์ Java โดยค่าเริ่มต้น ใช้ withJava() ในบล็อก androidLibrary เพื่อเปิดใช้ ซึ่งจะช่วยปรับปรุงเวลาบิลด์ เมื่อไม่จำเป็นต้องคอมไพล์ Java

ประโยชน์ของปลั๊กอินไลบรารี Android-KMP

ปลั๊กอิน Android-KMP มีประโยชน์ต่อไปนี้สำหรับโปรเจ็กต์ KMP

  • ปรับปรุงประสิทธิภาพและความเสถียรของการบิลด์: ออกแบบมาเพื่อความเร็วในการบิลด์ที่เพิ่มประสิทธิภาพและความเสถียรที่ดียิ่งขึ้นภายในโปรเจ็กต์ KMP การมุ่งเน้นที่เวิร์กโฟลว์ KMP ช่วยให้กระบวนการบิลด์มีประสิทธิภาพและเชื่อถือได้มากขึ้น

  • การผสานรวม IDE ที่ได้รับการปรับปรุง: ช่วยให้การเติมโค้ด การนำทาง การแก้ไขข้อบกพร่อง และประสบการณ์โดยรวมของนักพัฒนาซอฟต์แวร์ดีขึ้นเมื่อทำงานกับ ไลบรารี KMP Android

  • การกำหนดค่าโปรเจ็กต์ที่ง่ายขึ้น: ปลั๊กอินช่วยลดความซับซ้อนในการกำหนดค่า สำหรับโปรเจ็กต์ KMP โดยการนำความซับซ้อนเฉพาะของ Android เช่น ตัวแปรบิลด์ ออก ซึ่งจะทำให้ไฟล์บิลด์สะอาดและดูแลรักษาง่ายขึ้น ก่อนหน้านี้ การใช้ปลั๊กอิน com.android.library ในโปรเจ็กต์ KMP อาจสร้างชื่อชุดแหล่งข้อมูลที่ทำให้สับสน เช่น androidAndroidTest รูปแบบการตั้งชื่อนี้ ไม่ค่อยเป็นที่เข้าใจสำหรับนักพัฒนาซอฟต์แวร์ที่คุ้นเคยกับโครงสร้างโปรเจ็กต์ KMP มาตรฐาน

สิ่งที่ต้องมีก่อน

หากต้องการใช้ปลั๊กอิน com.android.kotlin.multiplatform.library คุณต้องกำหนดค่าโปรเจ็กต์ให้มีเวอร์ชันขั้นต่ำต่อไปนี้หรือสูงกว่า

  • ปลั๊กอิน Android Gradle (AGP): 8.10.0
  • ปลั๊กอิน Gradle ของ Kotlin (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ที่อยู่ในไดเรกทอรีรากของโปรเจ็กต์ เพิ่มอีเมลแทนของปลั๊กอินลงในบล็อก plugins โดยใช้ apply false ซึ่งจะทำให้ นามแฝงของปลั๊กอินพร้อมใช้งานกับโปรเจ็กต์ย่อยทั้งหมดโดยไม่ต้องใช้ตรรกะของปลั๊กอิน กับโปรเจ็กต์รูทเอง

    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 เปิดไฟล์ build.gradle.kts ในโมดูลไลบรารี KMP แล้วใช้ปลั๊กอินที่ด้านบนของไฟล์ภายในบล็อก 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. กำหนดค่าเป้าหมาย KMP ของ Android กำหนดค่าบล็อก Kotlin Multiplatform (kotlin) เพื่อกำหนดเป้าหมาย Android ภายในkotlin ให้ระบุ เป้าหมาย Android โดยใช้ 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. ใช้การเปลี่ยนแปลง หลังจากใช้ปลั๊กอินและกำหนดค่าkotlin บล็อกแล้ว ให้ซิงค์โปรเจ็กต์ Gradle เพื่อใช้การเปลี่ยนแปลง

ย้ายข้อมูลจากปลั๊กอินเดิม

คู่มือนี้จะช่วยคุณย้ายข้อมูลจากปลั๊กอิน com.android.library เวอร์ชันเดิมไปยังปลั๊กอิน com.android.kotlin.multiplatform.library

1. การประกาศทรัพยากร Dependency

งานทั่วไปคือการประกาศการขึ้นต่อกันสำหรับชุดแหล่งที่มาเฉพาะของ Android ปลั๊กอินใหม่กำหนดให้ต้องวางรายการเหล่านี้ไว้ภายในบล็อก sourceSets อย่างชัดเจน ซึ่งแตกต่างจากบล็อก dependencies ทั่วไปที่ใช้ก่อนหน้านี้

Android-KMP

ปลั๊กอินใหม่นี้ช่วยให้โครงสร้างสะอาดขึ้นด้วยการจัดกลุ่มการอ้างอิง Android ภายในandroidMainชุดแหล่งที่มา นอกจากชุดแหล่งข้อมูลหลักแล้ว ยังมีชุดแหล่งข้อมูลทดสอบ 2 ชุดซึ่งสร้างขึ้นตามคำขอ androidDeviceTest และ androidHostTest (ดูข้อมูลเพิ่มเติมได้ที่การกำหนดค่าการทดสอบโฮสต์และอุปกรณ์)

// 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 ที่เกี่ยวข้องชื่อ main, deviceTest และ hostTest คุณกำหนดค่าชุดแหล่งที่มาและการคอมไพล์ได้ใน สคริปต์บิลด์ดังนี้

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

ปลั๊กอินเดิม

ระบบจะเปิดใช้การประมวลผลทรัพยากรโดยค่าเริ่มต้น คุณสามารถเพิ่มไดเรกทอรี res ใน src/main ได้ทันที และเริ่มเพิ่ม Drawable, ค่า 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 และการทดสอบฝั่งอุปกรณ์ (Instrumented) จะปิดใช้โดยค่าเริ่มต้น คุณต้องเลือกใช้โดยชัดแจ้ง เพื่อสร้างชุดแหล่งข้อมูลและการกำหนดค่าการทดสอบ ในขณะที่ปลั๊กอินเวอร์ชันเก่า จะสร้างชุดแหล่งข้อมูลและการกำหนดค่าการทดสอบโดยอัตโนมัติ

โมเดลการเลือกใช้นี้ช่วยยืนยันว่าโปรเจ็กต์ของคุณยังคงมีขนาดเล็กและมีเฉพาะตรรกะการสร้างและชุดแหล่งข้อมูลที่คุณใช้งานอยู่เท่านั้น

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 ระบบจะสร้างชุดแหล่งข้อมูล test และ androidTest โดยค่าเริ่มต้น คุณจะกำหนดค่าลักษณะการทำงานของบล็อกภายใน 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 ต้องคอมไพล์แหล่งที่มาของ Java สำหรับเป้าหมาย Android คุณ ต้องเปิดใช้ฟังก์ชันนี้อย่างชัดเจนด้วยปลั๊กอินใหม่ โปรดทราบว่าการดำเนินการนี้จะ เปิดใช้การคอมไพล์สำหรับไฟล์ Java ที่อยู่ในโปรเจ็กต์โดยตรง ไม่ใช่สำหรับ การอ้างอิง นอกจากนี้ วิธีตั้งค่าเวอร์ชันเป้าหมาย JVM ของคอมไพเลอร์ Java และ Kotlin ก็จะเปลี่ยนไปด้วย

Android-KMP

คุณต้องเลือกใช้การคอมไพล์ Java โดยโทรหา withJava() ตอนนี้ได้กำหนดค่าเป้าหมาย JVM ไว้ภายในบล็อก kotlin { androidLibrary {} } โดยตรง เพื่อให้การตั้งค่าเป็นไปในทิศทางเดียวกันมากขึ้น การตั้งค่า jvmTarget ที่นี่จะมีผลกับการคอมไพล์ทั้ง Kotlin และ Java สำหรับเป้าหมาย 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

ปลั๊กอินเดิม

ระบบจะเปิดใช้การคอมไพล์ Java โดยค่าเริ่มต้น เป้าหมาย JVM สำหรับทั้งแหล่งที่มาของ Java และ Kotlin ได้รับการตั้งค่าในบล็อก 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บล็อกจะวนซ้ำตัวแปรเดียว คุณยังคงเข้าถึงพร็อพเพอร์ตี้ทั่วไป เช่น name และ artifacts ได้ แต่จะเข้าถึงพร็อพเพอร์ตี้ที่เฉพาะเจาะจงประเภทบิลด์ไม่ได้

// build.gradle.kts

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

ปลั๊กอินเดิม

ตัวแปรหลายรายการช่วยให้คุณเข้าถึงพร็อพเพอร์ตี้เฉพาะประเภทบิลด์เพื่อ กำหนดค่างานได้

// build.gradle.kts

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

6. เลือกตัวแปรของทรัพยากร Dependency ของไลบรารี Android

ไลบรารี KMP จะสร้างตัวแปรเดียวสำหรับ Android อย่างไรก็ตาม คุณอาจ ต้องใช้ไลบรารี Android มาตรฐาน (com.android.library) ที่มีหลาย รูปแบบ (เช่น free/paid รสชาติของผลิตภัณฑ์) การควบคุมวิธีที่โปรเจ็กต์ เลือกตัวแปรจาก Dependency นั้นเป็นข้อกำหนดทั่วไป

Android-KMP

ปลั๊กอินใหม่จะรวมและอธิบายตรรกะนี้ไว้ภายในบล็อก kotlin.android.localDependencySelection ซึ่งจะช่วยให้เห็นได้ชัดเจนยิ่งขึ้นว่า ระบบจะเลือกตัวแปรใดของทรัพยากร Dependency ภายนอกสำหรับ ไลบรารี 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 Surface ที่แตกต่างจาก com.android.library ดูข้อมูลโดยละเอียดเกี่ยวกับ DSL และอินเทอร์เฟซใหม่ได้ที่การอ้างอิง API