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版本演化时间线:关键兼容性节点 Android 1.0 API 1 2.3 Gingerbread API 9-10 4.0 ICS API 14-15 5.0 Lollipop API 21 6.0 Marshmallow API 23 8.0 Oreo API 26-27 关键变化说明: Android 6.0 → 运行时权限模型 | Android 8.0 → 后台执行限制 | Android 10 → Scoped Storage | Android 11 → 包可见性 早期版本 统一阶段 权限与隐私时代 严格限制

从这张图你可以看到:适配的复杂度是递增的。早期版本主要加功能,从Android 6.0开始加限制,到了Android 8.0以后就变成“限制+收紧”。做适配时,越新的版本越得专门留时间。

2.5 版本适配的四个基本原则

讲这么多,我总结四条原则,你记牢了:

  1. 编译版本永远向上看。 compileSdk用最新,哪怕你暂时不调targetSdk。这样编译时能提前知道哪些API要弃用了。
  2. 目标版本逐版升级。 别跳版本。从28跳到30没关系,但从28直接跳到34,很多行为变更会被叠加在一起,问题根本定位不了。
  3. 最低版本跟市场走。 查你app的Google Play控制台,看看用户分布。我一般会放弃最底部的2%-3%用户,换取开发效率。
  4. 每个大版本发布后,跑一次兼容性测试。 别等人报bug才知道出了问题。

实用工具:Android Studio自带的 App Inspection 和 Compatibility Test Suite (CTS) 可以在你调targetSdk之前就发现潜在问题。我每次升级前都会跑一遍,能省至少半天排错时间。

好了,版本演化和三个SDK参数的事就说这么多。记住:适配不是一次性的活,而是一个持续迭代的过程。每次系统更新时,先看看你的compileSdk和targetSdk有没有跟着走,这是最基础也是最重要的习惯。