| # 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 as part of the |
| platform build. You can run it manually from an |
| [AOSP platform checkout](https://source.android.com/setup/build/downloading) |
| using `m checkapi`. To run the tool from a Jetpack checkout, run the `./gradlew |
| checkApi` task. |
| |
| ## API rules {#rules} |
| |
| One of the difficulties in concrete rules is applying them to a platform that |
| was developed without strict guidelines from the beginning, so some of the |
| existing APIs may not adhere. In some cases, the right choice might be to go |
| with what is consistent with APIs in the same general area of the code, rather |
| than in the ideal rules laid out herein. |
| |
| The rules are a work in progress and will be added to in the future as other |
| patterns emerge from future API reviews. |
| |
| ## 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. Merging API stubs with |
| implementation to come at a later date would be a violation of this guideline. |
| |
| 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 CTS requirements and implementation expectation. |
| |
| Testing API surfaces provides a base guarantee that the API surface is usable |
| and we've exposed all the necessary aspects. Testing for existence is not |
| sufficient; the API functionality itself must be tested. |
| |
| A change that adds a new API should include corresponding CTS tests in the same |
| Gerrit topic. This is enforced 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 platform APIs must be associated with a flag <a name="basics-flagged"></a> |
| |
| All platform APIs must be associated with a |
| [feature flag](http://go/android-flags) using the |
| [@FlaggedApi annotation][flaggedapi]. |
| |
| [flaggedapi]: https://source.corp.google.com/h/googleplex-android/platform/superproject/main/+/main:frameworks/libs/modules-utils/java/android/annotation/FlaggedApi.java?q=symbol%3A%5Cbandroid.annotation.FlaggedApi%5Cb%20case%3Ayes |
| |
| Note: For FAQ on API flagging, please visit |
| [FAQ on API Flagging](/api-guidelines/faq.md) |
| page. |
| |
| ### All generated APIs must be compliant with the guidelines <a name="basics-auto-generated-code"></a> |
| |
| APIs generated by tools must follow the API guidelines just the same 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. |
| - [codegen](http://go/android-codegen): |
| [does not work well with `@FlaggedApi`](https://g3doc.corp.google.com/api-guidelines/faq.md#i-cannot-use-flaggedapi-with-data-classes-generated-by-codegen) |
| |
| ## Coding style [S] <a name="style"></a> |
| |
| This category pertains to the general coding style that developers should use, |
| especially in the public API. |
| |
| ### Follow standard Java coding conventions, except where noted <a name="style-conventions"></a> |
| |
| Android's platform coding conventions are documented for external contributors |
| here: |
| |
| https://source.android.com/source/code-style.html |
| |
| Overall, we tend to follow standard Java coding conventions. |
| |
| Please also review the |
| [Kotlin-Java interop guide](https://developer.android.com/kotlin/interop) for |
| best practices related to writing Kotlin-friendly APIs in Java. Some of these |
| guidelines are reflected in the recommendations on this site; however, the link |
| may contain slightly newer information that has not yet been propagated. |
| |
| ### 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 |
| |
| 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 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. |
| |
| ### Deprecation best-practices <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"--> |