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