对build.gradle中三个xxxVersion的理解

前言

Gradle 作为 android studio 时代官方指定的自动化构建工具,是我们开发任何项目都必不可少的神器,关于它的介绍,请看 stormzhang 的这篇blog。Android 项目的 app module 下的 build.gradle文件中,定义了三个 version :compiledSdkVersion、minSdkVersion、targetSdkVersion,它们的含义和作用是什么,请看下文分解。

正文

compiledSdkVersion

这个是用来告诉 gradle 用哪个版本的 sdk 来编译你的项目。这意味着你可以使用API版本中包含的Android API功能(以及所有以前的版本)。如果你尝试使用API 16中的功能,但将compileSdkVersion设置为15,则会收到编译错误。如果你的手机版本是15,将compileSdkVersion设置为16,只要你的应用不尝试调用 API 16特有的API,仍然可以在API 15设备上运行。

需要强调的是修改 compileSdkVersion 不会改变运行时的行为。当你修改了 compileSdkVersion 的时候,可能会出现新的编译警告、编译错误,但新的 compileSdkVersion 不会被包含到 APK 中:它纯粹只是在编译的时候使用。(你真的应该修复这些警告,他们的出现一定是有原因的)

因此我们强烈推荐总是使用最新的 SDK 进行编译。在现有代码上使用新的编译检查可以获得很多好处,避免新弃用的 API ,并且为使用新的 API 做好准备。

minSdkVersion

这个很好理解,就是当前应用所支持运行的最低系统版本。假设设置为23,如果你的手机系统版本22,是安装不上这个应用的。

在开发时 minSdkVersion 也起到一个重要角色:lint 默认会在项目中运行,它在你使用了高于 minSdkVersion 的 API 时会警告你,帮你避免调用不存在的 API 的运行时问题。如果只在较高版本的系统上才使用某些 API,通常使用运行时检查系统版本的方式解决。

可以看个官方提供的检查系统版本的代码示例:

1
2
3
4
5
6
7
8
9
private void setUpActionBar() {
// Make sure we're running on Honeycomb or higher to use ActionBar APIs
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
}else{
//nothing
}
}

targetSdkVersion

这个是最不好理解的一个。官方解释说,这是 Android 提供向前兼容的主要依据。

这是什么意思呢?随着 Android 系统的升级,某个系统的 API 或者模块的行为可能会发生改变,但是为了保证老 APK 的行为还是和以前兼容。只要 APK 的 targetSdkVersion 不变,即使这个 APK 安装在新 Android 系统上,其行为还是保持老的系统上的行为,这样就保证了系统对老应用的前向兼容性。

这里还是用原文的例子,在 Android 4.4 (API 19)以后,AlarmManager 的 set()setRepeat() 这两个 API 的行为发生了变化。在 Android 4.4 以前,这两个 API 设置的都是精确的时间,系统能保证在 API 设置的时间点上唤醒 Alarm。因为省电原因 Android 4.4 系统实现了 AlarmManager 的对齐唤醒,这两个 API 设置唤醒的时间,系统都对待成不精确的时间,系统只能保证在你设置的时间点之后某个时间唤醒。

这时,虽然 API 没有任何变化,但是实际上 API 的行为却发生了变化,如果老的 APK 中使用了此 API,并且在应用中的行为非常依赖 AlarmManager 在精确的时间唤醒,例如闹钟应用。如果 Android 系统不能保证兼容,老的 APK 安装在新的系统上,就会出现问题。

Android 系统是怎么保证这种兼容性的呢?这时候 targetSdkVersion 就起作用了。APK 在调用系统 AlarmManager 的 set() 或者 setRepeat() 的时候,系统首先会查一下调用的 APK 的 targetSdkVersion 信息,如果小于 19,就还是按照老的行为,即精确设置唤醒时间,否者执行新的行为。

感谢

Android targetSdkVersion 原理

0%