在开发 Android App 时,开发人员最容易出现困惑的地方之一应该是 compileSdkVersion、minSdkVersion 和 targetSdkVersion 这些参数的用途。对此,有 Google 内部的 Android 开发人员就这个议题写了一篇文章:Picking your compileSdkVersion, minSdkVersion, and targetSdkVersion。在这里会用不同的角度来说明这些参数的用途,希望能对大家在理解上有所帮助。

buildToolsVersion

首先,这是在那篇文章中没有说明到的另一个与版本有关的参数。这个参数主要是用来指定用哪一组编译程序来将你所编写的 Source Code 转成操作系统可以载入的形式,也就是产出 Apk。所以 Build Tools 在概念上可以看成是 Android Studio 的一部份或是其中一个套件,只是同时会有好几组。

譬如说要修理车辆,每一组的 Build Tools 就像是有人把修车的工具,扳手、起子、套筒之类的放在一个包包里。只是随着工具设计的翻新,包包里的工具可能会做调整,像是起子原本是各尺寸一只,现在可能改成只有一只但可以换各种尺寸的头。同样是拿来修车,工具也一样,但是为了区别内容物的不同所以给了不同的编号。

选用哪一组 Build Tools 原则上不会有太大的差异,大概就是编译的效能、产出的文件大小等等的细节。但有时候还是可能会牵涉到 Apk 内容或结构的问题影响运行,仍然要多注意改版的资讯。最保险的做法还是让 buildToolsVersion 的主版本编号与 compileSdkVersion 同步。

compileSdkVersion

compileSdkVersion 则是 Build Tools 在进行编译时,检查源代码在呼叫 SDK 所使用的规格是否正确的基准,但所指定的 SDK 并不会被编入 Apk 中。Google 会在发行新版系统时对 SDK 做调整,为了保持相容性,在规格上不太可能采取激进的方式,例如:同样名称的函式改为不同的参数规格。最常出现的大概就是在函式上标注 @Deprecated,等系统发行过几个版本之后再正式废止。

buildToolsVersion 及 compileSdkVersion 顾名思义就是在编译、生成时期所使用的工具,这句话的重点是编译过了、顺利产出 Apk,不代表运行上就没有问题,而且所谓的运行还要细分是在哪个版本上运行。因为 SDK 不是包含在 Apk 里,是包含在 Android 的系统之中。Apk 在哪一个版本的 Android 中运行,调用的就是对应版本的 SDK。所以运行调用叫会不会报错,跟编译会不会成功是没有直接的关连,除非运行的环境和 compileSdkVersion 指定的版本相同,但也仅限于规格的部份。

用旅游来做例子,Build Tools 就好像旅行社,把你对旅游的构想转成实际的行程。而 Compile SDK 则是旅行社在行前检查所使用的检查表,用来确认在行前是不是有什么细节遗漏了。选用哪一个旅行社对于规划行程没有什么太大的差别,顶多只是能够提供服务的多寡或细致的程度。而行前检查表如果用错了版本就有可能会出问题,像是要去的目的地签证条件改变了,旧的版本没有列上去,在行前检查时一切没问题,到了当地才发现没有办法入境,于是整个行程就报销了。但如果是用新的检查表,就可以在行前发现问题,并且做出补救的措施,确保行程能够如计划进行。

由于 Google Play 只限制 App 可运行的 SDK 最低版本,并没有限定最高的版本。也就是,使用者可以在硬体厂商有提供更新的情况下不断地升级系统版本,而 App 则会一直保持在可安装的状态下。如果一直不更动 compileSdkVersion,则有一些变动在编译时期不会被发现,前段提到的标注 @Deprecated 就是一例。前几次的系统版本更新在运行 App 上可能不会有问题,但是一旦真的有函式被废止了,则要到运行时才能发现,这时要侦错就不是件容易的事。但如果是使用新的 compileSdkVersion,则是在编译时就会有对应的讯息供作参考。

所以在开头提到的文章中有一个很重要的关键点是:当编译的结果还存有警告时,一定要进行对应的处理,这些警告的设计是有其作用的。

targetSdkVersion

