版权声明:
本公众号发布的所有文章,均属于原创,版权归本公众号所有。
未经允许,不得转载。
在新建一个 Android Project 的时候,都是需要选择当前创建的 App 支持的版本的。而这些配置,就反应在 compileSdkVersion、minSdkVersion、targetSdkVersion 三个属性的配置上。
它们分别代表的含义,就是本片文章的内容。
首先思考一下,这些 XxxSdkVersion 为什么而存在呢?
在现如今 Android 版本高速迭代的情况下,每一版本 Android 系统的升级,都是革命式的,总是会发布一些新的组件和对应的 Api 支持。而这些,都是旧版本不具备的。
那么,在这种系统级别进行迭代的过程中,难道基于旧版本开发的 App 就全部不可以用了吗?当然,从现在的实际情况来看,每一版本 Android SDK 的升级,多数 Api 都是向前兼容的。
而为了保证向前兼容新版本的 Android SDK,就需要根据根据当前 App 支持的 SDK Level 来运行不同的逻辑,这个时候就需要用到 targetSdkVersion。
既然一个 App 所用到的 Api 都有可能在旧版本上不被支持(完全没有此方法),那么应用市场和设备,在安装运行这个 App 之前,如何区分此 App 是否适用当前设备的系统版本呢?这个时候,就需要用到 minSdkVersion ,来标记当前 App 支持的最低 Android SDK 版本。
在开发过程中,如果有新的系统版本被发布了,如果想使用最新的 Android SDK 版本进行编译,这样可以在开发期间,处理掉一些编译警告、编译错误等。这个时候就需要用到 compileSdkVersion 了,它纯粹只是在编译的时候,指定是基于那么版本的 Android SDK 进行编译。
既然已经了解了它们大概都是用来干什么的,接下来详细讲讲这些 XxxSdkVersion 的影响范围。
compileSdkVersion 是在开发和编译期间,给开发者使用的。用于告诉 Gradle ,使用那个 Android SDK 版本来进行编译和打包 App,如果需要使用新的 Android SDK 中的 Api,就需要更新 compileSdkVersion 对应的版本号。
而我们知道,android.jar 并不会被编译进 Apk 中,同时 compileSdkVersion 只是改变的编译行为而不会改变运行时的行为,也就是说,当 Apk 被安装在设备上之后,它就是直接和系统的 Api 交互了,编译时候的 android.jar 只是为了保证编译能通过。
当 compileSdkVersion 被修改的时候,可能会出现一些编译时候的警告和编译错误,这些错误应该都会被编译器的 Lint 检测到。注意这些并不是 Error ,而是 Warning 。但是这些 Warning 的出现都是有原因的,一定要及时修复这些 Warning,哪怕需要使用 @SuppressLint
或者 @TargetApi
进行标记它,也只是我们在确定无碍的情况下的一种处理方式。
minSdkVersion 从名字上应该就可以看出来区别,它是标记当前 App 运行设备的 Android SDK 版本的最低要求,minSdkVersion 一般是应用商店来判断当前用户设备设备是否可以安装此应用的一个判断条件,同时用户也无法安装 minSdkVersion 高于当前用户设备的 App,会导致安装失败。
minSdkVersion 除了标记最低支持的版本之外,Lint 还会在你使用了高于 minSdkVersion 的 Api 的时候警告你,如果依然需要使用这些 Api ,可以使用 Build.VERSION.SDK_INT 进行版本判断,SDK_INT 标记当前设备的 Android SDK 版本号。
minSdkVersion 还会影响 App 中引用的第三方库,应用中引用的 第三方库都必须大于 App 主项目的 minSdkVersion。例如在项目中引用了三个库,它们的 minSdkVersion 分别是 9、14、17 ,那么你项目内的 minSdkVersion 必须至少是 17 才可以同时使用他们。当然,如果你坚持想用比你 App 的 minSdkVersion 版本高的第三方库,可以使用 tools:overrideLibrary
进行标记,但是这样的行为是高风险行为,必须充分测试才可以。
minSdkVersion 直接影响了你的 App 使用的用户范围,所以谨慎选择。其实这就是一个取舍的问题,虽然 minSdkVersion 提高几个版本,可以方便的实现更多的效果和功能,但是哪怕低 Android SDK 版本的设备市场占有率在逐年递减,在 Android 用户这个庞大的基数下,数量仍然不可小觑。
前面提到 targetSdkVersion 是 Android 提供向前兼容的主要依据,在应用的 targetSdkVersion 没有更新之前,系统为了兼容旧版本,依然保持在旧版本上的行为效果,给开发者预留出从容兼容新版本的时间。
举个例子,在 Android 7.0 之后,对 File 的分享启动了 StrictMode,当你想要通过 file:// 安装一个私有目录下的 apk 的时候,会抛出 FileUriExposedException
错误,这个时候你就需要使用 Android 提供的 FileProvider 来对此进行支持。但是这样重大的改动,只有在开发者主动将 targetSdkVersion 升级到 24 才会启动,如果 targetSdkVersion 没有被升级,会依然保持之前的行为效果,并不用担心 FileUriExposedException 异常。
既然 targetSdkVersion 的升级都伴随着代码层级上的更新,依然需要谨慎更新,如果升级了 targetSdkVersion ,最好在发布之前,进行充分的测试。
如果有一些 Api 想在低版本上,依然使用旧的行为进行处理,可以利用 ApplicationInfo.targetSdkVersion 来进行简单的区分,它可以得到当前 App 设定的 targetSdkVersion 的值。
到这里基本上就讲清楚了 minSdkVersion 、targetSdkVersion、compileSdkVersion 的关系都已经明确了。
简单来说:
minSdkVersion :标记最低支持版本。
targetSdkVersion:用于系统保持向前兼容。
compileSdkVersion:用于开发阶段,指定参与便于的 Android SDK 版本。
理论上来说,minSdkVersion 应该指定为当前 App 支持的最低版本,compileSdkVersion 应该为最新的 Android SDK 版本,而 targetSdkVersion 根据需要进行升级。
所以理想的关系是:
minSdkVersion(Lowest possible) <= targetSdkVersion <= compileSdkVersion(Latest SDK)
参考资料:
https://medium.com/google-developers/picking-your-compilesdkversion-minsdkversion-targetsdkversion-a098a0341ebd
http://chinagdg.org/2016/01/picking-your-compilesdkversion-minsdkversion-targetsdkversion/