Dodawanie zależności kompilacji

System kompilacji Gradle w Android Studio umożliwia dodawanie do kompilacji zewnętrznych plików binarnych lub innych modułów biblioteki jako zależności. Zależności mogą znajdować się na Twoim komputerze lub w zdalnym repozytorium, a wszystkie zależności przechodnie, które deklarują, są automatycznie uwzględniane. Na tej stronie opisujemy, jak używać zależności w projekcie aplikacji na Androida, w tym szczegóły dotyczące zachowań i konfiguracji specyficznych dla wtyczki Androida do obsługi Gradle (AGP). Bardziej szczegółowe informacje o zależnościach Gradle znajdziesz w przewodniku Gradle dotyczącym zarządzania zależnościami. Pamiętaj jednak, że Twój projekt aplikacji na Androida musi używać tylko konfiguracji zależności zdefiniowanych na tej stronie.

Dodawanie zależności biblioteki lub wtyczki

Najlepszym sposobem na dodawanie zależności kompilacji i zarządzanie nimi jest używanie katalogów wersji, czyli metody, z której domyślnie korzystają nowe projekty. W tej sekcji opisujemy najczęstsze typy konfiguracji używane w projektach na Androida. Więcej opcji znajdziesz w dokumentacji Gradle . Przykład aplikacji, która korzysta z katalogów wersji, znajdziesz w Now in Android. Jeśli masz już skonfigurowane zależności kompilacji bez katalogów wersji i projekt wielomodułowy, zalecamy migrację.

Wskazówki dotyczące dodawania zależności natywnych (nie są powszechne) i zarządzania nimi znajdziesz w sekcji Zależności natywne.

W tym przykładzie dodajemy do projektu zdalną zależność binarną (bibliotekę Jetpack Macrobenchmark), lokalną zależność modułu biblioteki (myLibrary) i zależność wtyczki (wtyczkę Androida do obsługi Gradle). Oto ogólne kroki, które należy wykonać, aby dodać te zależności do projektu:

  1. Dodaj alias wersji zależności, której chcesz używać, w sekcji [versions] pliku katalogu wersji o nazwie libs.versions.toml (w katalogu gradle w widoku Projekt lub w Skryptach Gradle w widoku Android):

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

    Aliasy mogą zawierać łączniki lub znaki podkreślenia. Te aliasy generują zagnieżdżone wartości, do których można się odwoływać w skryptach kompilacji. Odwołania zaczynają się od nazwy katalogu, czyli części libs w libs.versions.toml. Jeśli używasz jednego katalogu wersji, zalecamy pozostawienie domyślnej wartości „libs”.

  2. Dodaj alias zależności w sekcji [libraries] (w przypadku zdalnych plików binarnych lub lokalnych modułów biblioteki) lub [plugins] (w przypadku wtyczek) w pliku 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" }
    

    Niektóre biblioteki są dostępne w opublikowanym wykazie materiałów (BOM), który grupuje rodziny bibliotek i ich wersje. Możesz dodać BOM do katalogu wersji i plików kompilacji oraz pozwolić mu zarządzać tymi wersjami. Więcej informacji znajdziesz w sekcji Korzystanie z listy materiałów (BoM).

  3. Dodaj odwołanie do aliasu zależności w skrypcie kompilacji modułów, które wymagają zależności. Gdy odwołujesz się do aliasu ze skryptu kompilacji, zamień znaki podkreślenia i łączniki na kropki. Skrypt kompilacji na poziomie modułu będzie wyglądać tak:

    Kotlin

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

    Dynamiczny

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

    Odwołania do wtyczek zawierają plugins po nazwie katalogu, a odwołania do wersji zawierają versions po nazwie katalogu (odwołania do wersji są rzadkie; przykłady odwołań do wersji znajdziesz w sekcji Zależności o tych samych numerach wersji). Odwołania do bibliotek nie zawierają kwalifikatora libraries, więc nie można używać versions ani plugins na początku aliasu biblioteki.

Konfigurowanie zależności

W bloku dependencies możesz zadeklarować zależność biblioteki za pomocą jednej z kilku różnych konfiguracji zależności (np. implementation pokazanej wcześniej). Każda konfiguracja zależności zawiera inne instrukcje dla Gradle dotyczące sposobu używania zależności. W tabeli poniżej opisujemy każdą konfigurację, której możesz użyć w przypadku zależności w projekcie aplikacji na Androida.