在推出新的 Android SDK 版本有函式的行为新旧版本不一致时,为保持相容性,旧的行为会被保留,并且会以 targetSdkVersion 的值来判断要运行哪一种行为。以开头提到的文章中举例的 AlarmManager#set 来说,依官方文件的说明,Android 4.4 (API 19)以后使用的是不精确的时间,以减少设备被唤醒的次数及降低电量的耗损。官方文件中的另一段注解文字说到:targetSdkVersion 小于 API 19 的会继续之前旧的行为,也就是 SDK 中会判断 targetSdkVersion 的资讯来决定运行的源代码内容。

以前段提到旅游的例子来说,当实际出发到了当地的海关,targetSdkVersion 的规则就如同海关柜台人员不是一体套用新的签证规则,而是会好心地依照填写的申请日期决定适用的签证规则。如果填的是新规则公布之后的日子,代表填写的人应该知道新的签证规则,所以当然就照新的签证规则来审核。相对地,填写的日期在新规则公布之前的日子,则会使用旧的签证规则来审核。

Android 透过这种方式让 App 在新的系统版本中不会有预期之外的行为出现,即便 Google 打算在新版本中改变原本的行为。所以 targetSdkVersion 主要的用途是让开发者告知 SDK,开发者所认知的函式行为应该是哪一种,如果 targetSdkVersion 是设定成改变之前的值,则 SDK 会运行旧的版本,否则就运行新的。对开发者来说,修改 targetSdkVersion 后代表的意义是:开发者已经知道了新的 SDK 行为,并且确认这个行为是 App 所需要的。所谓的确认通常指的是要在参数指定之对应版本的运行环境中做过测试,而不光只是编译成功。

依照以上的说明,如果在更换了 targetSdkVersion 内容,却还是使用万年的模拟器设定来进行测试,以致模拟器上系统的版本一直没换,这时就有必要重新检讨开发时的测试策略了。

minSdkVersion

最直接的用途就是要求 Google Play 设定 App 可被安装的系统版本最底限,在这个版本之后的则不会被限制。

对开发者来说有另外一个要观注的重点和 targetSdkVersion 一样,minSdkVersion 也具有相同的意义。试想有一个 App 是在 Android 4.4 (API 19)开发的,预期的是 AlarmManager#set 的新行为,但是当 minSdkVersion 的值比 API 19 小时,程式运作在 API 18 以下的环境中一定没有 AlarmManager#set 的新行为,这时 App 会产生什么结果?

如果是上架很久的 App,源代码应该也是对应着系统版本演进的历程做修改。所以源代码中或多或少都有包含先前所提到和 SDK 类似用系统版本来判断程式要运行的新、旧逻辑区块,以适应各种不同版本的系统。在这种情况之下,minSdkVersion 理所当然的可以是很早期的版本数值。

如果是新开发的 App,因为没有经历过这些过程,所以 targetSdkVersion 和 minSdkVersion 在开发初始的阶段里意义上是一样的,这时对 minSdkVersion 调整最保守的做法应该是逐次逐版地往前调。当 minSdkVersion 的数值逐版向前调整时,也应逐版在对应的环境中做过测试,确保程式在旧行为下所呈现的结果也符合预期,并且在必要时要加上对新旧版本的判断式、补上合于旧版环境的源代码。

就像开头提到的文章中所指出,即使 14 亿台设备中的 0.7% 也是逼进一千万台可观的数字,如果不想放弃这样的商机,在砸了自己的招牌之前,还是乖乖地每一个版本确实地做好测试,否则宁可不要轻易地下调 minSdkVersion。

更多相关文章

  1. android将so打到jar包中并运行
  2. 解决cocos2d-X 2.0版本后创建的Android项目提示org.cocos2dx.lib
  3. 解决android ERROR: Unknown option '--no-crunch'(转载)
  4. Error:(27, 13) Failed to resolve: com.android.support.constr
  5. MAC android Studio 5.0 环境搭建
  6. android Forlinux framworks学习资料
  7. android源码编译报错:prebuilts/misc/linux-x86/bison/bison: 没
  8. Android(安卓)版本列表
  9. Android(安卓)Opencv例子Face-detection运行

随机推荐

  1. Android学习笔记之mainfest文件中android
  2. Android(安卓)使用com.j256.ormlite
  3. Android给View画边框
  4. android 动画总结
  5. android资料下载地址汇总
  6. Android获取本机Mac地址和IP地址
  7. Android(安卓)dependency ‘androidx.cor
  8. Android(安卓)SQLite是线程安全的吗?
  9. android viewholder
  10. android EditText 去除边框