Zygote
Evolutionintermediate

Reading the SDK

An API level is a boundary in a very large surface. This page teaches the four primary sources — the reference, the API diff, the platform source and the behaviour notes — and how to read each one without being misled by what it leaves out.

12 minAPI 1–37 · 17interactivequizverified 2026-10-27

The Android SDK is one of the largest public APIs ever shipped, and it changes every year. "Read the SDK" is not a metaphor: there are documents that tell you exactly what changed, and they are generated from the SDK itself. The skill is knowing which document answers which question, and where each one is allowed to lie to you.

TL;DR#

  • The android.jar you compile against is the contract. Reference docs describe it; the API diff enumerates its changes; neither is more authoritative than the stub itself.
  • compileSdk, targetSdk and minSdk are three different questions: what you build against, what behaviour you opt into, and what devices can install you.
  • An API diff is generated per level and lists additions, changes and removals. It is the most precise record of the public surface, and it says nothing about behaviour.
  • The platform source (cs.android.com) documents what the framework actually does, including everything the reference docs omit. It is not a contract, but it is the truth.
  • Deprecation is a warning, not a removal. The API you are told not to use will usually still work for years, which is both a comfort and a trap.

Mental model#

Think of the SDK as a very large public library.

The catalogue is the reference documentation: entries for every book, with a description of what each is for. It is useful for finding things, and it is written by humans, so it lags.

The accessions list is the API diff: what arrived, what changed shelfmark, what was withdrawn this year. It is generated mechanically from the shelves themselves, so it is complete and boring and trustworthy about existence.

The books are the platform source. When the catalogue description disagrees with the book, the book wins.

The librarian's notices are the behaviour-change documents: "from this year, this reading room works differently". They are the only source that tells you what happens when you use an API, as opposed to whether it exists.

Where the analogy breaks#

A library's catalogue and its shelves describe the same objects. The Android SDK has a third thing that neither describes: the runtime behaviour behind the API, which can change without the signature changing at all. PackageManager can gain a new restriction on an existing method, and no API diff will show it. That is why behaviour-change documents exist as a separate genre, and why "it compiles" is never the same claim as "it works".

The big picture#

Loading diagram…
Text description of this diagram

The Time Machine at a selected API level. A slider runs from API 1 to API 37. For each level it shows the release card with the version, dessert name where one existed, date and headline features; a developer's-world card listing the UI toolkit, language, IDE, build system, background API and async model in use at that level; and a behaviour card listing the changes introduced at that level, each marked as applying to all apps or only to apps targeting that level. A diff mode compares any two API levels side by side and highlights the rows that differ.

That diagram is the fastest way to build intuition for how much changes per level. Step it from API 21 to 37 and watch the developer's world change: the language, the UI toolkit, the background API. None of those changes appear in a single API diff, because each is spread over several levels.

Deep dive#

The three numbers#

Every Android build declares three API levels, and conflating them is the most common source of confusion about "which Android version does this support".

minSdk is the lowest API level the app will install on. The package manager refuses the install below it. It is a product decision: raise it and you drop devices; lower it and you must guard every newer API with a runtime check.

compileSdk is the SDK the app is compiled against. It determines which classes, methods and constants exist at compile time. It must be greater than or equal to targetSdk, because you cannot target behaviour you did not compile against.1

targetSdk is the compatibility contract: it tells the platform which behaviour changes the app has opted into. This is the number that matters most and is understood least. A change marked "for apps targeting API 36 or higher" does not apply to an app with targetSdk = 35, even on a device running API 37.

A useful way to hold all three: minSdk is where you run, compileSdk is what you know, targetSdk is what you promise to handle.

The API diff#

The API diff reports are generated per level and enumerate every class, method and field added, changed or removed between two API levels.3 They are the closest thing to a changelog of the public surface, and they are mechanical: if a method exists in the new stub and not the old one, it appears.

Read an API diff in this order:

  1. Removals first. These are rare and they are the ones that break builds.
  2. Signature changes. A parameter type or return type change is a source-incompatible change even when the method name survives.
  3. Additions by package. This is where you find the new capability, and grouping by package tells you which subsystem is being invested in.
  4. Deprecations. These are annotations rather than removals, and they signal direction.

What an API diff cannot tell you: whether a method's behaviour changed, whether a new restriction was added to an existing method, or whether a feature is gated behind a flag. Those live in the behaviour-change documents and, ultimately, in the source.

Reading the platform source#

The reference documentation describes intent. The source describes implementation. When they disagree, source wins, and cs.android.com is the fastest way to get there.4

Three habits make source reading productive:

Read the interface, then the implementation. For a framework API, the public class in frameworks/base/core/java/ is usually a thin shell over a service in frameworks/base/services/. A method on PackageManager often does nothing but parcel its arguments and call a Binder proxy.

Follow the Binder boundary. Every Manager class has a corresponding service. Find the Stub/Proxy pair generated from AIDL, and the service method is on the other side. That is usually where the actual policy lives.

Check the annotations. @SystemApi, @hide, @Deprecated and the @RequiresPermission annotation tell you who the API is for. A @hide method is not part of the contract even though you can see it in the source, and reflecting into it is exactly what non-SDK restrictions exist to stop.

Deprecation, removal and the graveyard#