Konfiguracja Zachowanie
implementation Gradle dodaje zależność do ścieżki kompilacji i pakuje ją do danych wyjściowych kompilacji. Gdy moduł konfiguruje zależność implementation, informuje Gradle, że nie chcesz, aby moduł wyciekał zależność do innych modułów w czasie kompilacji. Oznacza to, że zależność nie jest udostępniana innym modułom, które zależą od bieżącego modułu.

Użycie tej konfiguracji zależności zamiast api może znacznie skrócić czas kompilacji ponieważ zmniejsza liczbę modułów, które system kompilacji musi ponownie skompilować. Jeśli na przykład zależność implementation zmieni swój interfejs API, Gradle ponownie skompiluje tylko tę zależność i moduły, które bezpośrednio od niej zależą. Większość modułów aplikacji i testów powinna używać tej konfiguracji.

api Gradle dodaje zależność do ścieżki kompilacji i danych wyjściowych kompilacji. Gdy moduł zawiera zależność api, informuje Gradle, że moduł chce przechodnio eksportować tę zależność do innych modułów, aby była ona dostępna zarówno w czasie wykonywania, jak i w czasie kompilacji.

Używaj tej konfiguracji ostrożnie i tylko w przypadku zależności, które musisz przechodnio eksportować do innych odbiorców. Jeśli zależność api zmieni swój zewnętrzny interfejs API, Gradle ponownie skompiluje wszystkie moduły, które mają dostęp do tej zależności w czasie kompilacji. Duża liczba zależności api może znacznie wydłużyć czas kompilacji. Jeśli nie chcesz udostępniać interfejsu API zależności w osobnym module, moduły biblioteki powinny zamiast tego używać zależności implementation.

compileOnly Gradle dodaje zależność tylko do ścieżki kompilacji (tzn. nie jest ona dodawana do danych wyjściowych kompilacji). Jest to przydatne, gdy tworzysz moduł na Androida i potrzebujesz zależności podczas kompilacji, ale nie jest ona wymagana w czasie wykonywania. Jeśli na przykład zależy Ci na bibliotece, która zawiera tylko adnotacje w czasie kompilacji (zwykle używane do generowania kodu, ale często nie są uwzględniane w danych wyjściowych kompilacji), możesz oznaczyć tę bibliotekę jako compileOnly.

Jeśli używasz tej konfiguracji, moduł biblioteki musi zawierać warunek czasu wykonywania, który sprawdza, czy zależność jest dostępna, a następnie płynnie zmienia swoje zachowanie, aby nadal działać, jeśli nie jest dostępna. Pomaga to zmniejszyć rozmiar końcowej aplikacji, ponieważ nie dodaje zależności przejściowych, które nie są krytyczne.

Uwaga: nie możesz używać konfiguracji compileOnly z zależnościami archiwum Androida (AAR).

runtimeOnly Gradle dodaje zależność tylko do danych wyjściowych kompilacji, do użycia w czasie wykonywania. Oznacza to, że nie jest ona dodawana do ścieżki kompilacji. Jest to rzadko używane w Androidzie, ale często w aplikacjach serwerowych do udostępniania implementacji logowania. Biblioteka może na przykład używać interfejsu API logowania, który nie zawiera implementacji. Odbiorcy tej biblioteki mogą dodać ją jako implementation zależność i uwzględnić runtimeOnly zależność dla rzeczywistej implementacji logowania.
ksp
kapt
annotationProcessor

Te konfiguracje dostarczają biblioteki, które przetwarzają adnotacje i inne symbole w kodzie przed jego skompilowaniem. Zwykle sprawdzają kod lub generują dodatkowy kod, co zmniejsza ilość kodu, który musisz napisać.

Aby dodać taką zależność, musisz dodać ją do ścieżki klasy procesora adnotacji za pomocą konfiguracji ksp, kapt lub annotationProcessor. Użycie tych konfiguracji poprawia wydajność kompilacji, ponieważ oddziela ścieżkę kompilacji od ścieżki klasy procesora adnotacji. Jeśli Gradle znajdzie procesory adnotacji w ścieżce kompilacji, dezaktywuje unikanie kompilacji, co negatywnie wpływa na czas kompilacji (Gradle 5.0 i nowsze ignorują procesory adnotacji znalezione w ścieżce kompilacji ).

