Android版本演进与TargetSDK,究竟该怎么对应?

这些年我一直在做Android开发,每次Google发布新系统,群里总有人问:“我该把targetSdkVersion升到多少?不升行不行?”其实这个问题,说白了就一句话:targetSdkVersion决定了你的App能用哪些新特性,也决定了系统会不会帮你“打补丁”。

我记得刚入行那年,手头有个老项目targetSdk还定在19(Android 4.4)。用户手机升级到Android 7.0后,App一打开就直接崩溃。查了半天,原来是FileProvider没配置——系统在N版本强制了“私有目录文件不可通过file:// URI共享”。这就是典型的targetSdk没跟上惹的祸。

所以这一章,我就把自己折腾多年的经验掏出来,帮你把版本演进和targetSdk的对应关系理清楚。你看完就能知道:什么时候该升,升的时候重点防什么坑。

1. targetSdkVersion到底是什么?

你每次在build.gradle里写的targetSdkVersion,其实是在告诉系统:“我这个App已经在目标API级别上做过完整测试了,你尽管把新平台的行为变更应用到我身上。”
反过来,如果你的targetSdk低于当前设备API,系统就会用兼容模式运行——保留旧行为,但你也用不上新特性。

关键点:targetSdkVersion ≠ compileSdkVersion。

  • compileSdkVersion:编译时能调用的API范围,相当于“你能用多少工具”。
  • targetSdkVersion:运行时系统按哪个版本的行为来对待你的App,相当于“你要求系统怎么待你”。

我以前见过有人直接把compileSdk和targetSdk写成一样,然后漏了权限适配,结果在Android 11上闪退。嗯,这里要注意两者各管各的。

2. 一张图串起版本演进与TargetSDK

我自己习惯用这张图来给团队讲脉络。它把每个大版本的核心变更节点、对应targetSdk区间、以及常见的适配难点串在了一起。

Android版本与TargetSDK对应关系图 Android版本演进 · TargetSDK 对应关系(API 14~34) 说明:每对箭头代表「系统版本 → 对应targetSdk」;橙色标注为重大行为变更节点,需重点回测。 建议: 每次升级targetSdk至少跨2~3个小版本,避免单次变动过大。 API 14~15 ICS 4.0~4.0.4 API 16~18 Jelly Bean 4.1~4.3 API 19 KitKat 4.4 API 21~22 Lollipop 5.0~5.1 API 23 ★ M 6.0 运行时权限 API 24~25 ★ N 7.0 文件共享 API 26~27 O 8.0 后台限制 API 28 P 9.0 非SDK接口 API 29 10 分区存储 API 30~31 11/12 权限自动重置 API 33 ★ 13 通知权限 API 34 14 前台服务类型 当前建议: 新项目 targetSdk = 34(Android 14);存量项目至少升级到 33,以通过Google Play 2024年8月要求。 回测要点:运行时权限(API 23+)→ 分区存储(API 29+)→ 前台服务类型(API 34+)

3. 各版本关键变更 & TargetSDK 适配要点

我列了个表,把从API 14到34之间必须回测的行为变更挑了出来。每当我接手一个老项目,就会按这个表格去扫一遍。

目标API Android版本 核心行为变更 常见适配坑
236.0 Marshmallow运行时权限模型未处理权限拒绝、未动态申请
247.0 NougatFileProvider强制;多窗口相机/文件分享崩溃
268.0 Oreo隐式广播限制;后台执行限制;通知渠道Service启动异常、通知不显示
289.0 Pie非SDK接口灰名单反射调用被禁止,闪退
2910分区存储(Scoped Storage)无法直接访问公共目录
3011权限自动重置;包可见性应用间跳转失败
3313通知运行时权限 POST_NOTIFICATIONS推送无法弹出通知
3414前台服务类型声明;动态广播接收器限制后台任务被系统kill

我个人的一个小技巧:每次升级targetSdk时,不要一次跳太多版本。比如从API 23直接跳到33,中间的行为变更堆积在一起,排查起来特别痛苦。我一般会分两到三次,每次跨3~4个版本,把变更点逐个击破。

4. 如何选择当前项目的TargetSDK?

这个问题其实没有标准答案,要看你的用户群和业务场景。但我可以给你一个常用的决策逻辑:

  1. 新项目:直接用当前最新的稳定API(2025年推荐targetSdk 34)。好处是能用上新API,也符合Play商店要求。
  2. 存量老项目:先确认最低用户设备的API level。比如你的大量用户还在Android 8.0(API 26),那targetSdk可以设到28或29,但要保证在旧设备上也能正常运行。
  3. 必须满足的分发平台要求:例如Google Play要求2024年8月后新版本targetSdk至少33,否则无法上架。你想想看,不能上架还怎么玩?
  4. 避坑指南:我曾经接手一个targetSdk=19的项目,用户群体中有30%还在用Android 5.0。我们一次性升到29,结果测试时发现很多国产ROM(比如华为、小米)对分区存储的处理有差异,花了整整两周才修完。所以建议你按版本逐级升,每升一个版本都做一轮全量回归。

5. 升级TargetSDK的通用流程

我记得在带团队时,把流程整理成了5步,现在基本是团队标配:

  • Step 1:查看行为变更文档(Android Developer官网),列出从当前targetSdk到目标版本之间所有的“break change”。
  • Step 2:在gradle中修改targetSdkVersion和compileSdkVersion(最好一致)。
    android {
        compileSdkVersion 34
        defaultConfig {
            targetSdkVersion 34
        }
    }
  • Step 3:编译项目,修复所有编译错误(比如废弃API替换、新权限声明)。
  • Step 4:在模拟器和真机(覆盖目标版本+低版本)上做功能回测。重点关注:权限、文件访问、通知、后台任务、隐式Intent。
  • Step 5:灰度发布1%用户,观察崩溃率、ANR率,然后全量。

注意:不要以为编译通过就算完。行为变更往往是运行期生效的。比如targetSdk从28升到29后,你的App读取公共目录的路径被改变了,必须用MediaStore或SAF,否则文件就找不到。这种问题编译时不会报错,但用户打开时直接白屏。我之前就吃过这个亏,连夜发紧急hotfix…

6. 关于模拟器适配的一个小提醒

因为本章主要讲版本对应,模拟器这块我后面会有专门章节。但这里先提一句:用模拟器跑targetSdk升级后的回测非常高效。我习惯创建多个AVD(API 23、26、28、30、33、34),每个都预装好测试数据。这样每改完一个版本,一键启动模拟器就能跑完整流程。具体怎么配置模拟器快照和自动化测试,我们在第8章详细聊。