Android almost never removes a public API. Deprecated APIs stay because installed apps depend on them, and an app that cannot be updated still has to run. AsyncTask was deprecated in Android 11 and is still present. This produces a strange landscape where the documentation tells you not to use something that works perfectly well and will keep working.

The practical rules:

  • Deprecated means "there is a better way", not "this is broken". Migrate when you have a reason; do not panic-migrate.
  • Removal happens at the level of behaviour, not signatures. A method can remain and stop doing what it did, especially when a permission or background restriction lands on it.
  • Non-SDK restrictions are the real removal mechanism. Since Android 9, the platform restricts access to non-SDK interfaces, with allowlists, greylists and blocklists. An app that reflected into @hide internals can break without any public API changing.1

Reading release notes without being fooled#

Release notes are marketing documents with a technical appendix. They are useful, and they are structured to make every release look large. A few habits help:

  • Separate features from behaviour changes. A new API is optional; a behaviour change is something that happens to you. The behaviour-change page is the one that predicts breakage.
  • Check the scope tag. "For apps targeting API N" versus "for all apps" is the single most useful label in modern Android documentation.
  • Check the device gate. Some changes only apply on large screens, only on devices with a certain feature, or only when a flag is enabled.
  • Check the source when it matters. If a restriction would break your app, verify it against the platform source or a test device rather than trusting a summary.

How it evolved#

The SDK's own shape has evolved alongside the platform. Early releases added whole packages; modern releases add smaller surfaces and spend more words on behaviour.

Architecture changes12 releases
APIVersionWhat changed
268.0 Oreo
  • Project Treble: the vendor interface separates vendor and system code
  • Background execution limits
  • Broadcast and service restrictions
  • HIDL for HALs
278.1 Oreo
  • Android Go: a lighter configuration of the same platform
289 Pie
  • App Standby Buckets
  • Mainline groundwork
  • Non-SDK interface restrictions (greylists) begin
  • BiometricPrompt
2910
  • Project Mainline: APEX and updatable system modules
  • Scoped storage
  • Bubbles
  • Project Mainline starts shipping through Play
3011
  • GKI: the Generic Kernel Image splits the kernel into core + vendor modules
  • App hibernation
  • Package visibility filtering
  • Incremental app installs
3112
  • Bluetooth permissions split into the nearby-devices family
  • Exact alarm permissions
  • Foreground service launch restrictions
3212L
  • Window size classes and activity embedding
3313 Tiramisu
  • Granular media permissions replace READ_EXTERNAL_STORAGE
  • The notification permission becomes a runtime permission
  • Predictive back gesture
3414 Upside Down Cake
  • Foreground service types are mandatory
  • Selected photos access via READ_MEDIA_VISUAL_USER_SELECTED
3515 Vanilla Ice Cream
  • 16 KB page size support for native libraries
  • Edge-to-edge is enforced when targeting 35
3616 Baklava
  • The release moves to Q2 (June) with a Q4 feature drop
  • Two SDK releases per year starting with 36
  • Desktop windowing arrives in developer options then stable
3717 Cinnamon Bun
  • Strict per-device app memory limits are enforced by the system
  • Generational garbage collection is added to ART's Concurrent Mark-Compact collector
  • A lock-free MessageQueue for apps targeting API 37
  • Compose-first: new platform and Jetpack APIs target Compose only; View libraries enter maintenance mode
  • Hybrid APK signing (v3.2) combines classical and ML-DSA post-quantum signatures
  • Native library dynamic code loading must be read-only

The trend across those rows is consistent: since Treble, a growing share of "what changed" is about targetSdk-gated behaviour rather than new classes. That is not an accident. As the API surface matures, the leverage moves from adding capability to changing defaults safely.

Under the hood#

Curiosity corner#

  • The API surface is enormous and grows every year. The API Explorer on this site charts classes added per level from the machine-readable API history; the curve is not linear.
  • compileSdk can be higher than the device's API level. You can compile against 37 and run on a device at 30, as long as you guard the calls — which is what minSdk and runtime checks are for.
  • Two API levels can share a marketing version. Android 12 is API 31, Android 12L is API 32.

Try it#

Package SDK levels
adb shell getprop ro.build.version.sdk
adb shell dumpsys package com.android.settings | grep -E "minSdk|targetSdk"
adb shell cmd package resolve-activity --brief android.intent.action.MAIN
Example output
Illustrative output — package names and numbers differ per device.

Build it#

B02 — Intent explorer is a small app that prints the resolved component and the declaring package for an intent, which is the practical version of "read the package manager instead of guessing".

Check yourself#

Check yourself

1 / 12

What does an API level identify?

0 answered · 0 correct

Sources#

Sources

Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.

  1. docs<uses-sdk> | App architecturedeveloper.android.comaccessed 2026-10-27↩
  2. docsTarget API level requirements for Google Play appsdeveloper.android.comaccessed 2026-10-27↩
  3. docsAPI Differences between 35 and 36developer.android.comaccessed 2026-10-27↩
  4. sourceAndroid Code Search (cs.android.com)cs.android.comaccessed 2026-10-27↩
  5. docsAndroid releases and versionsdeveloper.android.comaccessed 2026-10-27↩
  6. sourceAndroid Gerrit code reviewandroid-review.googlesource.comaccessed 2026-10-27↩
  7. wikiAndroid version historyWikipediaaccessed 2026-10-27↩