2. Android 版本演化与兼容性:从1.0到14的关键变化
从2008年第一款Android手机诞生到现在,这系统经历了翻天覆地的变化。我最早接触Android开发时,还在用Android 2.2 Froyo,那时候屏幕才3.2英寸,内存256MB就算大容量了。你想想看,现在随便一台千元机都是6GB起步,这变化有多大。
做适配,说白了就是跟版本演化打交道。不了解历史,你根本不知道为什么要做那些奇怪的适配判断。这一章,我就带你把Android这十几年的关键变化捋一遍。
2.1 那些改变一切的版本节点
版本太多,记不全很正常。但有几个里程碑你必须记住:
| 版本 | API等级 | 发布时间 | 关键变化 |
|---|---|---|---|
| Android 1.0 | 1 | 2008年 | 首次面世,基础框架确立 |
| Android 2.3 Gingerbread | 9-10 | 2010年 | 支持多指触控、NFC、复制粘贴 |
| Android 3.0 Honeycomb | 11-13 | 2011年 | 专为平板设计,引入ActionBar |
| Android 4.0 Ice Cream Sandwich | 14-15 | 2011年 | 统一手机和平板UI,引入GridLayout |
| Android 4.4 KitKat | 19 | 2013年 | 全屏沉浸式模式,ART运行时预览 |
| Android 5.0 Lollipop | 21 | 2014年 | Material Design,ART正式取代Dalvik |
| Android 6.0 Marshmallow | 23 | 2015年 | 运行时权限模型,Doze省电模式 |
| Android 7.0 Nougat | 24-25 | 2016年 | 多窗口支持,FileProvider |
| Android 8.0 Oreo | 26-27 | 2017年 | 后台执行限制,通知渠道 |
| Android 9 Pie | 28 | 2018年 | 非SDK接口限制,切片功能 |
| Android 10 | 29 | 2019年 | 强制Scoped Storage,深色模式 |
| Android 11 | 30 | 2020年 | 包可见性限制,一次性权限 |
| Android 12 | 31-32 | 2021年 | Material You,精确闹钟权限 |
| Android 13 | 33 | 2022年 | 通知权限,主题图标 |
| Android 14 | 34 | 2023年 | 更严格的隐式广播限制,屏幕录制检测 |
看这个表,你会发现一个规律:几乎每两个大版本就会有一次“破坏性”变更。Android 6.0的运行时权限,Android 7.0的FileProvider,Android 8.0的后台限制,Android 10的Scoped Storage……每一次都让不少开发者深夜加班。
核心观点:版本演化不是线性的,而是阶梯式的。每登上一个台阶,旧代码就可能不兼容。适配的本质,就是跟上这个阶梯。
接下来,我们把三个最重要的SDK配置参数说清楚。这是每个Android项目都绕不开的坑。
2.2 三个"SDK"的含义与选择策略
刚入行那会儿,我看着 compileSdkVersion、minSdkVersion、targetSdkVersion 这三个东西,觉得就是随便填填数字。后来踩了不知道多少坑才明白,它们各自管着不同的事。
compileSdkVersion
这个最简单。它告诉编译器:你用哪个版本的API来编译项目。比如你设为34,就能用Android 14的新API。我个人习惯是永远用最新稳定版。
android {
compileSdk 34
}
注意,编译版本变了不代表你的app只能跑在Android 14上。它只是让你能用新API,能不能用还得靠运行时判断。
minSdkVersion
这是你的app愿意支持的最低门槛。设成21,意味着Android 5.0以下的用户就装不了你的app。
设得低,覆盖广,但很多新API不能直接用。设得高,开发舒服,但用户流失。怎么选?
我的经验:如果不是特殊场景,建议minSdk设到21或23。Android 5.0以下的市场份额已经很低了,为了那1%的用户牺牲开发效率,不划算。
targetSdkVersion
这个最容易被忽略,但恰恰是最坑的。它告诉系统:我测试过这个API版本,你按这个版本的行为来对待我的app。比如你targetSdk设成29,系统就知道你的app兼容Android 10的Scoped Storage,不会给你做向下兼容。
它和compileSdk不一样:compileSdk决定能用哪些API,targetSdk决定系统怎么对待你的app。
android {
compileSdk 34
targetSdk 33 // 比如还没适配Android 14的某些变更
minSdk 23
}
避坑指南:我曾经见过一个项目,compileSdk升到34了,targetSdk还在28。结果Android 14设备上很多行为异常——因为系统默认用Android 9的兼容行为,新的权限模型完全没生效。切记:targetSdk一定要跟着你的实际适配进度走。
2.3 选择策略:三种场景的实战建议
光说理论不够,我直接给策略。
场景一:全新项目
- compileSdk:最新稳定版(比如34)
- targetSdk:和compileSdk一致(比如34)
- minSdk:看你用户画像,一般21或23起
新项目别给自己挖坑,直接怼最新API。测试也方便。
场景二:维护中的老项目
- compileSdk:升到最新版,哪怕targetSdk没动
- targetSdk:每次大版本发布后,花两周测试,然后往上调一档
- minSdk:别轻易降,但如果用户量级变了可以考虑升
我习惯的做法是:每年年初把targetSdk调到当年最新的稳定API版本。比如2024年就调到34。这样一年只折腾一次,时间可控。
场景三:技术债务严重的项目
- 第一步:先把compileSdk升到最新,解决所有编译警告
- 第二步:把minSdk调到能支持新特性的最低版本
- 第三步:targetSdk逐版升级,每版做专项测试
别想着一步到位。我见过太多团队想一次性跳到最新targetSdk,结果代码改崩了。逐版升级,每版修复该版本的弃用API,反而更稳。
2.4 从1.0到14:核心演化时间线
我画了一张图,把那些“不能不知道”的版本节点串起来。你看完就明白为什么适配越做越复杂了。
从这张图你可以看到:适配的复杂度是递增的。早期版本主要加功能,从Android 6.0开始加限制,到了Android 8.0以后就变成“限制+收紧”。做适配时,越新的版本越得专门留时间。
2.5 版本适配的四个基本原则
讲这么多,我总结四条原则,你记牢了:
- 编译版本永远向上看。 compileSdk用最新,哪怕你暂时不调targetSdk。这样编译时能提前知道哪些API要弃用了。
- 目标版本逐版升级。 别跳版本。从28跳到30没关系,但从28直接跳到34,很多行为变更会被叠加在一起,问题根本定位不了。
- 最低版本跟市场走。 查你app的Google Play控制台,看看用户分布。我一般会放弃最底部的2%-3%用户,换取开发效率。
- 每个大版本发布后,跑一次兼容性测试。 别等人报bug才知道出了问题。
实用工具:Android Studio自带的 App Inspection 和 Compatibility Test Suite (CTS) 可以在你调targetSdk之前就发现潜在问题。我每次升级前都会跑一遍,能省至少半天排错时间。
好了,版本演化和三个SDK参数的事就说这么多。记住:适配不是一次性的活,而是一个持续迭代的过程。每次系统更新时,先看看你的compileSdk和targetSdk有没有跟着走,这是最基础也是最重要的习惯。