| # Android API Guidelines |
| |
| This document is intended to be a guide for developers to understand the general |
| principles that the API Council enforces in API reviews. |
| |
| In addition to following these guidelines when writing APIs, developers should |
| run the [API Lint](#apilint) tool, which encodes many of these rules in checks |
| that it runs against APIs. |
| |
| Think of this as the guide to the rules that are obeyed by that Lint tool, plus |
| general advice on rules that cannot be easily codified into that tool. |
| |
| [TOC] |
| |
| ## API Lint tool {#apilint} |
| |
| [API Lint](https://source.corp.google.com/h/googleplex-android/platform/superproject/main/+/main:tools/metalava/src/main/java/com/android/tools/metalava/ApiLint.kt) |
| is integrated into the Metalava static analysis tool and runs automatically |
| during validation in CI. You can run it manually from a local |
| [platform checkout](https://source.android.com/setup/build/downloading) using `m |
| checkapi` or a local AndroidX checkout using |
| `./gradlew :path:to:project:checkApi`. |
| |
| ## API rules {#rules} |
| |
| The Android platform and many Jetpack libraries existed before this set of |
| guidelines was created, and the policies set forth below are continually |
| evolving to meet the needs of the Android ecosystem. |
| |
| As a result, some existing APIs may not follow the guidelines. In other cases, |
| it might provide a better user experience for app developers if a new API stays |
| consistent with existing APIs rather than strictly adhere to the guidelines. |
| |
| Use your judgement and reach out to API Council if there are difficult questions |
| about an API that need to be resolved or guidelines that need to be updated. |
| |
| ## API basics <a name="basics"></a> |
| |
| This category pertains to the core aspects of an Android API. |
| |
| ### All APIs must be implemented <a name="basics-implemented"></a> |
| |
| Irrespective of an API's audience (public, `@SystemApi`, etc.), all API surfaces |
| must be implemented when merged or exposed as API. Do not merge API stubs with |
| implementation to come at a later date. |
| |
| Unimplemented API surfaces have multiple issues: |
| |
| - There is no guarantee that a proper or complete surface has been exposed. |
| Until an API is tested or used by clients, there is no way to verify a |
| client has the appropriate APIs to be able to use the feature. |
| - APIs without implementation cannot be tested in Developer Previews |
| - APIs without implementation cannot be tested in CTS |
| - By definition, APIs without implementation are not IC complete |
| |
| ### All APIs must be tested <a name="basics-tested"></a> |
| |
| This is in line with platform CTS requirements, AndroidX policies, and generally |
| the idea that APIs must be implemented. |
| |
| Testing API surfaces provides a base guarantee that the API surface is usable |
| and we have addressed expected use cases. Testing for existence is not |
| sufficient; the API functionality itself must be tested. |
| |
| A change that adds a new API should include corresponding tests in the same CL |
| or Gerrit topic. This is enforced in the platform by go/api-test-coverage |
| presubmit. |
| |
| APIs should also be *testable*. You should be able to answer the question, "How |
| will an app developer test code that uses your API?" |
| |
| ### All APIs must be documented <a name="basics-documented"></a> |
| |
| Documentation is a key part of API usability. While the syntax of an API surface |
| may seem obvious, any new clients will not understand the semantics, behavior, |
| or context behind the API. |
| |
| ### All generated APIs must be compliant with the guidelines <a name="basics-auto-generated-code"></a> |
| |
| APIs generated by tools must follow the same API guidelines as hand-written |
| code. |
| |
| Tools that are discouraged for generating APIs: |
| |
| - `AutoValue`: violates guidelines in various ways, e.g., there is no way to |
| implement final value classes nor final builders with the way AutoValue |
| works. |
| |
| ## Coding style <a name="style"></a> |
| |
| This category pertains to the general coding style that developers should use, |
| especially when writing public APIs. |
| |
| ### Follow standard coding conventions, except where noted <a name="style-conventions"></a> |
| |
| Android coding conventions are documented for external contributors here: |
| |
| https://source.android.com/source/code-style.html |
| |
| Overall, we tend to follow standard Java and Kotlin coding conventions. |
| |
| ### Acronyms should not be capitalized in method names <a name="acronyms-in-method-name"></a> |
| |
| For example: method name should be `runCtsTests` and not `runCTSTests`. |
| |
| ### Names shouldn't end with `Impl` <a name="dont-end-with-impl"></a> |
| |
| This exposes implementation details, avoid that. |
| |
| <!--#include file="/api-guidelines/classes.md"--> |
| |
| <!--#include file="/api-guidelines/methods.md"--> |
| |
| <!--#include file="/api-guidelines/docs.md"--> |
| |
| <!--#include file="/api-guidelines/framework.md"--> |
| |
| ## Services <a name="services"></a> |
| |
| ### Handling `Intent`s in system-bound developer services <a name="services-intents"></a> |
| |
| Services that are intended to be extended by the developer and bound by the |
| system, for example abstract services like `NotificationListenerService`, may |
| respond to an `Intent` action from the system. Such services should meet the |
| following criteria: |
| |
| 1. Define a `SERVICE_INTERFACE` string constant on the class containing the |
| fully-qualified class name of the service. This constant must be annotated |
| with `@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)`. |
| 1. Document on the class that a developer must add an `<intent-filter>` to |
| their `AndroidManifest.xml` in order to receive Intents from the platform. |
| 1. Strongly consider adding a system-level permission to prevent rogue apps |
| from sending `Intent`s to developer services. |
| |
| ## Kotlin-Java interop <a name="kotin-interop"></a> |
| |
| See the official Android |
| [Kotlin-Java interop guide](https://developer.android.com/kotlin/interop) for a |
| full list of guidelines. Select guidelines have been copied to this guide to |
| improve discoverability. |
| |
| ### API visibility {#kotlin-interop-visibility} |
| |
| Some Kotlin APIs, like `suspend fun`s, aren't intended to be used by Java |
| developers; however, *do not* attempt to control language-specific visibility |
| using `@JvmSynthetic` as it has side-effects on how the API is presented in |
| debuggers that make debugging more difficult. |
| |
| Please see the |
| [Kotlin-Java interop guide](https://developer.android.com/kotlin/interop) or |
| [Async guide](/api-guidelines/async.md) for |
| specific guidance. |
| |
| ### Companion objects {#kotlin-interop-companion} |
| |
| Kotlin uses `companion object` to expose static members. In some cases, these |
| will show up from Java on an inner class named `Companion` rather than on the |
| containing class. `Companion` classes may show as empty classes in API text |
| files -- that is working as intended. |
| |
| To maximize compatibility with Java, annotate companion objects' |
| [non-`const` fields](https://developer.android.com/kotlin/interop#companion_constants) |
| with `@JvmField` and |
| [public functions](https://developer.android.com/kotlin/interop#companion_functions) |
| with `@JvmStatic` to expose them directly on the containing class. |
| |
| ```kotlin {.good .no-copy} |
| companion object { |
| @JvmField val BIG_INTEGER_ONE = BigInteger.ONE |
| @JvmStatic fun fromPointF(pointf: PointF) { |
| /* ... */ |
| } |
| } |
| ``` |
| |
| <!--#include file="/api-guidelines/evolution.md"--> |
| |
| ## XML schemas <a name="xml"></a> |
| |
| If an XML schema serves as a stable interface between components, that schema |
| must be explicitly specified and must evolve in a backward-compatible manner, |
| similar to other Android APIs. For example, the structure of XML elements and |
| attributes must be preserved similar to how methods and variables are maintained |
| on other Android API surfaces. |
| |
| NOTE API Council does not explicitly review XML schemas and AOSP does not have |
| tooling to automatically ensure compatibility for XML schemas or parsing. |
| Proceed with caution. |
| |
| ### XML deprecation <a name="xml-deprecation"></a> |
| |
| If you'd like to deprecate an XML element or attribute, you can add the |
| `xs:annotation` marker, but you must continue to support any existing XML files |
| by following the typical `@SystemApi` evolution lifecycle. |
| |
| ```xml {.no-copy} |
| <xs:element name="foo"> |
| <xs:complexType> |
| <xs:sequence> |
| <xs:element name="name" type="xs:string"> |
| <xs:annotation name="Deprecated"/> |
| </xs:element> |
| </xs:sequence> |
| </xs:complexType> |
| </xs:element> |
| ``` |
| |
| ### Element types must be preserved <a name="xml-element-types"></a> |
| |
| Schemas support the `sequence` element, `choice` element and `all` elements as |
| child elements of `complexType` element. However, these child elements differ in |
| the number and order of their child elements, so modifying an existing type |
| would be an incompatible change. |
| |
| If you want to modify an existing type, the best-practice is to deprecate the |
| old type and introduce a new type to replace it. |
| |
| ```xml {.no-copy} |
| <!-- Original "sequence" value --> |
| <xs:element name="foo"> |
| <xs:complexType> |
| <xs:sequence> |
| <xs:element name="name" type="xs:string"> |
| <xs:annotation name="Deprecated"/> |
| </xs:element> |
| </xs:sequence> |
| </xs:complexType> |
| </xs:element> |
| |
| <!-- New "choice" value --> |
| <xs:element name="fooChoice"> |
| <xs:complexType> |
| <xs:choice> |
| <xs:element name="name" type="xs:string"/> |
| </xs:choice> |
| </xs:complexType> |
| </xs:element> |
| ``` |
| |
| <!--#include file="/api-guidelines/mainline.md"--> |