Wtyczka Androida do obsługi Gradle zakłada, że zależność jest procesorem adnotacji jeśli jej plik JAR zawiera ten plik:

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

Jeśli wtyczka wykryje procesor adnotacji, który znajduje się w ścieżce kompilacji, spowoduje błąd kompilacji.

ksp to procesor symboli Kotlin, który jest uruchamiany przez kompilator Kotlin.

kapt i apt to osobne narzędzia, które przetwarzają adnotacje przed wykonaniem kompilatorów Kotlin lub Java.

Przy wyborze konfiguracji należy wziąć pod uwagę te kwestie:

  • Jeśli procesor jest dostępny jako procesor symboli Kotlin, użyj go jako zależności ksp. Więcej informacji o korzystaniu z procesorów symboli Kotlin znajdziesz w artykule Migracja z kapt do ksp.
  • Jeśli procesor nie jest dostępny jako procesor symboli Kotlin:
    • Jeśli Twój projekt zawiera źródło Kotlin (ale może też zawierać źródło Java), użyj aby je uwzględnić.kapt
    • Jeśli Twój projekt używa tylko źródła Java, użyj annotationProcessor aby je uwzględnić.

Więcej informacji o korzystaniu z procesorów adnotacji znajdziesz w sekcji Dodawanie procesorów adnotacji.

lintChecks

Użyj tej konfiguracji, aby uwzględnić bibliotekę zawierającą sprawdzenia lintera które mają być wykonywane przez Gradle podczas kompilowania projektu aplikacji na Androida.

Pamiętaj, że pliki AAR zawierające plik lint.jar automatycznie uruchamiają sprawdzenia zdefiniowane w tym pliku lint.jar. Nie musisz dodawać jawnej zależności lintChecks. Umożliwia to zdefiniowanie bibliotek i powiązanych z nimi sprawdzeń lintera w ramach jednej zależności, co zapewnia, że sprawdzenia są wykonywane, gdy odbiorcy korzystają z Twojej biblioteki.

lintPublish Użyj tej konfiguracji w projektach bibliotek na Androida, aby uwzględnić sprawdzenia lintera, które mają być kompilowane przez Gradle do pliku lint.jar i spakowane w pliku AAR. Powoduje to, że projekty, które korzystają z Twojego pliku AAR, również stosują te sprawdzenia lintera. Jeśli wcześniej używałeś konfiguracji zależności lintChecks do uwzględniania sprawdzeń lintera w opublikowanym pliku AAR, musisz przeprowadzić migrację tych zależności , aby zamiast tego używać konfiguracji 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"))
}

Dynamiczny

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')
}

Konfigurowanie zależności dla konkretnego wariantu kompilacji

Wszystkie poprzednie konfiguracje stosują zależności do wszystkich wariantów kompilacji. Jeśli zamiast tego chcesz zadeklarować zależność tylko dla konkretnego wariantu kompilacji zbioru źródeł lub dla testowego zbioru źródeł, musisz napisać nazwę konfiguracji wielkimi literami i dodać przed nią nazwę wariantu kompilacji lub testowego zbioru źródeł.

Aby na przykład dodać zdalną zależność binarną tylko do wariantu usługi „bezpłatnej” za pomocą konfiguracji implementation, użyj tego kodu:

Kotlin

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

Dynamiczny

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

Jeśli jednak chcesz dodać zależność dla wariantu, który łączy wariant usługi i rodzaj kompilacji, musisz zainicjować nazwę konfiguracji:

Kotlin

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

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

Dynamiczny

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

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

Aby dodać zależności implementation do testów lokalnych i testów instrumentowanych, użyj tego kodu:

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

Dynamiczny

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'
}

Jednak w tej sytuacji niektóre konfiguracje nie mają sensu. Na przykład, ponieważ inne moduły nie mogą zależeć od androidTest, jeśli użyjesz konfiguracji androidTestApi, zobaczysz to ostrzeżenie:

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

Kolejność zależności

Kolejność, w jakiej wymieniasz zależności, wskazuje priorytet każdej z nich: pierwsza biblioteka ma wyższy priorytet niż druga, druga ma wyższy priorytet niż trzecia itd. Ta kolejność jest ważna w przypadku scalania zasobów lub scalania elementów manifestu z bibliotek w aplikacji.

