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 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.
API Lint 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 using m checkapi . To run the tool from a Jetpack checkout, run the ./gradlew checkApi task.
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.
This category pertains to the core aspects of an Android API.
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:
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?”
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 feature flag using the @FlaggedApi annotation.
Note: For FAQ on API flagging, please visit FAQ on API Flagging page.
APIs generated by tools must follow the API guidelines just the same as hand-written code.
Tools that are discouraged for generating APIs:
This category pertains to the general coding style that developers should use, especially in the public API.
Android's platform coding conventions are documented for external contributors here:
Overall, we tend to follow standard Java coding conventions.
Please also review the Kotlin-Java interop guide 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.
For example: method name should be runCtsTests and not runCTSTests .
This exposes implementation details, avoid that.
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:
See the official Android Kotlin-Java interop guide for a full list of guidelines. Select guidelines have been copied to this guide to improve discoverability.
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 or Async guide for specific guidance.
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 with @JvmField and public functions with @JvmStatic to expose them directly on the containing class.
companion object @JvmField val BIG_INTEGER_ONE = BigInteger.ONE @JvmStatic fun fromPointF(pointf: PointF) /* . */ > >
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.
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.
name="foo"> name="name" type="xs:string"> name="Deprecated"/>
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.
name="foo"> name="name" type="xs:string"> name="Deprecated"/> name="fooChoice"> name="name" type="xs:string"/>