Android面试:compileSdkVersion、targetSdkVersion、minSdkVersion作用与区别

作用

Android Studio 新建一个工程后,build.gradle里会有compileSdkVerson、targetSdkVersion、minSdkVersion这几个字段,这些配置有啥意义呢?

compileSdkVersion:和编译时有关。

1、只和编译相关

比如我们当前compileSdkVersion=28(Andorid 9.0),Android 10 新增了有关5G的api。我们的app想尽早使用5G相关的api,这时只需要将compileSdkVersion=29(Android 10),就能在编译阶段编译通过。此外,还需要注意的是,由于这个5G api是新增的,因此需要判断当前系统版本>=29才能使用新api。

至于这个声明,其实不用太在意,它只是我们在查看源代码和编译时才发挥作用的,它与应用兼容性关系不大。它指定了 Gradle 用哪个版本的 API 级别来编译你的应用,这样你在代码里就能够使用这个 API 级别提供的方法和功能。

2、和运行时行为无关

开发的应用程序在Android 6.0系统运行,不会以Android 6.0新增的行为运行,决定Android系统行为的仍然是targetSDKVersion。那么compileSDKVersion有什么用呢?选择最新的API版本,在编译的时候检查代码的错误和警告,提示开发者修改和优化。

例如,在android6.0之前的系统是不需要动态申请权限的,在6.0之后的系统需要动态申请权限。这个和你的compileSdkVersion的版本选择是完全没有任何关系的。也就是说你app运行时需不需要动态申请权限和你complieSdk是否设置的6.0,没有半毛钱关系,记住compileSDK只是关系到你编译出来的包。不是运行的表现行为,决定Android系统行为的仍然是targetSDKVersion。

所以修改compileSdkVersion是不会改变你app在手机上运行的表现行为的。但是我们一般情况,也是最理想的情况就是把compileSdkVersion设置到最高,因为使用新的编译检查可以获得很多好处,可以避免弃用的API,并且为使用新的API做好准备。

minSdkVersion:

指定app运行的最低设备sdk版本,如minSdkVersion=19 表示该app最低支持Android 4.4(API 19)设备,低于此版本的设备将不能使用该app。继续在上述代码,造成的结果大于或等于Android 4.4的系统可以正常执行,小于Android 4.4的系统将在运行时尝试访问不可用的 API 时发生崩溃。

通过minSdkVersion告知 Android 系统,其正使用在指定 API 级别引入的 API。如果由于某种原因将应用安装在 API 级别较低的平台上,则它会在运行时试图访问不存在的 API 时发生崩溃。如果应用所需的最低 API 级别高于目标设备上平台版本的 API 级别,则系统不允许安装该应用,以防出现这种结果。

随着Android系统版本的持续更新,之前旧的系统版本占有率越来越低,我们可以根据需要将minSdkVersion值往后调整。

targetSdkVersion

直观翻译是“目标版本”,它的作用是兼容旧的api,怎么理解呢?那就看看这个字段用在哪些地方。举个例子,Android 8.0/8.1 系统规定了透明的activity 不能固定方向,否则抛出异常。我们暂时不管google设计的目的何在,先想想假设我们的app使用了透明的activity,且固定了方向,在Android 8.0版本以下运行正常,当我们运行在Android 8.0/8.1系统上,结果如何会如何呢?很不幸,直接crash。对于我们来说,这结果当然不能接受了,我一个好端端的app,你升级个Android 系统直接让我的app挂掉,没有转圜的余地,不科学啊。

因此,google想出了一个办法,那就是通过targerVersion字段来区分同一api在不同系统上的行为。我们来看看源码:Android 8.0 Activity onCreate

从上图可以看出:getApplicationInfo().targetSdkVersion取的值即是在build.gradle里设置的targetSdkVersion值,这里判断targetSdkVersion是否大于Android 8.0(O),如果成立才执行后续逻辑(透明且固定方向),进而抛出异常。在此我们知道,想让这段逻辑不成立,那么我们将targetSdkVersion设置为26(Android 8.0 对应26)以下,即使我们app运行在Andorid 8.0以上的设备,都不会出现问题。这样,我们的app不更新,但是新的Android SDK 里Activity onCreate方法变更了部分逻辑行为,通过targetSdkVersion限制,我们的app依然能够以旧的逻辑运行新的设备上,达到了兼容老版本api的目的。

总结来说:

对于同一个API(方法),新版本的系统更改了它的内部实现逻辑,新逻辑可能会影响之前调用此API的App,为了兼容此问题,引入targetSdkVersion。当targetSdkVersion>=xx(某个系统版本)时再生效其新修改的逻辑,否则还是沿用之前的逻辑。换句话说:如果你更改了targetSdkVersion值,说明你已经测试过兼容性问题了。

google建议:

    /**
     * The minimum SDK version this application targets.  It may run on earlier
     * versions, but it knows how to work with any new behavior added at this
     * version.  Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT}
     * if this is a development build and the app is targeting that.  You should
     * compare that this number is >= the SDK version number at which your
     * behavior was introduced.
     */
    public int targetSdkVersion;

大致意思就是:当我们更新targetSdkVersion时,比如从26(Android 8.0)变更到29(Android 9.0),意味着我们对26~29之间的系统兼容性进行了充分的测试,因此每当我们变更targerSdkVersion时,要充分测试其系统兼容性。
也许你会说,那我可以不更新targetSdkVersion值嘛,一劳永逸,理论上没啥问题。但是,如果你想在新的系统上使用api新的行为,那么就需要更新targetSdkVersion。再者,google会对targetSdkVersion进行一些强关联,比如app上传到google play,必须要求targetSdkVersion>=26(具体的值随着时间的推移,要求不一样)。

三者联系

compileSdkVersion>=targetSdkVersion>minSdkVersion

一句话总结:

targerVersion字段来区分同一api在不同系统上的行为:对于同一个API(方法),新版本的系统更改了它的内部实现逻辑,新逻辑可能会影响之前调用此API的App,为了兼容此问题,引入targetSdkVersion。当targetSdkVersion>=xx(某个系统版本)时再生效其新修改的逻辑,否则还是沿用之前的逻辑。换句话说:如果你更改了targetSdkVersion值,说明你已经测试过兼容性问题了。

minSdkVersion字段用来指定app运行的最低设备sdk版本,如minSdkVersion=19 表示该app最低支持Android 4.4(API 19)设备,低于此版本的设备将不能使用该app。

compileSdkVersion代表着编译的时候,会采用该api的规范进行代码检查和警告,但是并不会编译进apk中。开发的应用程序在Android 7.0系统运行,不会以Android 7.0新增的行为运行,决定Android系统行为的仍然是targetSDKVersion

猜你喜欢

转载自blog.csdn.net/cpcpcp123/article/details/114754529