הגדרה של Android Gradle Library Plugin ל-KMP

פלאגין Gradle‏ com.android.kotlin.multiplatform.library הוא הכלי הנתמך באופן רשמי להוספת יעד Android למודול ספרייה של Kotlin Multiplatform‏ (KMP). הוא מפשט את הגדרת הפרויקט, משפר את ביצועי הבנייה ומציע שילוב טוב יותר עם Android Studio.

הגישה הקודמת הוצאה משימוש, ועכשיו מומלץ להשתמש בפלאגין, שנקרא גם פלאגין Android-KMP. המשך השימוש בתוסף com.android.library ל-KMP לא ייתמך יותר על ידי JetBrains ולא ייהנה מעדכונים ושיפורים עתידיים.

כדי להחיל את הפלאגין הזה, אפשר לעיין בקטע החלת הפלאגין Android-KMP. אם אתם צריכים לבצע מיגרציה מממשקי API מדור קודם, כדאי לעיין במדריך המיגרציה.

תכונות עיקריות והבדלים

התוסף Android-KMP מותאם במיוחד לפרויקטים של KMP, והוא שונה מהתוסף הרגיל com.android.library בכמה היבטים מרכזיים:

  • ארכיטקטורה של וריאנט יחיד: התוסף משתמש בווריאנט יחיד, ומסיר את התמיכה בטעמי מוצר ובסוגי build, מה שמפשט את ההגדרה ומשפר את ביצועי ה-build.

  • אופטימיזציה ל-KMP: הפלאגין מיועד לספריות KMP, ומתמקד בקוד Kotlin משותף וביכולת פעולה הדדית, ללא תמיכה ב-AIDL, ב-RenderScript וב-builds מקוריים ספציפיים ל-Android.

  • בדיקות שמושבתות כברירת מחדל: גם בדיקות יחידה וגם בדיקות מכשיר (instrumentation) מושבתות כברירת מחדל כדי לשפר את מהירות הבנייה. אפשר להפעיל אותם אם צריך.

  • אין תוסף Android ברמה העליונה: ההגדרה מתבצעת באמצעות בלוק androidLibrary ב-Gradle KMP DSL, ושומרת על מבנה עקבי של פרויקט KMP. אין חסימה של התוסף android ברמה העליונה.

  • הסכמה לשימוש בהידור Java: הידור Java מושבת כברירת מחדל. כדי להפעיל את האפשרות, משתמשים ב-withJava() בבלוק androidLibrary. כך משפרים את זמני ה-build כשאין צורך בהידור של Java.

היתרונות של הפלאגין של ספריית Android-KMP

התוסף Android-KMP מספק את היתרונות הבאים לפרויקטים של KMP:

  • שיפור הביצועים והיציבות של ה-build: הוא מתוכנן למהירויות build אופטימליות וליציבות משופרת בפרויקטים של KMP. ההתמקדות שלו בתהליכי עבודה של KMP תורמת לתהליך בנייה יעיל ואמין יותר.

  • שילוב משופר של IDE: הוא מספק השלמת קוד, ניווט, ניפוי באגים וחוויית פיתוח משופרים באופן כללי כשעובדים עם ספריות KMP Android.

  • הגדרה פשוטה יותר של פרויקטים: הפלאגין מפשט את ההגדרה של פרויקטים ב-KMP על ידי הסרת מורכבויות ספציפיות ל-Android, כמו וריאציות של build. כך קובצי ה-build יהיו נקיים יותר וקל יותר לתחזק אותם. בעבר, שימוש בתוסף com.android.library בפרויקט KMP יכול היה ליצור שמות מבלבלים של קבוצות מקור, כמו androidAndroidTest. מוסכמת השמות הזו הייתה פחות אינטואיטיבית למפתחים שמכירים את מבני הפרויקטים הרגילים של KMP.

דרישות מוקדמות

כדי להשתמש בפלאגין com.android.kotlin.multiplatform.library, הפרויקט צריך להיות מוגדר עם הגרסאות המינימליות הבאות או גרסאות מתקדמות יותר:

  • Android Gradle Plugin (AGP): ‏ 8.10.0
  • Kotlin Gradle Plugin (KGP): ‏ 2.0.0

החלת הפלאגין Android-KMP על מודול קיים

כדי להחיל את הפלאגין Android-KMP על מודול ספרייה קיים של KMP, צריך לבצע את השלבים הבאים:

  1. הצהרה על יישומי פלאגין בקטלוג הגרסאות. פותחים את קובץ ה-TOML של קטלוג הגרסאות (בדרך כלל gradle/libs.versions.toml) ומוסיפים את הקטע [plugins]:

    # To check the version number of the latest Kotlin release, go to
    # https://kotlinlang.org/docs/releases.html
    
    [versions]
    androidGradlePlugin = "8.12.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. החלת הפלאגין בקובץ build של מודול בספריית 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. הצהרה על יחסי תלות

משימה נפוצה היא הצהרה על יחסי תלות עבור קבוצות של קבצים ספציפיים ל-Android. בתוסף החדש, צריך למקם את הפקודות האלה במפורש בתוך הבלוק sourceSets, בניגוד לבלוק הכללי dependencies ששימש בעבר.

Android-KMP

הפלאגין החדש מקדם מבנה נקי יותר על ידי קיבוץ של יחסי תלות ב-Android בתוך קבוצת המקור androidMain. בנוסף לסט המקורות הראשי, יש שני סטים של מקורות לבדיקה, שנוצרים לפי דרישה: 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

פלאגין מדור קודם

עיבוד המשאבים הופעל כברירת מחדל. אפשר להוסיף מייד ספרייה ב-ressrc/main ולהתחיל להוסיף קבצים מסוג XML drawables, ערכים וכו'.

// 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-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, בדרך כלל באמצעות ה-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. הפעלת קומפילציה של מקור 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. אינטראקציה עם וריאציות של build באמצעות androidComponents

התוסף androidComponents עדיין זמין לאינטראקציה עם ארטיפקטים של build באופן פרוגרמטי. רוב הפונקציות של Variant API נשארו ללא שינוי, אבל הממשק החדש של AndroidKotlinMultiplatformVariant מוגבל יותר כי הפלאגין יוצר רק וריאציה אחת.

לכן, מאפיינים שקשורים לסוגי build ולטעמי מוצרים כבר לא זמינים באובייקט variant.

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. בחירת וריאציות של יחסי תלות בספריית 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 זמין במאמר פתרון שגיאות התאמה.

מאמרי עזרה על Plugin API

לפלאגין החדש יש משטח API שונה מזה של com.android.library. למידע מפורט על ה-DSL והממשקים החדשים, אפשר לעיין בהפניות ל-API: