| ## Dependencies {#dependencies} | |
| Artifacts may depend on other artifacts within AndroidX as well as sanctioned | |
| third-party libraries. Additionally, artifacts may have toolchain dependencies | |
| that are not explicitly specified in their `dependencies` build configuration or | |
| don't appear in their Maven publications (`pom` or `module` files). | |
| ### Versioned artifacts {#dependencies-versioned} | |
| One of the most difficult aspects of independently-versioned releases is | |
| maintaining compatibility with public artifacts. In a monorepo such as Google's | |
| repository or Android Git at `main` revision, it's easy for an artifact to | |
| accidentally gain a dependency on a feature that may not be released on the same | |
| schedule. | |
| To address this problem, library owners in AndroidX can choose from several | |
| types of dependencies: | |
| - Project `project(":core:core")` uses the tip-of-tree sources for the | |
| `androidx.core:core` library and requires that they be loaded in the | |
| workspace and released at the same time. | |
| - Playground `projectOrArtifact(":core:core")` is used for the | |
| [Playground](/docs/playground.md) workflow and will use | |
| tip-of-tree sources, if present in the workspace, or `SNAPSHOT` prebuilt | |
| artifacts from [androidx.dev](http://androidx.dev) otherwise. | |
| - Pinned `"androidx.core:core:1.4.0"` uses the prebuilt AAR and requires that | |
| it be checked in to the `prebuilts/androidx/internal` local Maven repository | |
| or, when using the Playground workflow, the remote Google Maven repository. | |
| Libraries should prefer pinned dependencies with the lowest possible versions | |
| that include the APIs or behaviors required by the library, and should only use | |
| project or Playground specs in cases where tip-of-tree APIs or behaviors are | |
| required. | |
| **Do not** upgrade the version of a library's dependency to artificially boost | |
| adoption of that version. | |
| #### Pre-release dependencies {#dependencies-pre-release} | |
| Pre-release suffixes **must** propagate up the dependency tree. For example, if | |
| your artifact has a dependency on an artifact versioned `1.1.0-alpha01` then | |
| your artifact must also carry the `alpha` suffix. | |
| NOTE This does not apply to test dependencies: suffixes of test dependencies do | |
| *not* carry over to your artifact. | |
| #### Pinned versions {#dependencies-prebuilt} | |
| To avoid issues with dependency versioning, pin your dependencies to the oldest | |
| stable version of an artifact that includes the necessary APIs. This will ensure | |
| that the artifact's release schedule is not accidentally tied to that of another | |
| artifact and will allow developers to use older libraries if desired. | |
| ``` | |
| dependencies { | |
| api("androidx.collection:collection:1.0.0") | |
| ... | |
| } | |
| ``` | |
| Artifacts are built and tested against both pinned and tip-of-tree versions of | |
| their dependencies to ensure behavioral compatibility. | |
| #### Tip-of-tree versions {#dependencies-project} | |
| Below is an example of a project dependency, which uses tip-of-tree sources for | |
| the dependency rather than a prebuilt `JAR` or `AAR`. It ties the artifact's | |
| release schedule to that of the dependency artifact because the dependency will | |
| need to be released at the same time. | |
| ``` | |
| dependencies { | |
| api(project(":collection")) | |
| ... | |
| } | |
| ``` | |
| ### Non-public APIs {#dependencies-non-public-apis} | |
| Artifacts may depend on non-public or restricted APIs exposed within their own | |
| artifact or another artifact in the same `groupId`; however, cross-artifact | |
| usages are subject to binary compatibility guarantees. See | |
| [`@RestrictTo` APIs](/docs/api_guidelines#restricted-api) for | |
| more details. | |
| Dependency versioning policies are enforced at build time in the `createArchive` | |
| task, which ensures that pre-release version suffixes are propagated | |
| appropriately. Cross-artifact API usage policies are enforced by the `checkApi` | |
| and `checkApiRelease` tasks. | |
| ### Third-party libraries {#dependencies-3p} | |
| Artifacts may depend on libraries developed outside of AndroidX; however, they | |
| must conform to the following guidelines: | |
| * Prebuilt **must** be checked into Android Git | |
| * `prebuilts/maven_repo` is recommended if this dependency is only | |
| intended for use with AndroidX artifacts, otherwise please use | |
| `external` | |
| * Prebuilt directory **must** contains an `OWNERS` file identifying one or | |
| more individual owners (e.g. NOT a group alias) | |
| * Library **must** be approved by legal | |
| Please see Jetpack's | |
| [open-source policy page](/docs/open_source.md) for more | |
| details on using third-party libraries. | |
| ### Platform extension (sidecar JAR) dependencies {#dependencies-sidecar} | |
| Platform extension or "sidecar JAR" libraries ship as part of the Android system | |
| image and are made available to developers through the `<uses-library>` manifest | |
| tag. | |
| Examples include Camera OEM extensions (`androidx.camera.extensions.impl`) and | |
| Window OEM extensions (`androidx.window.extensions`). | |
| Extension libraries may be defined in AndroidX library projects (see | |
| `androidx.window.extensions`) or externally, ex. in AOSP alongside the platform. | |
| In either case, we recommend that libraries use extensions as pinned, rather | |
| than project-type, dependencies to facilitate versioning across repositories. | |
| *Do not* ship extension interfaces to Google Maven. Teams may choose to ship | |
| stub JARs publicly, but that is not covered by AndroidX workflows. | |
| Project dependencies on extension libraries **must** use `compileOnly`: | |
| `build.gradle`: | |
| ``` | |
| dependencies { | |
| // Extension interfaces defined in Jetpack | |
| compileOnly(project(":window:extensions:extensions")) | |
| // Extension interfaces defined in a stub JAR | |
| compileOnly( | |
| fileTree( | |
| dir: "../wear_stubs", | |
| include: ["com.google.android.wearable-stubs.jar"] | |
| ) | |
| ) | |
| } | |
| ``` | |
| Documentation dependencies **must** use the `stubs` configuration: | |
| `docs-tip-of-tree/build.gradle` and `docs-public/build.gradle`: | |
| ``` | |
| dependencies { | |
| stubs("androidx.window:window-extensions:1.0.0-alpha01") | |
| stubs( | |
| fileTree( | |
| dir: "../wear/wear_stubs/", | |
| include: ["com.google.android.wearable-stubs.jar"] | |
| ) | |
| ) | |
| } | |
| ``` | |
| See [Packaging and naming](/docs/api_guidelines#module-naming) | |
| for details about defining extension interfaces in Jetpack projects. | |
| ### Types of dependencies {#dependencies-types} | |
| AndroidX allows dependencies to be specified as `api` or `implementation` with a | |
| "pinned" Maven spec (ex. `androidx.core:core:1.0.0`) or a "tip-of-tree" project | |
| spec (ex. `project(":core:core")`). | |
| Projects used in Playground, the experimental GitHub workflow, should use a | |
| "recent" project or artifact spec (ex. `projectOrArtifact(":core:core")`) which | |
| will default to tip-of-tree when used outside of the Playground workflow or a | |
| pinned `SNAPSHOT` artifact otherwise. | |
| Regardless of which dependency spec is used, all projects are built against | |
| tip-of-tree dependencies in CI to prevent regressions and enforce Jetpack's | |
| compatible-at-head policy. | |
| #### `api` versus `implementation` {#dependencies-api-vs-impl} | |
| `api`-type dependencies will appear in clients' auto-complete as though they had | |
| added the dependency directly to their project, and Studio will run any lint | |
| checks bundled with `api`-type dependencies. | |
| Dependencies whose APIs are exposed in a library's API surface **must** be | |
| included as `api`-type. For example, if your library's API surface includes | |
| `AccessibilityNodeInfoCompat` then you will use an `api`-type dependency on the | |
| `androidx.core:core` library. | |
| NOTE Libraries that provide client-facing lint checks, including | |
| `annotation-experimental`, **must** be included as `api`-type to ensure that | |
| lint checks are run in the clients' dependent projects. | |
| `implementation`-type dependencies will be included in the classpath, but will | |
| not be made available at design time (ex. in auto-complete) unless the client | |
| explicitly adds them. | |
| #### Constraints {#dependencies-constraints} | |
| Dependency constraints ensure that when certain libraries are used together, | |
| they meet certain requirements. Defining a constraint on a library *does not* | |
| pull that library into the classpath. | |
| In Jetpack, we use constraints to ensure that atomically-grouped libraries all | |
| resolve to the same version | |
| ([example](https://android-review.googlesource.com/c/platform/frameworks/support/+/1973425)) | |
| and, in rare cases, to avoid conflicts resulting from classes being moved | |
| between artifacts | |
| ([example](https://android-review.googlesource.com/c/platform/frameworks/support/+/2086029)). | |
| `core/core-ktx/build.gradle`: | |
| ``` | |
| dependencies { | |
| // Atomic group | |
| constraints { | |
| implementation(project(":core:core")) | |
| } | |
| } | |
| ``` | |
| In *extremely* rare cases, libraries may need to define a constraint on a | |
| project that is not in its `studiow` project set, ex. a constraint between the | |
| Paging and Compose libraries. As a workaround, libraries may hard-code the Maven | |
| coordinate using a version variable | |
| ([example](https://android-review.googlesource.com/c/platform/frameworks/support/+/2160202)) | |
| to indicate the tip-of-tree version. | |
| `paging/paging-common/build.gradle`: | |
| ``` | |
| dependencies { | |
| // Atomic group | |
| constraints { | |
| implementation("androidx.paging:paging-compose:${LibraryVersions.PAGING_COMPOSE}") | |
| } | |
| } | |
| ``` | |
| ### Dependency considerations {#dependencies-health} | |
| Generally, Jetpack libraries should avoid dependencies that negatively impact | |
| developers without providing substantial benefit. Libraries should consider the | |
| implications of their dependencies, including: | |
| - Large dependencies where only a small portion is needed (e.g. APK bloat) | |
| - Dependencies that slow down build times through annotation processing or | |
| compiler overhead | |
| - Dependencies which do not maintain binary compatibility and conflict with | |
| semantic versioning guarantees | |
| - Dependencies that are intended for server environments and don't interact | |
| well with the Android build toolchain (e.g. R8) or runtime (e.g. ART) | |
| #### Kotlin {#dependencies-kotlin} | |
| Kotlin is *strongly recommended* for new libraries and the Kotlin stdlib will | |
| already be present in the transitive dependencies of any library that depends on | |
| `androidx.annotations`. | |
| ``` | |
| plugins { | |
| id("AndroidXPlugin") | |
| id("kotlin-android") | |
| } | |
| dependencies { | |
| implementation(libs.kotlinStdlib) | |
| } | |
| ``` | |
| Java-based libraries *may* migrate to Kotlin, but they must be careful to | |
| maintain binary compatibility during the migration. Metalava does not cover all | |
| possible aspects of migration, so some manual work will be required. | |
| #### Kotlin reflect {#dependencies-kotlin-reflect} | |
| Reflection in libraries is | |
| [only allowed for backwards compatibility support](/docs/api_guidelines#sdk-reflection) | |
| and those users should use Java reflection. `kotlin-reflect` is very costly at | |
| runtime and should never be used. | |
| #### Kotlin coroutines {#dependencies-coroutines} | |
| The Kotlin coroutines library adds around 100kB post-shrinking. New libraries | |
| that are written in Kotlin should prefer coroutines over `ListenableFuture`, but | |
| existing libraries must consider the size impact on their clients. See | |
| [Asynchronous work with return values](/docs/api_guidelines#async-return) | |
| for more details on using Kotlin coroutines in Jetpack libraries. | |
| ``` | |
| dependencies { | |
| implementation(libs.kotlinCoroutinesAndroid) | |
| } | |
| ``` | |
| #### GSON {#dependencies-gson} | |
| GSON relies heavily on reflection and interacts poorly with app optimization | |
| tools like R8. Instead, consider using `org.json` which is included in the | |
| Android platform SDK. | |
| #### Guava {#dependencies-guava} | |
| The full Guava library is very large and should only be used in cases where | |
| there is a reasonable assumption that clients already depend on full Guava. | |
| For example, consider a library `androidx.foo:foo` implemented using Kotlin | |
| `suspend fun`s and an optional `androidx.foo:foo-guava` library that provides | |
| `ListenableFuture` interop wrappers with a direct dependency on | |
| `kotlinx.coroutines:kotlinx-coroutines-guava` and a transitive dependency on | |
| Guava. | |
| Libraries that only need `ListenableFuture` may instead depend on the standalone | |
| `com.google.guava:listenablefuture` artifact. See | |
| [Asynchronous work with return values](/docs/api_guidelines#async-return) | |
| for more details on using `ListenableFuture` in Jetpack libraries. | |
| #### Protobuf {#dependencies-protobuf} | |
| **Note**: It is preferred to use the [`wire`](https://github.com/square/wire) | |
| library for handling protocol buffers in Android libraries as it has a binary | |
| stable runtime. An example of its usage can be found | |
| [here](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:benchmark/benchmark-common/build.gradle?q=wireRuntime%20file:gradle&ss=androidx%2Fplatform%2Fframeworks%2Fsupport). | |
| [Protocol buffers](https://developers.google.com/protocol-buffers) provide a | |
| language- and platform-neutral mechanism for serializing structured data. The | |
| implementation enables developers to maintain protocol compatibility across | |
| library versions, meaning that two clients can communicate regardless of the | |
| library versions included in their APKs. | |
| The Protobuf library itself (`com.google.proto`), however, does not guarantee | |
| ABI compatibility across minor versions and a specific version **must** be used | |
| with a library to avoid conflict with other dependencies used by the developer. | |
| To do this, you must first create a new project to repackage the protobuf | |
| runtime classes, and then have it as a dependency in the project you generate | |
| protos in. In the project that generates protos, you must also relocate any | |
| import statements containing `com.google.protobuf` to your target package name. | |
| The | |
| [AndroidXRepackagePlugin](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:buildSrc/private/src/main/kotlin/androidx/build/AndroidXRepackageImplPlugin.kt) | |
| abstracts this for you. An example of its use to repackage the protobuf runtime | |
| library can be found | |
| [here](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:wear/protolayout/protolayout-external-protobuf/build.gradle) | |
| and its associated use in the library that generates protos can be found | |
| [here](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:wear/protolayout/protolayout-proto/build.gradle). | |
| Additionally, the Java API surface generated by the Protobuf compiler is not | |
| guaranteed to be stable and **must not** be exposed to developers. Library | |
| owners should wrap the generated API surface with well-documented public APIs | |
| that follow an appropriate language-specific paradigm for constructing data | |
| classes, e.g. the Java `Builder` pattern. | |
| ### Open-source compatibility {#dependencies-aosp} | |
| Jetpack's [open-source](/docs/open_source.md) guidelines | |
| require that libraries consider the open-source compatibility implications of | |
| their dependencies, including: | |
| - Closed-source or proprietary libraries or services that may not be available | |
| on AOSP devices | |
| - Dependencies that may prevent developers from effectively isolating their | |
| tests from third-party libraries or services | |
| Primary artifacts, e.g. `workmanager`, **must not** depend on closed-source | |
| components including libraries and hard-coded references to packages, | |
| permissions, or IPC mechanisms that may only be fulfilled by closed-source | |
| components. | |
| Optional artifacts, e.g. `workmanager-gcm`, *may* depend on closed-source | |
| components or configure a primary artifact to be backed by a closed-source | |
| component via service discovery or initialization. | |
| Some examples of safely depending on closed-source components include: | |
| - WorkManager's GCM Network Manager integration, which uses | |
| [manifest metadata](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:work/work-gcm/src/main/AndroidManifest.xml) | |
| for service discovery and provides an optional artifact exposing the | |
| service. | |
| - Downloadable Fonts integration with Play Services, which plugs in via a | |
| [`ContentProvider`](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:core/core/src/androidTest/java/androidx/core/provider/MockFontProvider.java) | |
| as a service discovery mechanism with developer-specified | |
| [signature verification](https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts#adding-certificates) | |
| for additional security. | |
| Note that in all cases, the developer is not *required* to use GCM or Play | |
| Services and may instead use another compatible service implementing the same | |
| publicly-defined protocols. | |
| ### Toolchain dependencies | |
| Toolchain dependencies are typically specified by the AndroidX build system and | |
| are often limited, if any, configuration on behalf of library owners. | |
| #### Kotlin language | |
| Several projects within AndroidX depend on aspects of the Kotlin compiler that | |
| do not guarantee binary compatibility, which means (1) Kotlin updates within | |
| AndroidX may be more complicated and (2) Kotlin updates may be more complicated | |
| for external clients. | |
| For this reason, we try to separate (1) and (2) by pinning the Kotlin language | |
| and API versions until the new compiler has been in use in AndroidX for at least | |
| three months. `kotlinc` only | |
| [supports three previous minor language versions](https://kotlinlang.org/docs/kotlin-evolution-principles.html#compatibility-options), | |
| therefore if we update to a `kotlinc` version that does not support the current | |
| AndroidX default `kotlinVersion`, the androidx default will be changed. | |
| Library owners *may* in limited cases update their Kotlin language version early | |
| by specifying the `kotlinVersion` DSL property: | |
| ``` | |
| androidx { | |
| kotlinVersion KOTLIN_2_2 | |
| } | |
| ``` | |
| Note that this propagates the version requirement to all dependencies and is not | |
| appropriate for low-level libraries. | |
| #### Java language (host-side) {#java-host} | |
| The Java language level determines the minimum version of the Java runtime | |
| required for lint checks and other host-side libraries like compilers. | |
| To avoid causing issues for clients, we try to separate Java compiler or runtime | |
| updates from language level by pinning the Java language level to the second | |
| most-recent stable LTS version. In extreme cases, however, we may be required to | |
| move to a more recent version because of a dependency like AGP or Gradle. | |
| Library owners *may*, in cases where clients are unable to update their Java | |
| version, temporarily pin their Java language version to a lower value by | |
| specifying the compatibility DSL properties: | |
| ``` | |
| javaExtension.apply { | |
| // TODO(b/12345678) Remove this once clients are able to update. | |
| sourceCompatibility = VERSION_17 | |
| targetCompatibility = VERSION_17 | |
| } | |
| ``` | |
| When doing so, library owners **must** file a bug and establish a timeline to | |
| un-pin and rejoin the rest of AndroidX. | |
| #### Java language (device-side) {#java-device} | |
| Currently, the highest Java language level supported for Android libraries is | |
| Java 1.8 (`VERSION_1_8`). AndroidX **does not** currently support library API | |
| desugaring, so the use of Java 8 APIs requires `minSdk 26` or higher. | |
| #### Android SDK {#compile-sdk} | |
| Similar to our library dependency versioning policy, libraries should depend on | |
| the lowest `compileSdk` version that provides the APIs needed by the library. | |
| We try to avoid unnecessary SDK upgrades because raising a library's | |
| `compileSdk` implicitly raises its `minCompileSdk`, which means that clients are | |
| required to raise their own `compileSdk`. This often requires updating Android | |
| Gradle Plugin, which can turn into a long process of upgrading many other | |
| dependencies. |