הוספת תלויות build

מערכת ה-build של Gradle ב-Android Studio מאפשרת לכם לכלול קבצים בינאריים חיצוניים או מודולים אחרים של ספריות ב-build שלכם כתלויות. יחסי התלות יכולים להיות במחשב שלכם או במאגר מרוחק, וכל יחסי התלות הטרנזיטיביים שהם מצהירים עליהם נכללים גם הם באופן אוטומטי. בדף הזה מוסבר איך להשתמש בתלויות בפרויקט Android, כולל פרטים על התנהגויות והגדרות שספציפיות לפלאגין של Android Gradle‏ (AGP). למדריך מפורט יותר בנושא יחסי תלות ב-Gradle, אפשר לעיין במדריך של Gradle לניהול יחסי תלות, אבל חשוב לזכור שבפרויקט Android צריך להשתמש רק בהגדרות של יחסי תלות שמוגדרות בדף הזה.

הוספת תלות של הפרויקט בספרייה או בפלאגין

הדרך הכי טובה להוסיף ולנהל יחסי תלות של גרסאות build היא להשתמש בקטלוגים של גרסאות, השיטה שבה פרויקטים חדשים משתמשים כברירת מחדל. בקטע הזה מפורטים סוגי ההגדרות הנפוצים ביותר לפרויקטים של Android. אפשרויות נוספות מפורטות במסמכי התיעוד של Gradle. דוגמה לאפליקציה שמשתמשת בקטלוגים של גרסאות זמינה במאמר Now in Android. אם כבר הגדרתם יחסי תלות של גרסאות build בלי קטלוגים של גרסאות ויש לכם פרויקט עם כמה מודולים, מומלץ להעביר אותו.

במאמר יחסי תלות מקומיים מוסבר איך מוסיפים ומנהלים יחסי תלות מקומיים (לא נפוץ).

בדוגמה הבאה, לפרויקט נוספו תלות בינארית מרחוק (ספריית Jetpack Macrobenchmark), תלות במודול של ספרייה מקומית (myLibrary) ותלות בפלאגין (הפלאגין של Android Gradle). כדי להוסיף את יחסי התלות האלה לפרויקט:

  1. מוסיפים כינוי לגרסה הרצויה של יחסי התלות בקטע [versions] של קובץ קטלוג הגרסאות, שנקרא libs.versions.toml (בספרייה gradle בתצוגת Project או Gradle Scripts בתצוגת Android):

    [versions]
    agp = "8.3.0"
    androidx-macro-benchmark = "1.2.2"
    my-library = "1.4"
    
    [libraries]
    ...
    
    [plugins]
    ...
    

    כינויים יכולים לכלול מקפים או קווים תחתונים. הכינויים האלה יוצרים ערכים בתצוגת עץ שאפשר להפנות אליהם בסקריפטים של build. ההפניות מתחילות בשם הקטלוג, החלק libs של libs.versions.toml. כשמשתמשים בקטלוג עם גרסה אחת, מומלץ להשאיר את ערך ברירת המחדל "libs".

  2. מוסיפים כינוי לתלות בקטעים [libraries] (לקבצים בינאריים מרוחקים או למודולים של ספריות מקומיות) או [plugins] (לפלאגינים) בקובץ libs.versions.toml.

    [versions]
    ...
    
    [libraries]
    androidx-benchmark-macro = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version.ref = "androidx-macro-benchmark" }
    my-library = { group = "com.myapplication", name = "mylibrary", version.ref = "my-library" }
    
    [plugins]
    androidApplication = { id = "com.android.application", version.ref = "agp" }
    

    חלק מהספריות זמינות ב-Bill of Materials‏ (BOM) שפורסם, שמקבץ משפחות של ספריות ואת הגרסאות שלהן. אתם יכולים לכלול BOM בקטלוג הגרסאות ובקובצי ה-build, והוא ינהל את הגרסאות האלה בשבילכם. פרטים נוספים זמינים במאמר שימוש ברשימת החומרים.

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

    Kotlin

    plugins {
      alias(libs.plugins.androidApplication)
    }
    
    dependencies {
      implementation(libs.androidx.benchmark.macro)
      implementation(libs.my.library)
    }

    מגניב

    plugins {
      alias 'libs.plugins.androidApplication'
    }
    
    dependencies {
      implementation libs.androidx.benchmark.macro
      implementation libs.my.library
    }

    הפניות לפלאגינים כוללות את plugins אחרי שם הקטלוג, והפניות לגרסאות כוללות את versions אחרי שם הקטלוג (הפניות לגרסאות הן לא נפוצות. דוגמאות להפניות לגרסאות מופיעות בקטע יחסי תלות עם מספרי גרסאות זהים). הפניות לספריות לא כוללות מזהה libraries, ולכן אי אפשר להשתמש ב-versions או ב-plugins בתחילת כינוי של ספרייה.

