
在 Android Studio 里看到 minSdk = 23,测试同事说手上的设备是 Android 13,构建日志又提示需要 JDK 17:这几个数字之间到底怎么换算?这台设备能安装应用吗?
一句话结论:Android 版本号对应平台 API Level,JDK 版本属于 Java 工具链,两者没有一一对应关系;升级适配还要分清设备系统变化和 targetSdk 触发的行为变化。
本文更新至 2026 年 10 月 28 日 ,大版本对照以已正式发布的 Android 17(API 37)为上限;Android 17 的小版本预览另行说明。版本对照依据 Android 官方 API Level 表。文末补充 Java/JDK 版本及其在 Android 构建中的作用,不展开 Android Gradle Plugin 的完整版本兼容表或应用商店的上架政策。
资料说明:本文参考了峥嵘life 于 2016 年 10 月 6 日发布的 《Android版本号和API的关系》,重新核对并编排版本表。
compileSdk、targetSdk、36.1 小版本 SDK 与逐版本适配清单,是依据 Android 官方文档补充的更新内容。
先把四个数字放在各自的位置
拿 Android 13 举例:"13"是系统版本名,"33"是它的 API Level 。设备运行 Android 13 时,Build.VERSION.SDK_INT 通常返回 33。看到"API 33 引入的类",开发者就知道它不能在 API 32 及更早的设备上直接使用。
一个应用还会在构建配置里写三个 SDK 值:
| 配置 | 回答的问题 | 举例 |
|---|---|---|
minSdk |
最低允许安装在哪个 API Level 上? | 23 表示 Android 6.0 起 |
compileSdk |
编译时能看到哪个版本及以下的 Android 平台 API? | 37 可编译引用 Android 17 的平台 API |
targetSdk |
应用针对哪个 API Level 完成适配和测试,并采用哪些受目标版本控制的系统行为? | 37 表示按 Android 17 的目标行为测试 |
这三个值不能互相代替。提高 compileSdk 不会自动提高最低安装版本,也不会自动让应用采用新版本的目标行为 ;提高 minSdk 则会缩小可安装设备范围。官方的 构建配置说明 对这三项有逐一解释。
Android 版本与 API Level 对照表
下面按官方平台版本表整理。表中的代号是 Build.VERSION_CODES 里的常量名,写版本判断时比直接写数字更容易读。注意 Android 17 对应 API 37;API 17 对应的是 Android 4.2 系列,两组数字不能直接画等号。
| Android 版本 | API Level | Build.VERSION_CODES 常量 |
|---|---|---|
| Android 17 | 37 | CINNAMON_BUN |
| Android 16 | 36 | BAKLAVA |
| Android 15 | 35 | VANILLA_ICE_CREAM |
| Android 14 | 34 | UPSIDE_DOWN_CAKE |
| Android 13 | 33 | TIRAMISU |
| Android 12L | 32 | S_V2 |
| Android 12 | 31 | S |
| Android 11 | 30 | R |
| Android 10 | 29 | Q |
| Android 9 | 28 | P |
| Android 8.1 | 27 | O_MR1 |
| Android 8.0 | 26 | O |
| Android 7.1 / 7.1.1 | 25 | N_MR1 |
| Android 7.0 | 24 | N |
| Android 6.0 | 23 | M |
| Android 5.1 | 22 | LOLLIPOP_MR1 |
| Android 5.0 | 21 | LOLLIPOP |
查老项目时,还可能遇到下面这些版本:
| Android 版本 | API Level | Build.VERSION_CODES 常量 |
|---|---|---|
| Android 4.4W(Wear) | 20 | KITKAT_WATCH |
| Android 4.4 | 19 | KITKAT |
| Android 4.3 | 18 | JELLY_BEAN_MR2 |
| Android 4.2 / 4.2.2 | 17 | JELLY_BEAN_MR1 |
| Android 4.1 / 4.1.1 | 16 | JELLY_BEAN |
| Android 4.0.3 / 4.0.4 | 15 | ICE_CREAM_SANDWICH_MR1 |
| Android 4.0~4.0.2 | 14 | ICE_CREAM_SANDWICH |
| Android 3.2 | 13 | HONEYCOMB_MR2 |
| Android 3.1 | 12 | HONEYCOMB_MR1 |
| Android 3.0 | 11 | HONEYCOMB |
| Android 2.3.3 / 2.3.4 | 10 | GINGERBREAD_MR1 |
| Android 2.3~2.3.2 | 9 | GINGERBREAD |
| Android 2.2 | 8 | FROYO |
| Android 2.1 | 7 | ECLAIR_MR1 |
| Android 2.0.1 | 6 | ECLAIR_0_1 |
| Android 2.0 | 5 | ECLAIR |
| Android 1.6 | 4 | DONUT |
| Android 1.5 | 3 | CUPCAKE |
| Android 1.1 | 2 | BASE_1_1 |
| Android 1.0 | 1 | BASE |
几个容易看错的地方:Android 12 和 12L 分别是 API 31、32;Android 7.0 与 7.1 分别是 API 24、25;Android 4.4W 的 API 20 是面向 Wear 的版本。并非每次系统补丁或界面版本变化都会让 API Level 加一。
每个 Android 版本升级后,应用要检查什么?
读适配清单前,先看触发条件:**「所有应用」指应用运行在该系统上就可能受影响; 「目标 API n」指应用在该系统上运行且 targetSdk 达到 n 时触发;「按需」**指只有使用相关能力的应用才需要处理。下面只选每代最容易影响应用的变化,完整细节以各行链接的官方文档为准。小修订版本若没有独立的通用限制,合并在同一行说明。
Android 13~17:权限、窗口和系统行为
| 版本 | 主要升级与限制 | 应用需要做的适配 |
|---|---|---|
| Android 17(API 37) | **所有应用:**系统加强应用内存限制。**目标 API 37:**大屏设备不再允许通过旧属性退出可调整大小和方向适配;访问局域网设备受 ACCESS_LOCAL_NETWORK 保护。 |
在 Android 17 设备上测内存峰值;用平板、折叠屏检查横竖屏及多窗口;有投屏、智能家居等局域网场景时,用系统选择器或按需申请局域网权限。 |
| Android 16(API 36) | **目标 API 36:**边到边显示的退出开关在 Android 16 设备上失效;预测性返回动画默认启用,旧式返回事件处理可能不再按预期触发。 | 处理状态栏、导航栏与键盘的 WindowInsets;将返回逻辑迁移到受支持的返回导航 API,检查手势返回和大屏布局。 |
| Android 15(API 35) | **目标 API 35:**界面默认绘制到系统栏下方。**所有应用:**部分设备采用 16 KB 内存页,含原生库的应用可能遇到兼容问题。 | 检查页面、弹窗和底部操作区是否被系统栏遮挡;若 APK 含 .so,按16 KB 页大小指南检查对齐并在相应设备或模拟器上测试。 |
| Android 14(API 34) | **目标 API 34:**前台服务需要声明合适的服务类型;用户可以只授权选中的照片或视频。 | 核对前台服务类型及对应权限;图片选择优先采用系统 Photo Picker,维护自建图库时处理 READ_MEDIA_VISUAL_USER_SELECTED 和授权范围变化。 |
| Android 13(API 33) | **所有应用:**通知引入 POST_NOTIFICATIONS 运行时权限。**目标 API 33:**读取其他应用的媒体文件改用图片、视频、音频的细分权限。 |
设计通知授权时机与拒绝后的体验;按用途申请 READ_MEDIA_IMAGES、READ_MEDIA_VIDEO、READ_MEDIA_AUDIO,仅选图片时优先用 Photo Picker。见目标版本行为。 |
这里最容易误判的是「所有应用」与「目标 API」的差别:例如 Android 17 的内存限制需要先在新系统上测试,局域网权限则要结合 targetSdk = 37 和实际网络用例检查。不要把每一行都理解成"所有项目必须加一项权限"。
Android 9~12L:存储、组件与后台执行
| 版本 | 主要升级与限制 | 应用需要做的适配 |
|---|---|---|
| Android 12L(API 32) | **按需:**大屏任务栏、分屏和信箱模式进一步变化;固定方向应用可能被放入兼容显示。 | 在 12L 平板或折叠屏上检查可调整大小、横竖屏切换、分屏后的状态恢复和布局留白;尽量提供自适应布局。 |
| Android 12(API 31) | **目标 API 31:**带 intent filter 的组件必须明确声明 android:exported;PendingIntent 要指定可变性;后台启动前台服务受限。**所有应用:**用户可只授予模糊位置。 |
检查合并后的 Manifest;为 PendingIntent 选 FLAG_IMMUTABLE 或确有需要时用 FLAG_MUTABLE;调整后台任务启动时机,并处理粗略位置结果。 |
| Android 11(API 30) | **目标 API 30:**分区存储进一步收紧,requestLegacyExternalStorage 不再是退出方式;查询已安装应用会被包可见性规则过滤;后台定位授权流程变化。 |
用 MediaStore、系统文件选择器或应用专属目录替代任意文件路径;仅为确有交互的包声明 <queries>;将后台定位引导到系统设置中的正式授权流程。 |
| Android 10(API 29) | **目标 API 29:**默认启用分区存储;后台定位需要独立声明 ACCESS_BACKGROUND_LOCATION。**所有应用:**后台直接启动 Activity 等隐私相关行为受到限制。 |
迁移共享文件读写到 MediaStore 或 Storage Access Framework;将定位拆成前台与后台用例;把后台提示改为通知等用户可见入口。 |
| Android 9(API 28) | **目标 API 28:**明文网络流量默认不被允许,HTTP 请求可能失败。 | 优先改用 HTTPS;确有明文服务时,在 Network Security Configuration 中仅为必要域名配置例外,并测试 WebView 与第三方 SDK 的请求。 |
从 Android 10 到 11,存储适配不能只靠保留旧 targetSdk:当目标 API 升到 30 时,Android 11 会忽略旧的 requestLegacyExternalStorage 退出标志。官方存储迁移文档列出了该边界。
Android 6~8.1:权限、文件共享与后台任务
| 版本 | 主要升级与限制 | 应用需要做的适配 |
|---|---|---|
| Android 8.1(API 27) | **按需:**改进低内存设备与自动填充等能力;没有一项适用于所有普通应用的新权限迁移。 | 低内存设备上检查启动、图片占用和后台任务;使用自动填充等新 API 时做版本判断。 |
| Android 8.0(API 26) | **目标 API 26:**通知需要频道;后台服务与多数隐式广播受到限制。 | 为通知创建频道;用 JobScheduler 或 WorkManager 承担可延迟工作,审查后台 Service 与 Manifest 广播接收器。 |
| Android 7.1(API 25) | **按需:**加入应用快捷方式、输入法富内容等 API;没有覆盖所有应用的统一强制迁移项。 | 使用快捷方式或图片输入时做 API 25 能力判断,并为旧设备保留普通入口。 |
| Android 7.0(API 24) | **目标 API 24:**向应用外暴露 file:// URI 会触发 FileUriExposedException。**所有应用:**多窗口带来窗口尺寸与生命周期变化。 |
文件共享改用 content:// URI(如 FileProvider)并授予临时访问权;测试分屏、配置变化和状态恢复。 |
| Android 6.0(API 23) | **目标 API 23:**危险权限改为运行时申请。**所有应用:**Doze 和 App Standby 会延迟网络、同步或任务执行。 | 在使用相机、定位等功能前检查并请求权限,处理拒绝与撤销;让非即时工作交给系统调度,验证待机后能否恢复。 |
Android 5.1 及以前:仅在维护老设备时适配
本文示例的 minSdk = 23 从 Android 6.0 起安装,因此下面这些版本不在该示例的测试矩阵内。如果你的产品确实还支持更低 API,再按功能使用情况处理;早期发布多是新增能力,并没有后来那样统一影响所有应用的权限迁移。
| 版本 | 主要升级与限制 | 应用需要做的适配 |
|---|---|---|
| Android 5.1(API 22) | **按需:**增加多 SIM 卡相关能力。 | 电话、短信或 SIM 业务不要假设设备只有一张卡;先判断设备能力与所需权限。 |
| Android 5.0(API 21) | **所有应用:**ART 成为默认运行时;平台支持 64 位架构。 | 老项目重点测试反射、JNI 与原生库;若含 .so,检查 ABI 覆盖情况。 |
| Android 4.4 / 4.4W(API 19 / 20) | **按需:**文件选择加入 Storage Access Framework;只有默认短信应用可写短信 Provider。API 20 为 Wear 专用版本。 | 文件选择用系统文档接口;短信应用需按默认短信应用规则工作;不要把 Wear API 20 当作手机通用版本。 |
| Android 4.3(API 18) | **按需:**加入低功耗蓝牙(BLE)平台 API。 | 使用 BLE 时先判断系统版本及设备是否具备对应蓝牙能力。 |
| Android 4.2(API 17) | 目标 API 17: ContentProvider 的 exported 默认值变为 false。 |
跨应用共享数据时明确声明 android:exported 与读写权限;内部 Provider 保持不导出。 |
| Android 4.1(API 16) | **目标 API 16:**读取或写入通话记录不再因联系人权限而自动获权。 | 确实使用通话记录时,分别检查并申请 READ_CALL_LOG / WRITE_CALL_LOG。 |
| Android 4.0 / 4.0.3(API 14 / 15) | **按需:**手机和平板界面逐步统一,导航和辅助功能 API 扩展。 | 维护旧界面时测试导航栏、主题和大小屏布局;新增 API 保留低版本分支。 |
| Android 3.x(API 11~13) | **按需:**平板界面、Action Bar 与 Fragment 成为重要平台能力。 | 仅在支持这类旧平板时验证布局和菜单;现代项目可用 AndroidX 兼容实现。 |
| Android 2.3(API 9 / 10) | **按需:**NFC、SIP 等能力加入平台,但取决于设备硬件和厂商实现。 | 使用前检查 PackageManager 设备特性,不要只凭 API Level 判定硬件存在。 |
| Android 1.6~2.2(API 4~8) | **按需:**早期多屏幕支持使固定尺寸界面可能进入兼容显示;其他能力按 API 逐步加入。 | 若仍维护这些设备,使用密度无关尺寸与替代资源,逐项检查调用 API 的引入版本。 |
| Android 1.0~1.5(API 1~3) | 平台初期版本;没有可概括所有现代应用的单项迁移限制。 | 只有 minSdk 仍覆盖这些设备时才需要单独验证;新 API 一律做版本保护。 |
表格是排查入口,不是"每升一级都要改一遍代码"的任务单。以 minSdk = 23、targetSdk = 37 的应用为例,先在 API 23 和 37 设备上走通核心流程;若项目用到通知、存储、前台服务或大屏,再在对应的门槛版本(如 API 26、29~31、33~36)做定向回归。升级目标 API 时,逐代阅读对应的官方行为变更文档,只处理项目实际使用的能力。
把对照表用到代码里
假设应用最低支持 Android 6.0,需要在 Android 13 及以上使用系统的 LocaleManager。这个类从 API 33 才加入,因此既要让编译器看得到它,也要在运行时挡住旧设备:官方 LocaleManager API 参考。
kotlin
// 示例:在 Context 扩展函数中读取当前应用的语言设置;旧系统返回 null。
fun Context.appLocaleTagsOrNull(): String? {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return null
return getSystemService(LocaleManager::class.java)
?.applicationLocales
?.toLanguageTags()
}
这段代码需要导入 android.content.Context、android.app.LocaleManager 和 android.os.Build,并用 API 33 或更高的 compileSdk 编译。SDK_INT 检查保护了只在新系统上执行的调用;null 是示例里为旧系统选择的返回值,真实产品可以改用 AndroidX 的应用语言兼容方案。能够编译通过,不代表所有 minSdk 覆盖的设备都具有这个 API。
例如,下面是一个 Kotlin DSL 的配置片段:
kotlin
android {
compileSdk = 37
defaultConfig {
minSdk = 23
targetSdk = 37
}
}
它的含义是:使用 API 37 编译;允许 Android 6.0(API 23)及以上设备安装;按目标 API 37 的行为进行适配。targetSdk = 37 不能代替运行时版本判断,升级它之前还要测试 Android 17 的目标行为变更。Android 17 已于 2026 年 6 月正式发布。
36.1:为什么现在只看整数还不够
过去,入门文章常把"一个 Android 大版本对应一个 API 整数"当作全部规则。Android 16 QPR2 带来了首个 minor SDK release(小版本 SDK)36.1 :它仍属于 Android 16,设备上的主要 API Level 仍是 36,但这个小版本可以增加平台 API。官方在 Android 16 QPR2 SDK 设置文档 中给出了 minorApiLevel = 1 的编译配置。
截至本文日期,完整版本常量表还列出了 Android 17 的 37.1 和 37.2。它们分别对应 QPR1 Beta 与 QPR2 Beta 中的小版本 API,不改变 Android 17 在上表中的主要 API Level 37。查具体新 API 时,要留意自己查到的是正式版能力还是预览版能力。
如果某个 API 明确标注"Added in version 36.1",仅判断 Build.VERSION.SDK_INT >= 36 就不够。Android 16 起可以结合 Build.VERSION.SDK_INT_FULL 与 Build.VERSION_CODES_FULL.BAKLAVA_1 判断完整版本;在还支持 API 35 及以下的应用中,先检查 SDK_INT >= 36,再访问 SDK_INT_FULL。这两个字段的定义见 官方 Build.VERSION 文档。
kotlin
val hasAndroid16Qpr2Api =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA &&
Build.VERSION.SDK_INT_FULL >= Build.VERSION_CODES_FULL.BAKLAVA_1
这里比较的是官方提供的完整版本常量,不要自己把 36.1 转成 361 去比。minSdk 和 targetSdk 仍按主要 API Level 配置;小版本 API 要用运行时检查保护。Android 还存在可通过系统更新交付的 SDK Extensions,遇到标注为扩展版本的 API,应按其扩展版本要求判断,别只套用上面的整数对照表。
Java/JDK 版本怎么读?它和 Android API 有对应关系吗?
旧资料里常写"JDK 1.8",现在更常写"JDK 8"或"Java 8"。这三种写法指向同一代 Java:1.8 是旧版本字符串,8 是 Java SE 与 JDK 的产品版本号。Oracle 的 Java 8 命名说明 对此有明确例子。JDK 9 以后,版本号直接写 9、10、11......,不再把 1. 放在前面。
| Java / JDK 版本 | 旧写法或版本范围 | 读表时要记住的事 |
|---|---|---|
| 1.0~1.4 | JDK 1.0~1.4 | 早期版本,旧文档可能直接用 1.x |
| 5、6、7、8 | 1.5、1.6、1.7、1.8 |
JDK 1.8 就是 JDK 8;8 是 LTS |
| 9、10 | JDK 9、10 | 新编号方式,无 1. 前缀 |
| 11 | JDK 11 | LTS |
| 12~16 | JDK 12~16 | 后续功能版本 |
| 17 | JDK 17 | LTS;Android Gradle Plugin 8.x 要求用 JDK 17 运行 |
| 18~20 | JDK 18~20 | 后续功能版本 |
| 21 | JDK 21 | LTS |
| 22~24 | JDK 22~24 | 后续功能版本 |
| 25 | JDK 25 | 截至本文日期,最新 LTS |
| 26 | JDK 26 | 2026 年 3 月发布的非 LTS 版本 |
| 27 | JDK 27 | 2026 年 9 月发布的最新版本,非 LTS |
这里的 LTS 按 Oracle Java SE 支持路线图标注;"最新"依据 Oracle JDK 下载页在本文日期可见的信息。它只是 Java 自身的发布序列,没有"JDK 17 对应 Android 17"或"JDK 8 对应 API 8"这样的关系。
放进 Android 工程后,JDK 至少要和下面三件事分开看:
| 设置 | 它控制什么 | 常见误解 |
|---|---|---|
| Gradle JDK | 在开发机或 CI 上运行 Gradle 和 Android Gradle Plugin | 装了最新 JDK,应用就支持最新 Android API |
sourceCompatibility / targetCompatibility |
Java 源码语法级别 / 编译出的 Java 字节码级别 | 写成 Java 17,设备就必须安装 JDK 17 |
compileSdk / minSdk / targetSdk |
Android 平台 API 的编译范围、最低安装版本和目标行为 | 它们是 JDK 版本号 |
例如,同一个项目可以用 JDK 17 运行 Gradle、用 Java 17 语法编译 Java 源码,同时设置 minSdk = 23、compileSdk = 37 。Java 语法能否编译、某个 Java 标准库 API 能否在旧 Android 设备上运行,还要看 Android 的支持情况及是否需要脱糖(desugaring)。Android 官方 JDK 构建指南区分了这些设置,Java API 脱糖说明也指出语言特性支持和库 API 支持是两回事。升级 JDK 时,应先按项目所用 Gradle、Android Gradle Plugin 的兼容要求选版本,而不是看到 JDK 27 就直接把工程切过去。
最后记住一个判断顺序
遇到"这个 API 能不能用",先查官方 API 参考中它从哪个 API Level 或小版本/扩展版本 开始提供;再看项目的 compileSdk 能否编译;最后对照 minSdk,给旧设备加运行时判断或兼容实现。升级 targetSdk 时,按上面的清单区分系统对所有应用的变化和目标版本行为,并只对实际用到的功能做适配。若问题出在 Java 语法、Gradle 启动或 Java 标准库,则回头查 JDK、编译选项与脱糖配置。应用自身的 versionCode、versionName 则是另一套发布版本号。
查表时最实用的一组数字是:Android 13→33、14→34、15→35、16→36、17→37。但真正写兼容代码时,别只背表,要回到具体 API 的"Added in"标注。