Android targetSdkVersion 原理

17 January 2016

前几天 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 系统提供前向兼容的主要手段。这是什么意思呢?随着 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 需要做完整的测试了。

写完这篇文章,再回头去看一下原文的 targetSdkVersion 那一段,发现作者是说的多么“滴水不漏”。

Android targetSdkVersion详解相关推荐

  1. android WebView详解,常见漏洞详解和安全源码(上)

    这篇博客主要来介绍 WebView 的相关使用方法,常见的几个漏洞,开发中可能遇到的坑和最后解决相应漏洞的源码,以及针对该源码的解析.  由于博客内容长度,这次将分为上下两篇,上篇详解 WebView ...

  2. 【转】Android菜单详解——理解android中的Menu--不错

    原文网址:http://www.cnblogs.com/qingblog/archive/2012/06/08/2541709.html 前言 今天看了pro android 3中menu这一章,对A ...

  3. Android菜单详解——理解android中的Menu

    前言 今天看了pro android 3中menu这一章,对Android的整个menu体系有了进一步的了解,故整理下笔记与大家分享. PS:强烈推荐<Pro Android 3>,是我至 ...

  4. Android LayoutInflater详解

    Android LayoutInflater详解 在实际开发中LayoutInflater这个类还是非常有用的,它的作用类 似于findViewById().不同点是LayoutInflater是用来 ...

  5. android Fragments详解

    android Fragments详解一:概述 android Fragments详解二:创建Fragment 转载于:https://my.oschina.net/liangzhenghui/blo ...

  6. android WebView详解,常见漏洞详解和安全源码(下)

    上篇博客主要分析了 WebView 的详细使用,这篇来分析 WebView 的常见漏洞和使用的坑.  上篇:android WebView详解,常见漏洞详解和安全源码(上)  转载请注明出处:http ...

  7. android子视图无菜单,Android 菜单详解

    Android中菜单分为三种,选项菜单(OptionMenu),上下文菜单(ContextMenu),子菜单(SubMenu) 选项菜单 可以通过两种办法增加选项菜单,一是在menu.xml中添加,该 ...

  8. Android StateFlow详解

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/121913352 本文出自[赵彦军的博客] 文章目录 系列文章 一.冷流还是热流 S ...

  9. Android SharedFlow详解

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/121911675 本文出自[赵彦军的博客] 文章目录 系列文章 什么是SharedF ...

最新文章

  1. 人工智能筑起网络安全“铜墙铁壁”
  2. python label怎么用_python tkinter label标签怎么使用?
  3. SHELL脚本--简介
  4. Kubuntu中thunderbird最小化到任务栏
  5. java定义dll文件位置,生成网站时如何设置固定的dll文件名?-Java架构师必看
  6. layer中嵌套的页面如何操作父页面_layui框架中layer父子页面交互详细解说
  7. jzoj2136-(GDKOI2004)汉诺塔【找规律,模拟】
  8. java多次点击时事件_click事件的累加绑定,绑定一次点击事件,执行多次
  9. python基础实训_python基础实践(三)
  10. 信息学奥赛一本通(1256:献给阿尔吉侬的花束)
  11. maven install 没反应
  12. hdu1166 敌兵布阵 线段树
  13. 让系统“飞”起来 读懂电脑虚拟内存常遇问题
  14. 解决weka打开不了package manner的方法!
  15. C++ 查看openCV版本
  16. Elasticsearch密码设置及其后续问题解决
  17. USB 为什么一般选择48MHz
  18. Unity 3D光源-Point Light点光源详解/灯泡、模拟灯光效果教程
  19. 帆软填报-根据角色/权限设置校验规则(含开关配置表校验)
  20. redhat 7.4 安装php,在 CentOS 中安装 PHP 7.4 的方法

热门文章

  1. 按键驱动的思路分析和代码实现
  2. 命令解释器的设计及实现
  3. 16位汇编相关寄存器
  4. python绘制折线图中文图例不显示_python使用matplotlib绘图时图例显示问题的解决...
  5. Android:安卓工程结构介绍
  6. ubuntu mysql自动备份_Ubuntu下mysql数据库自动备份脚本
  7. 161. Leetcode 55. 跳跃游戏 (贪心算法-贪心区间)
  8. 从C语言的角度重构数据结构系列(五)-C语言的程序结构和基本语法
  9. tableau可视化数据分析60讲(二)-tableau入门篇之各模块功能介绍
  10. 规则化和模型选择(Regularization and model selection)