הגדרת יחסי תלות

בתוך הבלוק dependencies, אפשר להצהיר על תלות בספרייה באמצעות אחת מכמה הגדרות תלות שונות (כמו implementation שמוצגת למעלה). כל הגדרת תלות מספקת ל-Gradle הוראות שונות לגבי אופן השימוש בתלות. בטבלה הבאה מתוארות כל ההגדרות שאפשר להשתמש בהן ליחסי תלות בפרויקט Android.

הגדרות אישיות התנהגות
implementation ‫Gradle מוסיף את התלות ל-classpath של ה-compile ומאגד את התלות לפלט ה-build. כשמגדירים במודול תלות מסוג implementation, זה מאותת ל-Gradle שאתם לא רוצים שהמודול ידליף את התלות למודולים אחרים בזמן הקימפול. כלומר, התלות לא זמינה למודולים אחרים שתלויים במודול הנוכחי.

שימוש בהגדרת התלות הזו במקום ב-api יכול לשפר משמעותית את זמן ה-build, כי היא מפחיתה את מספר המודולים שמערכת ה-build צריכה לקמפל מחדש. לדוגמה, אם ה-API של יחסי תלות ב-implementation משתנה, Gradle מקמפל מחדש רק את יחסי התלות האלה ואת המודולים שתלויים בהם ישירות. רוב מודולי האפליקציות והבדיקות צריכים להשתמש בהגדרה הזו.

api ‫Gradle מוסיף את התלות לנתיב המחלקות (classpath) של ההידור ולפלט ה-build. כשמודול כולל תלות מסוג api, הוא מודיע ל-Gradle שהמודול רוצה לייצא את התלות הזו באופן טרנזיטיבי למודולים אחרים, כדי שהיא תהיה זמינה להם גם בזמן הריצה וגם בזמן הקימפול.

צריך להשתמש בהגדרה הזו בזהירות ורק עם יחסי תלות שצריך לייצא באופן טרנזיטיבי לצרכנים אחרים במעלה הזרם. אם ה-API החיצוני של יחסי תלות מסוג api משתנה, Gradle מקמפל מחדש את כל המודולים שיש להם גישה ליחסי התלות האלה בזמן הקימפול. אם יש הרבה יחסי תלות ב-api, זמן ה-build יכול להתארך באופן משמעותי. אלא אם רוצים לחשוף את ה-API של התלות למודול נפרד, מודולים של ספריות צריכים להשתמש בתלויות implementation.

compileOnly ‫Gradle מוסיף את התלות רק לנתיב ה-classpath של הקומפילציה (כלומר, היא לא מתווספת לפלט ה-build). האפשרות הזו שימושית כשיוצרים מודול של Android וצריך את התלות במהלך ההידור, אבל לא חובה שהיא תהיה נוכחת בזמן הריצה. לדוגמה, אם אתם מסתמכים על ספרייה שכוללת רק אנוטציות של זמן הידור – בדרך כלל משתמשים בהן כדי ליצור קוד, אבל לעיתים קרובות הן לא נכללות בפלט ה-build – אתם יכולים לסמן את הספרייה הזו בתור compileOnly.

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

הערה: אי אפשר להשתמש בהגדרה compileOnly עם יחסי תלות של Android Archive‏ (AAR).

