Android-0.Android中minsdkversion和targetSdkVersion的选择

问题

在调用系统播放mp4时,代码如下:

 private void viewMediaFile(String path) {
        if (!TextUtils.isEmpty(path)) {
            String type = "video/*";
            if (path.contains("png") || path.contains("jpeg") || path.contains("jpg")) {
                type = "image/*";
            }
            String value = String.valueOf(path);
            File file = new File(value);

            Intent intent = new Intent();
            intent.setAction(android.content.Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(file), type);
            startActivity(intent);
        }
    }

发现原工程可以正常调用,而我的demo却直接崩溃了,错误如下:

android.os.FileUriExposedException: 
file:///storage/emulated/0/Movies/VID_88.mp4 exposed beyond app through Intent.getData()

最后得出结论为targetSdkVersion不同,我的demo设置成了28,而原工程是21,从而导致行为不同。

简介

targetSdkVersion即目标软件开发版本,在创建每一个Android项目的时候都需要选择targetSdkVersionminSdkVersion,一个targetSdkVersion的属性值表示创建的Android项目使用哪个API版本,高版本API编程接口可以兼容低版本API编程接口,反之则不行。

Android 7.0定义的手机系统的版本,该系统的版本对外开放的应用程序接口被定义为API 24,如果开发者想要使用Android 7.0系统提供的新功能,这些功能包括:多窗口支持、通知显示变更、JIT/AOT编译、快速的应用安装路径等,那么就需要选择API 24的应用程序接口。

 targetSdkVersion 24

API 19开发的Android项目在Android 7.0系统的手机上运行。

API 24开发的Android项目在Android 4.x系统的手机上运行。
它们运行的效果是否一样呢?
API 23开发的应用程序在低于Android 6.0系统上运行时,如果权限被禁用后,会提示如下图:

但是,如果API 23开发的应用程序在高于或等于Android 6.0系统的手机上运行时需要自己定义运行时权限申请的代码:
https://blog.csdn.net/hgy413/article/details/82968070
如果需要显示类似于上面图片显示的Toast提示,开发者需要在onRequestPermissionResult回调方法中,打印拍照权限被禁用,请在权限管理修改这句话。

举这个例子的目的,想要说明为什么在API 23版本开发的APP在低于Android 6.0系统不会执行上述代码的原因。
高版本的API定义了一些编程接口,但是通常不需要开发者考虑是否高版本API开发的APP在低版本的Android系统的兼容性问题,API和Android系统是两个不一样的概念,API属于应用层的东西,Android系统属于底层的东西,开发者想要显示底层的演示效果,就需要使用API来完成,如果想要不同的演示效果,又需要考虑选择哪个版本的API,也就是文章的标题提到的:如何选择targetSdkVersion属性值的问题。

如何选择targetSdkVersion

一个Android系统,对外提供一套API,如何选择targetSdkVersion取决于应用程序需要实现的功能,如果你的应用程序使用API 10就可以实现的功能,可以不用考虑使用API 24,使用低版本API的其中一个好处,可以让更多的Android系统运行的效果保持一致,即兼容性更好,打个比方:API 10开发的APP可能兼容98%以上的Android手机,而API 24开发的APP可能兼容仅有60%,所谓的不兼容并不是无法正常运行,而是在不同Android系统的手机运行的效果差异比较大,会让用户感觉难以接受;
使用低版本API的其中一个不足,显示的效果比较OUT,提供的可用的接口或类比较少,本来一句代码可以完成的功能(封装的类或接口),需要自己花一天琢磨写很多的代码,也就是有高版本API的其中一个原因,提供更多的或封装好的应用程序接口让开发者使用。

同时,高版本API会针对低版本存在的问题进行改进和完善,摈弃一下不用的类或接口,新增一些方法或属性,如果你使用的方法是在某个API被另一个方法代替的话,你可能就得在代码中区分APP是运行在哪个版本的Android系统。一个很典型的例子:
WebChromeClientonShowFileChooser()方法和openFileChooser()方法,如果你的targetSdkVersion小于19,在处理WebView上传表单的数据的时候就需要重写openFileChooser方法;如果你的targetSdkVersion大于或等于19,你就必须同时重写onShowFileChooseropenFileChooser两个方法,openFileChooser方法在Android 4.0以下系统被回调,另一则在Android 4.0以上系统被回调。这是高低版本API摈弃或新增一些类和方法时需要注意的其中一个问题。

了解并学习Android 4.x、Android 5.x、Android 6.x或Android 7.x系统的特性,重点掌握不同系统同一个功能的实现方式,即行为变更,特点:变更的行为在当前系统或更高系统版本中被支持,一个简单的例子:Android 7.0系统其中的一个行为变更是权限更改,尝试传递file:// URI 的方式写入本地文件或读取本地文件,使用API 24开发的APP将会触发 FileUriExposedException异常,也即文章开头提到的问题。

关于minSdkVersion和compileSdkVersion

minSdkVersion定义应用程序支持的最低API版本,最低版本设置为API 11,目标版本设置为API 24,那么应用程序调用使用API 14提供的方法时,Android Studio将提醒开发者引用一个未定义的方法,使用该方法需要将minSdkVersion设置为API 14以上,如下图:

继续在上述代码,造成的结果大于或等于Android 4.0的系统可以正常执行,小于Android 4.0的系统将在运行时尝试访问不可用的API 时发生崩溃。

compileSdkVersion定义应用程序编译选择哪个Android SDK版本,通常compileSDKVersion属性值被设置为最新的API版本,例如:25,改变compileSDKVersion的属性值不会影响Android系统运行行为,比如说,将属性值设置为25,targetSdkVersion属性值为23,代码如下:

    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "cn.teachcourse.demos"
        minSdkVersion 11
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

开发的应用程序在Android 7.0系统运行,不会以Android 7.0新增的行为运行,决定Android系统行为的仍然是targetSDKVersion,那么compileSDKVersion有什么用呢?

因为环境是compileSdkVersion这个版本的SDK,所以你可以用一些这个版本的API,但是只是IDE给你的便利性帮助而已,帮助你检测代码,避免使用一些弃用的API。就算你用个低版本的compileSdkVersion,你依然可以那么写,但是可能会报错,报警告,但是你强制打包,其实也是没有问题的。IDE只是个工具,他的环境也只是工具的环境,不代表你应用运行时的表现。

targetSdkVersion、minSdkVersion和CompileSdkVersion之间的关系

记住一点:Android系统平台的行为变更,只有targetSdkVersion的属性值被设置为大于或等于该系统平台的API版本时,才会生效;compileSdkVersion属于Android编译项目时其中的一项配置,主要区别是compileSDKVersion不会被打包的APK文件中,targetSdkVersionminSdkVersion将被打包到APK文件中,具体可以解压APK文件后,查看AndroidManifest.xml文件,如下图:



最后总结

问题解答:
targetSdkVersion设置为小于24时,目标SDK可以正常使用上面问题的代码,但targetSdkVersion大于或等于24时,因为对于应用间共享文件这块,Android N中做了强制性要求,从而导致异常。

targetSdkVersion设置高的好处?
直接使用targetSdkVersion的新特性,而对于app在targetSdkVersion以下的目标机器运行,就需要自己模拟实现新特性了。

参考:
http://teachcourse.cn/2360.html


版权声明:本文为hgy413原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。