android之targetSdkVersion引发的一场雪岸

2,443 阅读4分钟

前几天由于某些原因项目Android SDK由28升级到了29,OKHttp由3.x升级到4.9, 隐藏的危险一步一步逼近。

    javaSDKVersion   : 1.8,
    compileSdkVersion: 28 -> 29,
    buildToolsVersion: "28.0.0" -> "29.0.3",
    minSdkVersion    : 15,
    targetSdkVersion : 28 -> 29,
  

在andorid 8.0手机中没有什么问题
在android 10手机中 很卡、闪退等各种问题

解决问题:将targetSdkVersion修改为原来的28

出现原因:暂时没有时间,后面再看看什么原因

compileSdkVersion

compileSdkVersion 告诉 Gradle 用哪个 Android SDK 版本编译你的应用。它纯粹只是在编译的时候使用。当你修改了 compileSdkVersion 的时候,可能会出现新的编译警告、编译错误等(你真的应该修复这些警告,他们的出现一定是有原因的)。需要强调的是修改 compileSdkVersion 不会改变运行时的行为,compileSdkVersion 并不会打包进APK里只是在编译时使用

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

注意,如果使用 Support Library ,那么使用最新发布的 Support Library 就需要使用最新的 SDK 编译。通常,新版的 Support Library 随着新的系统版本而发布,它为系统新增加的 API 和新特性提供兼容性支持。例如,要使用 23.1.1 版本的 Support Library ,compileSdkVersion 就必需至少是 23 (大版本号要一致!)

minSdkVersion

minSdkVersion 是应用可以运行的最低版本要求。minSdkVersion 是 Google Play 商店用来判断用户设备是否可以安装某个应用的标志之一。

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

请记住,你所使用的库可能有他们自己的 minSdkVersion 。你的应用设置的 minSdkVersion 必需大于等于这些库的 minSdkVersion 。例如有三个库,它们的 minSdkVersion 分别是 4, 7 和 9 ,那么你的 minSdkVersion 必需至少是 9 才能使用它们。在少数情况下,你仍然想用一个比你应用的 minSdkVersion 还高的库(处理所有的边缘情况,确保它只在较新的平台上使用),你可以使用 tools:overrideLibrary 标记,但请做彻底的测试!

targetSdkVersion

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,就还是按照老的行为,即精确设置唤醒时间,否者执行新的行为。

修改了APK的 targetSdkVersion 行为会发生变化,需要做完整的测试

buildToolsVersion

android构建工具的版本,在SDK Manager中安装选择版本, buildToolsVersion>=CompileSdkVersion; 高版本的build-tools 可以构建低版本编译的android程序

Gradle和SDK版本

minSdkVersion 和 targetSdkVersion 会被Gradle打包进最终的APK文件AndroidManifest.xml

更具体的在这里