runtimeOnly ‫Gradle מוסיף את התלות לפלט ה-build בלבד, לשימוש בזמן הריצה. כלומר, הוא לא נוסף ל-classpath של הקימפול. השימוש בזה ב-Android נדיר, אבל נפוץ באפליקציות שרת כדי לספק הטמעות של רישום ביומן. לדוגמה, ספרייה יכולה להשתמש ב-API של רישום ביומן שלא כולל הטמעה. משתמשים בספרייה הזו יכולים להוסיף אותה בתור תלות של implementation ולכלול תלות של runtimeOnly כדי להשתמש בהטמעה בפועל של הרישום ביומן.
ksp
kapt
annotationProcessor

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

כדי להוסיף תלות כזו, צריך להוסיף אותה לנתיב המחלקה של מעבד האנוטציות באמצעות ההגדרות ksp,‏ kapt או annotationProcessor. השימוש בהגדרות האלה משפר את ביצועי ה-build על ידי הפרדת ה-classpath של ה-compile מה-classpath של מעבד האנוטציות. אם Gradle מוצא מעבדי אנוטציות ב-classpath של הקומפילציה, הוא משבית את הימנעות מקומפילציה, מה שמשפיע לרעה על משך זמן של תהליך build (גרסה 5.0 ומעלה של Gradle מתעלמת ממעבדי אנוטציות שנמצאים ב-classpath של הקומפילציה).

הפלאגין של Android Gradle מניח שתלות היא מעבד אנוטציות אם קובץ ה-JAR שלה מכיל את הקובץ הבא:

META-INF/services/javax.annotation.processing.Processor

אם הפלאגין מזהה מעבד אנוטציות שנמצא ב-classpath של הקימפול, הוא יוצר שגיאת build.

‫ksp הוא מעבד סמלים של Kotlin, והוא מופעל על ידי המהדר של Kotlin.

‫kapt ו-apt הם כלים נפרדים שמעבדים הערות לפני שהקומפיילרים של Kotlin או Java פועלים.

כשמחליטים באיזו הגדרה להשתמש, כדאי להביא בחשבון את הנקודות הבאות:

  • אם מעבד זמין כמעבד סמלים של Kotlin, צריך להשתמש בו כתלות של ksp. במאמר מעבר מ-kapt ל-ksp מוסבר איך להשתמש ב-Kotlin Symbol Processors.
  • אם המעבד לא זמין כמעבד סמלים של Kotlin:
    • אם הפרויקט כולל קוד מקור ב-Kotlin (אבל יכול לכלול גם קוד מקור ב-Java), השתמשו ב-kapt כדי לכלול אותו.
    • אם הפרויקט משתמש רק במקור Java, צריך להשתמש ב-annotationProcessor כדי לכלול אותו.

מידע נוסף על השימוש במעבדי אנוטציות זמין במאמר הוספת מעבדי אנוטציות.

lintChecks

משתמשים בהגדרה הזו כדי לכלול ספרייה שמכילה בדיקות lint שרוצים ש-Gradle יבצע בזמן ה-build של פרויקט האפליקציה ל-Android.

חשוב לזכור שקובצי AAR שמכילים קובץ lint.jar יריצו באופן אוטומטי בדיקות שמוגדרות בקובץ lint.jar הזה. אין צורך להוסיף תלות מפורשת ב-lintChecks. כך אפשר להגדיר ספריות ובדיקות lint משויכות בתלות אחת, ולוודא שהבדיקות יפעלו כשהצרכנים ישתמשו בספרייה.

lintPublish משתמשים בהגדרה הזו בפרויקטים של ספריית Android כדי לכלול בדיקות lint שרוצים ש-Gradle יקמפל לקובץ lint.jar ויארוז ב-AAR. כך, פרויקטים שמשתמשים ב-AAR שלכם יפעילו גם את בדיקות ה-lint האלה. אם השתמשתם בעבר בהגדרת התלות lintChecks כדי לכלול בדיקות איתור שגיאות בקובץ ה-AAR שפורסם, אתם צריכים להעביר את יחסי התלות האלה כדי להשתמש בהגדרה lintPublish במקום זאת.