Jeśli na przykład Twój projekt deklaruje:

  • zależność od LIB_A i LIB_B (w tej kolejności),
  • a LIB_A zależy od LIB_C i LIB_D (w tej kolejności),
  • a LIB_B też zależy od LIB_C.

Wtedy kolejność zależności będzie wyglądać tak:

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

Dzięki temu zarówno LIB_A, jak i LIB_B mogą zastąpić LIB_C, a LIB_D nadal ma wyższy priorytet niż LIB_B, ponieważ LIB_A (która od niej zależy) ma wyższy priorytet niż LIB_B.

Więcej informacji o tym, jak scalane są manifesty z różnych źródeł projektu i zależności, znajdziesz w sekcji Scalanie wielu plików manifestu.

Informacje o zależnościach w Konsoli Play

Podczas kompilowania aplikacji AGP zawiera metadane opisujące zależności bibliotek, które są kompilowane w aplikacji. Podczas przesyłania aplikacji Konsola Play sprawdza te metadane, aby wyświetlać alerty o znanych problemach z pakietami SDK i zależnościami używanymi przez aplikację, a w niektórych przypadkach – aby przekazywać praktyczne wskazówki dotyczące rozwiązywania tych problemów.

Dane są kompresowane, szyfrowane za pomocą klucza podpisywania Google Play i przechowywane w bloku podpisywania aplikacji. Zalecamy zachowanie tego pliku zależności, aby zapewnić bezpieczne i pozytywne wrażenia użytkownikom. Możesz zrezygnować, dodając ten następujący dependenciesInfo blok do pliku build.gradle.kts modułu.

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

Więcej informacji o naszych zasadach i potencjalnych problemach z zależnościami znajdziesz na stronie pomocy dotyczącej korzystania z pakietów SDK innych firm w aplikacji.

Informacje o pakietach SDK

Android Studio wyświetla ostrzeżenia lintera w pliku katalogu wersji i w oknie struktury projektu w przypadku publicznych pakietów SDK na platformie Google Play SDK Index, gdy występują te problemy:

  • Pakiety SDK są oznaczone przez ich autorów jako przestarzałe.
  • Pakiety SDK naruszają zasady Google Play.
  • Pakiety SDK mają znane luki w zabezpieczeniach.
  • Pakiety SDK zostały wycofane przez ich autorów.

Ostrzeżenia wskazują, że należy zaktualizować te zależności, ponieważ używanie przestarzałych wersji może w przyszłości uniemożliwić publikowanie w Konsoli Google Play.

Dodawanie zależności kompilacji bez katalogów wersji

Do dodawania zależności i zarządzania nimi zalecamy używanie katalogów wersji, ale w prostych projektach mogą one nie być potrzebne. Oto przykład pliku kompilacji, który nie używa katalogów wersji:

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

Dynamiczny

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')
}

Ten plik kompilacji deklaruje zależność od wersji 12.3 biblioteki „app-magic” w grupie przestrzeni nazw „com.example.android”. Deklaracja zdalnej zależności binarnej jest skrótem od tego kodu:

Kotlin

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

Dynamiczny

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

Plik kompilacji deklaruje też zależność od modułu biblioteki na Androida o nazwie "mylibrary". Ta nazwa musi być zgodna z nazwą biblioteki zdefiniowaną za pomocą include: w pliku settings.gradle.kts. Podczas kompilowania aplikacji system kompilacji kompiluje moduł biblioteki i pakuje skompilowaną zawartość w aplikacji.

Plik kompilacji deklaruje też zależność od wtyczki Androida do obsługi Gradle (com.application.android). Jeśli masz kilka modułów, które używają tej samej wtyczki, w ścieżce kompilacji we wszystkich modułach możesz mieć tylko jedną wersję wtyczki. Zamiast określać wersję w każdym skrypcie kompilacji modułu, dodaj zależność wtyczki w skrypcie kompilacji głównej z wersją i wskaż, aby jej nie stosować. Dodanie apply false informuje Gradle, aby zapamiętał wersję wtyczki, ale nie używał jej w kompilacji głównej. Zwykle skrypt kompilacji głównej jest pusty, z wyjątkiem tego bloku plugins.

Kotlin

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

Dynamiczny

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

Jeśli masz projekt jednomodułowy, możesz jawnie określić wersję w skrypcie kompilacji na poziomie modułu i pozostawić pusty skrypt kompilacji na poziomie projektu:

Kotlin

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

Dynamiczny

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