1## Modules {#module} 2 3### Packaging and naming {#module-naming} 4 5Java packages within Jetpack follow the format `androidx.<feature-name>`. All 6classes within a feature's artifact must reside within this package, and may 7further subdivide into `androidx.<feature-name>.<layer>` using standard Android 8layers (app, widget, etc.) or layers specific to the feature. 9 10Maven specifications use the groupId format `androidx.<feature-name>` and 11artifactId format `<feature-name>` to match the Java package. For example, 12`androidx.core.role` uses the Maven spec `androidx.core:core-role`. 13 14Sub-features that can be separated into their own artifact are recommended to 15use the following formats: 16 17- Java package: `androidx.<feature-name>.<sub-feature>.<layer>` 18- Maven groupId: `androidx.<feature-name>` 19- Maven artifactId: `<feature-name>-<sub-feature>` 20 21Gradle project names and directories follow the Maven spec format, substituting 22the project name separator `:` or directory separator `/` for the Maven 23separators `.` or `:`. For example, `androidx.core:core-role` would use project 24name `:core:core-role` and directory `/core/core-role`. 25 26Android namespaces should be unique and match the module's root Java package. If 27the root Java package is not unique, include the sub-feature name. 28 29``` 30android { 31 namespace "androidx.core.role" 32} 33``` 34 35New modules in androidx can be created using the 36[project creator script](#module-creation). 37 38NOTE Modules for OEM-implemented shared libraries (also known as extensions or 39sidecars) that ship on-device and are referenced via the `<uses-library>` tag 40should follow the naming convention `com.android.extensions.<feature-name>` to 41avoid placing `androidx`-packaged code in the platform's boot classpath. 42 43#### Maven name and description 44 45The `name` and `description` fields of the `androidx` configuration block are 46used to generate Maven artifact metadata, which is displayed on the artifact's 47maven.google.com entry and d.android.com landing page. 48 49``` 50androidx { 51 name = "WorkManager Kotlin Extensions" 52 description = "Kotlin-friendly extensions for WorkManager." 53} 54``` 55 56The name should be a human-readable, title-cased representation of the 57artifact's Maven coordinate. All components of the name **must** appear in the 58artifact's Maven group or artifact ID, with some exceptions: 59 60- Marketing names may be shortened when used in the Maven group or artifact 61 ID, ex. "WorkManager" as `work`, "Android for Cars" as `car`, or "Kotlin 62 Extensions" as `ktx` 63- Long (>10 character) words may be truncated to a short (>5 character) prefix 64- Pluralization may be changed, ex. "Views" as `view` 65- The following descriptive terms may appear in the name: 66 - "extension(s)" 67 - "for" 68 - "integration" 69 - "with" 70 71**Do not** use the following terms in the name: 72 73- "AndroidX" 74- "Library" 75- "Implementation" 76 77The description should be a single phrase that completes the sentence, "This 78library provides ...". This phrase should provide enough description that a 79developer can decide whether they might want to learn more about using your 80library. **Do not** simply repeat the name of the library. 81 82#### Project directory structure {#module-structure} 83 84Libraries developed in AndroidX follow a consistent project naming and directory 85structure. 86 87Library groups should organize their projects into directories and project names 88(in brackets) as: 89 90``` 91<feature-name>/ 92 <feature-name>-<sub-feature>/ [<feature-name>:<feature-name>-<sub-feature>] 93 samples/ [<feature-name>:<feature-name>-<sub-feature>-samples] 94 integration-tests/ 95 testapp/ [<feature-name>:testapp] 96 testlib/ [<feature-name>:testlib] 97``` 98 99For example, the `navigation` library group's directory structure is: 100 101``` 102navigation/ 103 navigation-benchmark/ [navigation:navigation-benchmark] 104 ... 105 navigation-ui/ [navigation:navigation-ui] 106 navigation-ui-ktx/ [navigation:navigation-ui-ktx] 107 integration-tests/ 108 testapp/ [navigation:integration-tests:testapp] 109``` 110 111#### Project creator script {#module-creation} 112 113Note: The terms *project*, *module*, and *library* are often used 114interchangeably within AndroidX, with *project* being the technical term used by 115Gradle to describe a build target, e.g. a library that maps to a single AAR. 116 117New projects can be created using our 118[project creation script](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:development/project-creator/?q=project-creator&ss=androidx%2Fplatform%2Fframeworks%2Fsupport) 119available in our repo. 120 121It will create a new project with the proper structure and configuration based 122on your project needs! 123 124To use it, first install the virtualenv if it is not already installed 125 126* (Linux) `sudo apt-get install virtualenv python3-venv` 127* (Mac) `pip3 install virtualenv` 128* (Mac homebrew) `brew install virtualenv` 129 130Then run the script: 131 132```sh 133cd ~/androidx-main/frameworks/support && \ 134./development/project-creator/create_project.sh androidx.foo foo-bar 135``` 136 137If the module you are creating is an application (not a library), such as you 138might want for integration-tests, edit the project's `build.gradle` file and 139replace the plugin `id("com.android.library")` with 140`id("com.android.application")`. This allows you to run activities in that 141module from within Android Studio. 142 143If you are creating an unpublished module such as an integration test app with \ 144the project creator script, it may not make sense to follow the same naming \ 145conventions as published libraries. In this situation it is safe to comment out 146\ 147the `artifact_id` validation from the script or rename the module after it has \ 148been created. 149 150#### Common sub-feature names {#module-naming-subfeature} 151 152* `-testing` for an artifact intended to be used while testing usages of your 153 library, e.g. `androidx.room:room-testing` 154* `-core` for a low-level artifact that *may* contain public APIs but is 155 primarily intended for use by other libraries in the group 156* `-common` for a low-level, platform-agnostic Kotlin multi-platform artifact 157 intended for both client use and use by other libraries in the group 158* `-ktx` for a Kotlin artifact that exposes idiomatic Kotlin APIs as an 159 extension to a Java-only library. Note that new modules should be written in 160 Kotlin rather than using `-ktx` artifacts. 161* `-samples` for sample code which can be inlined in documentation (see 162 [Sample code in Kotlin modules](#sample-code-in-kotlin-modules) 163* `-<third-party>` for an artifact that integrates an optional third-party API 164 surface, e.g. `-proto`, `-guava`, or `-rxjava2`. This is common for Kotlin 165 libraries adapting their async APIs for Java clients. Note that a major 166 version is included in the sub-feature name (ex. `rxjava3`) for third-party 167 API surfaces where the major version indicates binary compatibility (only 168 needed for post-1.x). 169 170Artifacts **should not** use `-impl` or `-base` to indicate that a library is an 171implementation detail shared within the group. Instead, use `-core` or `-common` 172as appropriate. 173 174#### Splitting existing modules 175 176Use caution when splitting existing modules into smaller modules; doing so 177creates the potential for class duplication issues when a developer depends on a 178new sub-module alongside the older top-level module. Consider the following 179scenario: 180 181* `androidx.library:1.0.0` 182 * contains class `androidx.library.A` 183 * contains class `androidx.library.util.B` 184 185This module is split, moving `androidx.library.util.B` to a new module: 186 187* `androidx.library:1.1.0` 188 * contains class `androidx.library.A` 189 * depends on `androidx.library.util:1.1.0` 190* `androidx.library.util:1.1.0` 191 * contains class `androidx.library.util.B` 192 193A developer writes an app that depends directly on `androidx.library.util:1.1.0` 194and also transitively pulls in `androidx.library:1.0.0`. Their app will no 195longer compile due to class duplication of `androidx.library.util.B`. 196 197To avoid this issue make sure to define a 198[dependency constraint](/docs/api_guidelines/index.md#dependencies-constraints) 199on`androidx.library:1.1.0` from inside `androidx.library.util:1.1.0`. This 200ensures that if a developer depends on `androidx.library.util:1.1.0`, the 201minimum version of `androidx.library` will be `1.1.0`, avoiding the class 202duplication. 203 204Same-version groups already have constraints defined, so existing modules that 205are already in a same-version group may be split into sub-modules provided that 206(a) the sub-modules are also in the same-version group and (b) the full API 207surface of the existing module is preserved through transitive dependencies, 208e.g. the sub-modules are added as dependencies of the existing module. 209 210#### Same-version (atomic) groups {#modules-atomic} 211 212Library groups are encouraged to opt-in to a same-version policy whereby all 213libraries in the group use the same version and express exact-match dependencies 214on libraries within the group. Such groups must increment the version of every 215library at the same time and release all libraries at the same time. 216 217Atomic groups are specified in 218[libraryversions.toml](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:libraryversions.toml): 219 220``` 221// Non-atomic library group 222APPCOMPAT = { group = "androidx.appcompat" } 223// Atomic library group 224APPSEARCH = { group = "androidx.appsearch", atomicGroupVersion = "versions.APPSEARCH" } 225``` 226 227Libraries within an atomic group should not specify a version in their 228`build.gradle`: 229 230```groovy 231androidx { 232 name = 'AppSearch' 233 publish = Publish.SNAPSHOT_AND_RELEASE 234 mavenGroup = LibraryGroups.APPSEARCH 235 inceptionYear = '2019' 236 description = 'Provides local and centralized app indexing' 237} 238``` 239 240The benefits of using an atomic group are: 241 242- Easier for developers to understand dependency versioning 243- `@RestrictTo(LIBRARY_GROUP)` APIs are treated as private APIs and not 244 tracked for binary compatibility 245- `@RequiresOptIn` APIs defined within the group may be used without any 246 restrictions between libraries in the group 247 248Potential drawbacks include: 249 250- All libraries within the group must be versioned identically at head 251- All libraries within the group must release at the same time 252 253#### Early-stage development {#modules-atomic-alpha} 254 255There is one exception to the same-version policy: newly-added libraries within 256an atomic group may be "quarantined" from other libraries to allow for rapid 257iteration until they are API-stable. For example: 258 259```groovy 260androidx { 261 name = "androidx.emoji2:emoji2-emojipicker" 262 mavenVersion = LibraryVersions.EMOJI2_QUARANTINE 263} 264``` 265 266```groovy 267EMOJI2_QUARANTINE = "1.0.0-alpha01" 268``` 269 270A quarantined library must stay within the `1.0.0-alphaXX` cycle until it is 271ready to conform to the same-version policy. While in quarantime, a library is 272treated at though it is in a separate group from its nomical same-version group: 273 274- Must stay in `1.0.0-alphaXX`, e.g. same-version policy is not enforced 275- May use `project` or pinned version dependencies, e.g. strict-match 276 dependencies are not enforced 277- May release on a separate cadence from other libraries within group 278- Must not reference restricted `LIBRARY-GROUP`-scoped APIs 279 280When the library would like to leave quarantine, it must wait for its atomic 281group to be within a `beta` cycle and then match the version. It is okay for a 282library in this situation to skip versions, e.g. move directly from 283`1.0.0-alpha02` to `2.1.3-beta06`. 284 285#### Kotlin Multiplatform library versions {#modules-kmp-versioning} 286 287When a library adds [Kotlin Multiplatform](/docs/kmp.md) 288support, it is permitted to have different versions for the multiplatform 289artifacts until they reach alpha quality. 290 291##### Atomic Kotlin Multiplatform versions 292 293To specify an atomic version group for the Kotlin Multiplatform artifacts, use 294the `multiplatformGroupVersion` property in the `libraryversions.toml` file. 295 296``` 297[versions] 298DATASTORE = "1.2.3" 299DATASTORE_KMP = "1.2.3-dev05" 300[groups] 301DATASTORE = { group = "androidx.datastore", atomicGroupVersion = "versions.DATASTORE", multiplatformGroupVersion = "versions.DATASTORE_KMP" } 302``` 303 304Note that you can specify a `multiplatformGroupVersion` if and only if you are 305also specifying a `atomicGroupVersion`. 306 307##### Non-atomic Kotlin Multiplatform versions 308 309If your Kotlin Multiplatform Library does not have atomic version groups, you 310can specify a KMP specifc version in the `build gradle` file: 311 312```groovy 313import androidx.build.KmpPlatformsKt 314... 315 316androidx { 317 name = "Collection" 318 type = LibraryType.KMP_LIBRARY 319 mavenGroup = LibraryGroups.COLLECTION 320 mavenVersion = KmpPlatformsKt.enableNative(project) ? LibraryVersions.COLLECTION_KMP : LibraryVersions.KMP 321 inceptionYear = "2018" 322 description = "Standalone efficient collections." 323} 324``` 325 326### Choosing a `minSdkVersion` {#module-minsdkversion} 327 328The recommended minimum SDK version for new Jetpack libraries is currently 329**23** (Android 6.0, Marshmallow). This SDK was chosen to represent 99% of 330active devices based on Play Store check-ins (see Android Studio 331[distribution metadata](https://dl.google.com/android/studio/metadata/distributions.json) 332for current statistics). This maximizes potential users for external developers 333while minimizing the amount of overhead necessary to support legacy versions. 334 335However, if no explicit minimum SDK version is specified for a library, the 336default is **21** (Android 5.0, Lollipop). 337 338Note that a library **must not** depend on another library with a higher 339`minSdkVersion` that its own, so it may be necessary for a new library to match 340its dependent libraries' `minSdkVersion`. 341 342Individual modules may choose a higher minimum SDK version for business or 343technical reasons. This is common for device-specific modules such as Auto or 344Wear. 345 346Individual classes or methods may be annotated with the 347[@RequiresApi](https://developer.android.com/reference/android/annotation/RequiresApi.html) 348annotation to indicate divergence from the overall module's minimum SDK version. 349Note that this pattern is *not recommended* because it leads to confusion for 350external developers and should be considered a last-resort when backporting 351behavior is not feasible. 352 353### Platform extension (sidecar JAR) libraries {#module-extension} 354 355Platform extension or "sidecar JAR" libraries ship as part of the Android system 356image and are made available to developers through the `<uses-library>` manifest 357tag. 358 359Interfaces for platform extension libraries *may* be defined in Jetpack, like 360`androidx.window.extensions`, but must be implemented in the Android platform 361via AOSP or by device manufacturers. See 362[WindowManager Extensions](https://source.android.com/docs/core/display/windowmanager-extensions) 363for more details on the platform-side implementation of extension libraries, 364including motivations for their use. 365 366See 367[Platform extension (sidecar JAR) dependencies](/docs/api_guidelines#dependencies-sidecar) 368for guidelines on depending on extension libraries defined externally or within 369Jetpack. 370 371### Framework- and language-specific libraries (`-ktx`, `-guava`, etc.) {#module-ktx} 372 373New libraries should prefer Kotlin sources with built-in Java compatibility via 374`@JvmName` and other affordances of the Kotlin language. They may optionally 375expose framework- or language-specific extension libraries like `-guava` or 376`-rxjava3`. 377 378Existing Java-sourced libraries may benefit from extending their API surface 379with Kotlin-friendly APIs in a `-ktx` extension library. 380 381Extension libraries **may only** provide extensions for a single base library's 382API surface and its name **must** match the base library exactly. For example, 383`work:work-ktx` may only provide extensions for APIs exposed by `work:work`. 384 385Additionally, an extension library **must** specify an `api`-type dependency on 386the base library and **must** be versioned and released identically to the base 387library. 388 389Extension libraries *should not* expose new functionality; they should only 390provide language- or framework-friendly versions of existing library 391functionality. 392