- 原文链接:Picking your compileSdkVersion, minSdkVersion, and targetSdkVersion
- 作者:Ian Lake,Google Android 推广工程师
- 翻译:Guokai Han
当你发布一个应用之后,可能没过几个月Android系统就发布了一个新版本(取决于具体的发布时间)。这对你的应用意味着什么?所有的东西都不能用了?
别担心,向前兼容是Android非常关注的事情。用户在升级到新版本Android的时候,用以前版本的SDK构建的现有应用应该不会出什么问题。这就是compileSdkVersion,minSdkVersion和targetSdkVersion的作用,他们分别控制可以使用哪些API,要求的API级别是什么,以及应用的兼容模式。
compileSdkVersion
compileSdkVersion告诉Gradle用哪个Android SDK版本编译你的应用。使用任何新添加的API就需要使用对应Level的Android SDK。
需要强调的是,修改compileSdkVersion不会出改变运行时的行为。当你修改了compileSdkVersion的时候,可能会出现新的编译警告、编译错误,但新的compileSdkVersion不会被包含到APK中,它只是纯粹在编译的时候使用。(你应该修复这些警告,他们的出现一定是有原因的)
因此,我们强烈推荐总是使用最新的SDK进行编译。在现有的代码上使用新的编译检查可以获得很多的好处,避免新启用的API,并为使用新的API做好准备。
注意,如果使用Support Library,那么使用最新发布的Support Library就需要使用最新的SDK编译。例如,要使用23.1.1版本的Support Library,compileSdkVersion就必须至少是23(最大的版本号要一致!)。通常,新版的Support Library随着新系统的版本而发布,它为系统增加的API和新特性提供兼容性支持。
minSdkVersion
如果compileSdkVersion设置为可用最新的API,那么minSdkVersion则是应用可以运行的最低要求。minSDKVersion是Google Play商店用来判断用户设备是否可以安装某一个应用的标志之一。
在开发时,minSdkVersion也起到一个重要的角色,lint 默认在项目中运行,它在你使用了高于minSdkVersion的API时,会警告你,帮你避免调用不存在的API的运行时问题。如果只在高版本的系统上才使用某些API,通常使用运行时检查系统版本的方式解决。
请记住,你所使用的库,如Support Library或Google Play Services,可能有他们自己的minSdkVersion。你的应用设置的minSdkVersion必须大于等于这些库的minSdkVersion。例如有三个库,它们的minSdkVersion分别是 4, 7 和 9 ,那么你的 minSdkVersion必需至少是9才能使用它们。在少数情况下,你仍然想用一个比你应用的minSdkVersion还高的库(处理所有的边缘情况,确保它只在较新的平台上使用),你可以使用 tools:overrideLibrary标记,但请做彻底的测试!
当你决定使用什么minSdkVersion时候,你应该参考当前的Android 分布统计,它显示了最近7天所有访问Google Play的设备信息。他们就是你把应用发布到Google Play时的潜在用户。最终这是一个商业决策问题,取决于为了支持额外 3% 的设备,确保最佳体验而付出的开发和测试成本是否值得。
当然,如果某个新的 API 是你整个应用的关键,那么确定 minSdkVersion的值就比较容易了。不过要记得14亿设备中的 0.7% 也是个不小的数字。
targetSdkVersion
三个版本号中最有趣的就是targetSdkVersion了。targetSdkVersion是Android 提供向前兼容的主要依据,在应用的 targetSdkVersion没有更新之前系统不会应用最新的行为变化。这允许你在适应新的行为变化之前就可以使用新的API(因为你已经更新了 compileSdkVersion不是吗?)。
targetSdkVersion所暗示的许多行为变化都记录在VERSION_CODES 文档中了,但是所有恐怖的细节也都列在每次发布的平台亮点中了,在这个API Level表中可以方便地找到相应的链接。
例如,Android 6.0变化文档中谈了target为API 23 时会如何把你的应用转换到运行时权限模型上,Android 4.4 行为变化阐述了 target 为 API 19 及以上时使用 set() 和 setRepeating() 设置 alarm 会有怎样的行为变化。
由于某些行为的变化对用户是非常明显的(弃用的menu按钮,运行时权限等),所以将target更新为最新的 SDK 是所有应用都应该优先处理的事情。但这不意味着你一定要使用所有新引入的功能,也不意味着你可以不做任何测试就盲目地更新targetSdkVersion ,请一定在更新targetSdkVersion之前做测试!你的用户会感谢你的。
Gradle和SDK版本
所以设置正确的compileSdkVersion, minSdkVersion和 targetSdkVersion很重要。如你所想,Gradle和Android Studio 都在构建系统中集成了它们。在你的模块的build.gradle文件中(也可以在Android Studio的项目结构选项中)设置:
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.example.checkyourtargetsdk"
minSdkVersion 7
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
}
编译时用到的compileSdkVersion是和构建工具版本一起设置的 Android 设置之一。其他两个稍有不同,他们在构建变体(build variant)的那里声明。defaultConfig是所有构建变体的基础,也是设置这些默认值的地方。你可以想象在一个更复杂的系统中,应用的某些版本可能会有不同的minSdkVersion 。
minSdkVersion和targetSdkVersion与compileSdkVersion 的另一个不同之处是它们会被包含进最终的APK文件中,如果你查看生成的AndroidManifest.xml文件,你会看到类似下面这样的标签:
如果你在manifest文件中手工设置,你会发现Gradle在构建时会忽略它们(尽管其它构建系统可能会明确依赖它们)。
综合看来
如果你按照上面示例那样配置,你会发现这三个值的关系是:minSdkVersion <= targetSdkVersion <= compileSdkVersion
这种直觉是合理的,如果compileSdkVersion是你的最大值,minSdkVersion是最小值,那么最大值必需至少和最小值一样大且 target 必需在二者之间。
理想上,在稳定状态下三者的关系应该更像这样: minSdkVersion (lowest possible) <= targetSdkVersion == compileSdkVersion (latest SDK)
用较低的minSdkVersion来覆盖最大的人群,用最新的SDK设置 target和compile来获得最好的外观和行为。