Google 官方发布文章解析 compileSdkVersion、minSdkVersion 以及 targetSdkVersion 的含义,以及合理设置各个值的意义,原文 Picking your compileSdkVersion, minSdkVersion, and targetSdkVersion(后面简称 “原文”),还有翻译版。

其中,compileSdkVersion 和 minSdkVersion 都非常好理解,前者表示编译的 SDK 版本,后者表示应用兼容的最低 SDK 版本。但是对于 targetSdkVersion 其实很难一句话解析清楚,原文用了“万能”的词 —— interesting来描述。以前我也有一些迷糊,看到有些人和我有同样的困惑,本文试图彻底解决这个问题。

原文是这么说的:

targetSdkVersion is the main way Android provides forward compatibility

targetSdkVersion 是 Android 系统提供前向兼容的主要手段(即:新版本SDK手机兼容旧版本SDK工程)。这是什么意思呢?随着 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 4.4 上 AlarmManger 的一部分源代码:

private final boolean mAlwaysExact;  AlarmManager(IAlarmManager service, Context ctx) {      mService = service;    final int sdkVersion = ctx.getApplicationInfo().targetSdkVersion;    mAlwaysExact = (sdkVersion < Build.VERSION_CODES.KITKAT);}

看到这里,首选获取应用的 targetSdkVersion,判断是否是小于 Build.VERSION_CODES.KITKAT (即 API Level 19),来设置 mAlwaysExact变量,表示是否使用精确时间模式。

public static final long WINDOW_EXACT = 0;  public static final long WINDOW_HEURISTIC = -1;private long legacyExactLength() {      return (mAlwaysExact ? WINDOW_EXACT : WINDOW_HEURISTIC);}public void set(int type, long triggerAtMillis, PendingIntent operation) {      setImpl(type, triggerAtMillis, legacyExactLength(), 0, operation, null);}

这里看到,直接影响到 set() 方法给 setImpl()传入不同的参数,从而影响到了 set() 的执行行为。具体的实现在 AlarmManagerService.java,这里就不往下深究了。

看到这里,发现其实 Android 的 targetSdkVersion 并没有什么特别的,系统使用它也非常直接,甚至很“粗糙”。仅仅是用过下面的 API 来获取 targetSdkVersion,来判断是否执行哪种行为:

getApplicationInfo().targetSdkVersion;  

所以,我们可以猜测到,如果 Android 系统升级,发生这种兼容行为的变化时,一般都会在原来的保存新旧两种逻辑,并通过 if-else方法来判断执行哪种逻辑。果然,在源码中搜索,我们会发现不少类似 getApplicationInfo().targetSdkVersion < Buid.XXXX这样的代码,相对于浩瀚的 Android 源码量来说,这些还是相对较少了。其实原则上,这种会导致兼容性问题的修改还是越少越好,所以每次发布新的 Android 版本的时候,Android 开发者网站都会列出做了哪些改变,在这里,开发者需要特别注意。

最后,我们也可以理解原文中说的那句话的含义,明白了为什么修改了 APK 的 targetSdkVersion 行为会发生变化,也明白了为什么修改 targetSdkVersion 需要做完整的测试了。

总结:
android更新api大概有两种,一种是完全重写(这种就不干targetSdk什么事了);另一种,保留了老版本的处理逻辑,同时又新增了新的逻辑(用if else的方式来判断具体运行哪段逻辑)。而targetSdk就是用来判断这个if-else的。




转自:https://www.jianshu.com/p/20be54aab044

更多相关文章

  1. Nginx系列教程(六)| 手把手教你搭建 LNMP 架构并部署天空网络电影
  2. android 系统重启关机流程分析
  3. Android(安卓)调用相机以及调用系统图片软件浏览图片
  4. Android系统信息获取 之六:网络连接状态信息获取
  5. Android(安卓)YUV视频数据叠加时间信息
  6. Android(安卓)获取系统prop
  7. 基于rk3288平台android5.1系统的wifi流程分析 ---- 打开wifi,扫描
  8. android 2.3 频率管理
  9. android像launcher一样获取手机应用列表

随机推荐

  1. 一张图看明白 Android Handler 消息机制
  2. Android4.1 关于Rotation相关的Configura
  3. Android中WARNING: Application does not
  4. Android 判断Intent是否存在
  5. Android(安卓)Gradle 看这一篇就够了
  6. 使用android中的handler延迟执行方法
  7. Android开发SDK版本号和API level对照表,
  8. 如何查看android的avd中的sqlite数据库的
  9. Android 常用颜色
  10. Ubuntu 14搭建源码Android编译环境和Andr