<div><p><a href="http://www.codeceo.com/article/android-compilesdkversion-minsdkversion-targetsdkversion.html" target="_self">原文链接</a></p><p>作者:Ian Lake,Google Android 推广工程师;翻译:韩国恺。</p><p>当你发布一个应用之后,(取决于具体的发布时间)可能没过几个月 Android 系统就发布了一个新版本。这对你的应用意味着什么,所有东西都不能用了?</p><p>别担心,<strong>向前兼容</strong>是 Android 非常关注的事情。用户在升级到新版 Android 的时候,用以前版本的 SDK 构建的现有应用应该不会出问题。这就是 <strong>compileSdkVersion</strong>, <strong>minSdkVersion</strong> 和 <strong>targetSdkVersion</strong> 的作用:他们分别控制可以使用哪些 API ,要求的 API 级别是什么,以及应用的兼容模式。</p><p><img class="" title="androidversion" src="https://img3.mukewang.com/5b44c96200016f0b07600380.jpg" alt="" width="760" height="380" style="margin: 0px auto; padding: 5px; border: 1px solid rgb(230, 230, 230); max-width: 788px; display: block; height: auto; text-align: center; cursor: pointer;" data-original="https://img3.mukewang.com/5b44c96200016f0b07600380.jpg"></p><h2>compileSdkVersion</h2><p>compileSdkVersion 告诉 Gradle 用哪个 Android SDK 版本编译你的应用。使用任何新添加的 API 就需要使用对应 Level 的 Android SDK。</p><p>需要强调的是<strong>修改 compileSdkVersion 不会改变运行时的行为</strong>。当你修改了 compileSdkVersion 的时候,可能会出现新的编译警告、编译错误,但新的 compileSdkVersion 不会被包含到 APK 中:它纯粹只是在编译的时候使用。(你真的应该修复这些警告,他们的出现一定是有原因的)</p><p>因此我们强烈推荐<strong>总是使用最新的 SDK 进行编译</strong>。在现有代码上使用新的编译检查可以获得很多好处,避免新弃用的 API ,并且为使用新的 API 做好准备。</p><p>注意,如果使用 <a href="http://developer.android.com/tools/support-library/index.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog">Support Library</a> ,那么使用最新发布的 Support Library 就需要使用最新的 SDK 编译。例如,要使用 23.1.1 版本的 Support Library ,compileSdkVersion 就必需至少是 23 (大版本号要一致!)。通常,新版的 Support Library 随着新的系统版本而发布,它为系统新增加的 API 和新特性提供兼容性支持。</p><h2>minSdkVersion</h2><p>如果 compileSdkVersion 设置为可用的最新 API,那么 <strong>minSdkVersion 则是应用可以运行的最低要求</strong>。minSdkVersion 是 Google Play 商店用来判断用户设备是否可以安装某个应用的标志之一。</p><p>在开发时 minSdkVersion 也起到一个重要角色:<a href="http://developer.android.com/tools/debugging/improving-w-lint.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog">lint</a> 默认会在项目中运行,它在你使用了高于 minSdkVersion 的 API 时会警告你,帮你避免调用不存在的 API 的运行时问题。如果只在较高版本的系统上才使用某些 API,通常使用<a href="http://developer.android.com/training/basics/supporting-devices/platforms.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog#version-codes">运行时检查系统版本</a>的方式解决。</p><p>请记住,你所使用的库,如 <a href="http://developer.android.com/tools/support-library/features.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog">Support Library</a> 或 <a href="https://developers.google.com/android/guides/overview?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog">Google Play services</a>,可能有他们自己的 minSdkVersion 。你的应用设置的 minSdkVersion 必需大于等于这些库的 minSdkVersion 。例如有三个库,它们的 minSdkVersion 分别是 4, 7 和 9 ,那么你的 minSdkVersion 必需至少是 9 才能使用它们。在少数情况下,你仍然想用一个比你应用的 minSdkVersion 还高的库(处理所有的边缘情况,确保它只在较新的平台上使用),你可以使用 <a href="http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog#TOC-tools:overrideLibrary-marker">tools:overrideLibrary 标记</a>,但请做彻底的测试!</p><p>当你决定使用什么 minSdkVersion 时候,你应该<strong>参考当前的 <a href="http://developer.android.com/about/dashboards/index.html">Android 分布统计</a></strong>,它显示了最近 7 天所有访问 Google Play 的设备信息。他们就是你把应用发布到 Google Play 时的潜在用户。最终这是一个商业决策问题,取决于为了支持额外 3% 的设备,确保最佳体验而付出的开发和测试成本是否值得。</p><p>当然,如果某个新的 API 是你整个应用的关键,那么确定 minSdkVersion 的值就比较容易了。不过要记得 14 亿设备中的 0.7% 也是个不小的数字。</p><h2>targetSdkVersion</h2><p>三个版本号中最有趣的就是 targetSdkVersion 了。 <strong>targetSdkVersion 是 Android 提供向前兼容的主要依据</strong>,在应用的 targetSdkVersion 没有更新之前系统不会应用最新的行为变化。这允许你在适应新的行为变化之前就可以使用新的 API (因为你已经更新了 compileSdkVersion 不是吗?)。</p><p>targetSdkVersion 所暗示的许多行为变化都记录在 <a href="http://developer.android.com/reference/android/os/Build.VERSION_CODES.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog">VERSION_CODES</a> 文档中了,但是所有恐怖的细节也都列在每次发布的平台亮点中了,在这个 <a href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog#ApiLevels">API Level 表</a>中可以方便地找到相应的链接。</p><p>例如,<a href="http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog">Android 6.0 变化文档</a>中谈了 target 为 API 23 时会如何把你的应用转换到<a href="http://android-developers.blogspot.com/2015/08/building-better-apps-with-runtime.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog">运行时权限模型</a>上,<a href="http://developer.android.com/about/versions/android-4.4.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog#Behaviors">Android 4.4 行为变化</a>阐述了 target 为 API 19 及以上时使用 <a href="http://developer.android.com/reference/android/app/AlarmManager.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog#set%28int,%20long,%20android.app.PendingIntent%29">set()</a> 和 <a href="http://developer.android.com/reference/android/app/AlarmManager.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog#setRepeating%28int,%20long,%20long,%20android.app.PendingIntent%29">setRepeating()</a> 设置 alarm 会有怎样的行为变化。</p><p>由于某些行为的变化对用户是非常明显的(<a href="http://android-developers.blogspot.com/2012/01/say-goodbye-to-menu-button.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog">弃用的 menu 按钮</a>,运行时权限等),所以<strong>将 target 更新为最新的 SDK 是所有应用都应该优先处理的事情</strong>。但这不意味着你一定要使用所有新引入的功能,也不意味着你可以不做任何测试就盲目地更新 targetSdkVersion ,<strong>请一定在更新 targetSdkVersion 之前做测试!</strong>你的用户会感谢你的。</p><h2>Gradle 和 SDK 版本</h2><p>所以设置正确的 compileSdkVersion, minSdkVersion 和 targetSdkVersion 很重要。如你所想, <a href="http://developer.android.com/tools/building/plugin-for-gradle.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog">Gradle</a> 和 <a href="http://developer.android.com/tools/studio/index.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog">Android Studio</a> 都在构建系统中集成了它们。在你的模块的 build.gradle 文件中(也可以在 Android Studio 的项目结构选项中)设置:</p><pre>android { compileSdkVersion 23
buildToolsVersion “23.0.1”
defaultConfig { applicationId “com.example.checkyourtargetsdk”
minSdkVersion 7
targetSdkVersion 23
versionCode 1
versionName “1.0”
}
}
编译时用到的 compileSdkVersion 是和构建工具(buildToolsVersion)版本一起设置的 Android 设置之一。其他两个稍有不同,他们在构建变体(build variant)的那里声明。defaultConfig 是所有构建变体的基础,也是设置这些默认值的地方。你可以想象在一个更复杂的系统中,应用的某些版本可能会有不同的 minSdkVersion 。
minSdkVersion 和 targetSdkVersion 与 compileSdkVersion 的另一个不同之处是它们会被包含进最终的 APK 文件中,如果你查看生成的 AndroidManifest.xml 文件,你会看到类似下面这样的标签:
<uses-sdk android:targetSdkVersion=“23” android:minSdkVersion=“7” />
如果你在 manifest 文件中手工设置,你会发现 Gradle 在构建时会忽略它们(尽管其它构建系统可能会明确依赖它们)。
综合来看
如果你按照上面示例那样配置,你会发现这三个值的关系是:
minSdkVersion <= targetSdkVersion <= compileSdkVersion
这种直觉是合理的,如果 compileSdkVersion 是你的最大值,minSdkVersion 是最小值,那么最大值必需至少和最小值一样大且 target 必需在二者之间。
理想上,在稳定状态下三者的关系应该更像这样:
minSdkVersion (lowest possible) <=
targetSdkVersion == compileSdkVersion (latest SDK)
用较低的 minSdkVersion 来覆盖最大的人群,用最新的 SDK 设置 target 和 compile 来获得最好的外观和行为。#BuildBetterApps
关于本文的内容您可以参与我们 Google+ 帖子上的讨论,关注我们的 Android Development Patterns 信息流获得更多信息。
————————————————
如果你觉得本人的文章对你有所帮助,客官慢走赏瓶水喝
![微信](https://i-blog.csdnimg.cn/blog_migrate/b8e9d51ad5dbedac50f2dddc83217515.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/81454da9f23077f0ca6997a2f3f55901.png)
![支付宝](https://i-blog.csdnimg.cn/blog_migrate/d1411744a546dc8a10a9b2f0bb01f561.jpeg)