Relationship between minSdkVersion, compileSdkVersion, targetSdkVersion, buildeToolVersion

Here is a brief introduction, followed by a detailed description 
minSdkVersion: The minimum requirements that the application can run 
compileSdkVersion: Control which version of the api can be used  
targetSdkVersion: The compatibility mode of the application

minSdkVersion


As the name implies, the minimum sdk version required for the app to run. Phones lower than minSdkVersion will not be able to install it.

minSdkVersion also plays an important role during development: lint runs by default in the project, it warns you when you use an API higher than minSdkVersion, and helps you avoid runtime problems calling non-existing APIs (eg minSdkVersion 9 But you will be warned if you use the API that is only available in sdkVersion 10).

If some APIs are only used on a higher version of the system, it is usually solved by checking the system version at runtime. 
like this

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            //do something
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
            //do something
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7


compileSdkVersion


compileSdkVersion tells Gradle which Android SDK version to use to compile your app. Using any newly added API requires the corresponding version of the Android SDK.

Modifying compileSdkVersion does not change runtime behavior. When you modify compileSdkVersion, new compilation warnings and compilation errors may appear, but the new compileSdkVersion is not included in the APK: it is used purely at compile time.

注意,如果使用 Support Library ,那么使用最新发布的 Support Library 就需要使用最新的 SDK 编译。例如,要使用 23.1.1 版本的 Support Library ,compileSdkVersion 就必需至少是 23 。 

targetSdkVersion


三个属性中最难懂的就是这个了targetSdkVersion 是 Android 提供向前兼容的主要依据,在应用的 targetSdkVersion 没有更新之前系统不会应用最新的行为变化。

具体点就是随着 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 这两个 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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

看到这里,首选获取应用的 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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

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

getApplicationInfo().targetSdkVersion; 
  • 1

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

所以当我们修改了 APK 的 targetSdkVersion 后行为会发生变化,也就必须做完整的测试了。 

综合来看三个属性的关系是 
minSdkVersion <= targetSdkVersion <= compileSdkVersion

理想上,在稳定状态下三者的关系应该更像这样: 
minSdkVersion (lowest possible) <= targetSdkVersion == compileSdkVersion (latest SDK) 
用较低的 minSdkVersion 来覆盖最大的人群,用最新的 SDK 设置 target 和 compile 来获得新版本最好的效果。



buildeToolVersion

1、CompileSdkVersion是你SDK的版本号,也就是API Level,例如API-19、API-20、API-21等等。

2、buildeToolVersion是你构建工具的版本,其中包括了打包工具aapt、dx等等。这个工具的目录位于..your_sdk_path/build-tools/XX.XX.XX

在android studio 中 CompileSdkVersion >= buildeToolVersion


The compileSdkVersion (24) should not be lower than the targetSdkVersion (26) less... (⌘F1) 
There are some combinations of libraries, or tools and libraries, that are incompatible, or can lead to bugs. One such incompatibility is compiling with a version of the Android support libraries that is not the latest version (or in particular, a version lower than your targetSdkVersion.)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325475499&siteId=291194637