Kotlin

dependencies {
  // Executes lint checks from the ":checks" project at build time.
  lintChecks(project(":checks"))
  // Compiles lint checks from the ":checks-to-publish" into a
  // lint.jar file and publishes it to your Android library.
  lintPublish(project(":checks-to-publish"))
}

מגניב

dependencies {
  // Executes lint checks from the ':checks' project at build time.
  lintChecks project(':checks')
  // Compiles lint checks from the ':checks-to-publish' into a
  // lint.jar file and publishes it to your Android library.
  lintPublish project(':checks-to-publish')
}

הגדרת יחסי תלות לווריאנט build ספציפי

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

לדוגמה, כדי להוסיף תלות בינארית מרחוק רק לגרסת המוצר "free" באמצעות ההגדרה implementation, משתמשים בקוד הבא:

Kotlin

dependencies {
    freeImplementation("com.google.firebase:firebase-ads:21.5.1")
}

מגניב

dependencies {
    freeImplementation 'com.google.firebase:firebase-ads:21.5.1'
}

עם זאת, אם רוצים להוסיף תלות לווריאנט שמשלב גרסת מוצר וסוג גרסת build, צריך להפעיל את שם ההגדרה:

Kotlin

// Initializes a placeholder for the freeDebugImplementation dependency configuration.
val freeDebugImplementation by configurations.creating

dependencies {
    freeDebugImplementation(project(":free-support"))
}

מגניב

configurations {
    // Initializes a placeholder for the freeDebugImplementation dependency configuration.
    freeDebugImplementation {}
}

dependencies {
    freeDebugImplementation project(":free-support")
}

כדי להוסיף יחסי תלות של implementation לבדיקות המקומיות ולבדיקות אינסטרומנטציה, זה נראה כך:

Kotlin

dependencies {
    // Adds a remote binary dependency only for local tests.
    testImplementation("junit:junit:4.12")

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
}

מגניב

dependencies {
    // Adds a remote binary dependency only for local tests.
    testImplementation 'junit:junit:4.12'

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
}

עם זאת, יש הגדרות מסוימות שלא מתאימות למצב הזה. לדוגמה, מכיוון שמודולים אחרים לא יכולים להיות תלויים ב-androidTest, תופיע האזהרה הבאה אם תשתמשו בהגדרה androidTestApi:

WARNING: Configuration 'androidTestApi' is obsolete and has been replaced with
'androidTestImplementation'.

סדר התלות

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

לדוגמה, אם בפרויקט שלכם מוגדרים המאפיינים הבאים:

  • תלות ב-LIB_A וב-LIB_B (בסדר הזה)
  • ‫LIB_A תלוי ב-LIB_C וב-LIB_D (בסדר הזה)
  • וגם LIB_B תלוי ב-LIB_C

ואז סדר התלות השטוח יהיה:

  1. LIB_A
  2. LIB_D
  3. LIB_B
  4. LIB_C

כך אפשר לוודא שגם LIB_A וגם LIB_B יכולים לשנות את LIB_C, ושל-LIB_D עדיין יש עדיפות גבוהה יותר מאשר ל-LIB_B כי ל-LIB_A (שתלוי בו) יש עדיפות גבוהה יותר מאשר ל-LIB_B.

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

מידע על יחסי תלות ב-Play Console

כשמפתחים אפליקציה, AGP כולל מטא-נתונים שמתארים את יחסי התלות של הספרייה שמקומפלים באפליקציה. כשמעלים את האפליקציה, מערכת Play Console בודקת את המטא-נתונים האלה כדי לספק התראות על בעיות מוכרות בערכות ה-SDK וביחסי התלות שבהם האפליקציה משתמשת. במקרים מסוימים, המערכת מספקת משוב שניתן לפעול לפיו כדי לפתור את הבעיות האלה.

הנתונים נדחסים, מוצפנים באמצעות מפתח חתימה של Google Play ונשמרים בבלוק החתימה של האפליקציה שפורסמה. מומלץ לשמור את קובץ יחסי התלות הזה כדי לספק חוויית משתמש בטוחה וחיובית. כדי לבטל את ההסכמה, צריך לכלול את הבלוק הבא של dependenciesInfo בקובץ build.gradle.kts של המודול.

android {
    dependenciesInfo {
        // Disables dependency metadata when building APKs.
        includeInApk = false
        // Disables dependency metadata when building Android App Bundles.
        includeInBundle = false
    }
}

מידע נוסף על המדיניות שלנו ועל בעיות פוטנציאליות שקשורות לתלויות זמין בדף התמיכה בנושא שימוש בערכות SDK של צד שלישי באפליקציה.

תובנות לגבי ערכות SDK

ב-Android Studio מוצגות אזהרות של כלי הניתוח הסטטי (lint) בקובץ קטלוג הגרסאות ובתיבת הדו-שיח Project Structure (מבנה הפרויקט) לגבי ערכות SDK שמופיעות באופן ציבורי ב-Google Play SDK Index, אם מתקיימים התנאים הבאים:

  • ערכות ה-SDK מסומנות כמיושנות על ידי המחברים שלהן.
  • ערכות ה-SDK מפרות את המדיניות של Play.
  • יש בערכות ה-SDK פרצות אבטחה ידועות.
  • ערכות ה-SDK הוצאו משימוש על ידי המפתחים שלהן.

האזהרות הן אותות לכך שצריך לעדכן את יחסי התלות האלה, כי שימוש בגרסאות מיושנות עלול למנוע מכם לפרסם ב-Google Play Console בעתיד.

הוספת יחסי תלות של גרסאות build בלי קטלוגים של גרסאות

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

Kotlin

plugins {
    id("com.android.application")
}

android { ... }

dependencies {
    // Dependency on a remote binary
    implementation("com.example.android:app-magic:12.3")
    // Dependency on a local library module
    implementation(project(":mylibrary"))
}

מגניב

plugins {
    id 'com.android.application'
}

android { ... }

dependencies {
    // Dependency on a remote binary
    implementation 'com.example.android:app-magic:12.3'
    // Dependency on a local library module
    implementation project(':mylibrary')
}

בקובץ ה-build הזה מוצהרת תלות בגרסה 12.3 של הספרייה app-magic, בתוך קבוצת מרחב השמות com.example.android. הצהרת התלות הבינארית מרחוק היא קיצור של:

Kotlin

implementation(group = "com.example.android", name = "app-magic", version = "12.3")

מגניב

implementation group: 'com.example.android', name: 'app-magic', version: '12.3'

קובץ ה-build גם מצהיר על תלות במודול של ספריית Android בשם "mylibrary". השם הזה חייב להיות זהה לשם הספרייה שמוגדר באמצעות include: בקובץ settings.gradle.kts. כשאתם יוצרים את האפליקציה, מערכת ה-build מקמפלת את מודול הספרייה ואורזת את התוכן המקומפל שנוצר באפליקציה.

קובץ ה-build גם מצהיר על תלות בפלאגין של Android Gradle‏ (com.application.android). אם יש לכם כמה מודולים שמשתמשים באותו פלאגין, יכולה להיות לכם רק גרסה אחת של הפלאגין ב-classpath של ה-build בכל המודולים. במקום לציין את הגרסה בכל אחד מסקריפטי ה-build של המודולים, צריך לכלול את יחסי התלות של הפלאגין בסקריפט ה-build ברמה הבסיסית (root) עם הגרסה, ולציין שלא להחיל אותה. הוספת apply false מציינת ל-Gradle לשים לב לגרסה של הפלאגין, אבל לא להשתמש בה ב-build הבסיסי. בדרך כלל סקריפט ה-build ברמה הבסיסית ריק, חוץ מהבלוק plugins הזה.

Kotlin

plugins {
    id("org.jetbrains.kotlin.android") version "1.9.0" apply false
}

מגניב

plugins {
    id 'com.android.application' version '8.3.0-rc02' apply false
}

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

Kotlin

plugins {
    id("com.android.application") version "8.3.0"
}

מגניב

plugins {
    id 'com.android.application' version '8.3.0-rc02'
}