新手的第一个Android项目该如何选择targetSdkVersion

2017-03-06 17:27 阅读 1,818 次 评论 0 条
版权声明:本文著作权归TeachCourse所有,未经许可禁止转载,谢谢支持!
转载请注明出处:http://teachcourse.cn/2360.html

摘要:

新手的第一个Android项目或许没有认真考虑过如何选择targetSdkVersion的问题,也或许还有一部分像TeachCourse一样的开发者,积累一些工作经验后才回头来思考这个问题。那么该如何选择一个targetSdkVersion的属性值?一个属性值为23的targetSdkVersion表示什么含义?那么API 24和Android 7.0又是什么关系?为什么API 19开发的Android项目可以在Android 7.0系统的手机上运行,反之Android 4.x系统的手机可以运行API 24开发的Android项目?最后,正确理解compileSdkVersion、minSdkVersion和targetSdkVersion三者之间的关系。

应用程序接口和Android系统关系

一、认识targetSdkVersion

targetSdkVersion即目标软件开发版本,在创建每一个Android项目的时候都需要选择targetSdkVersionminSdkVersion,一个targetSdkVersion的属性值表示创建的Android项目使用哪个API版本,一个API版本使用一个整型数字表示,API的全称是Application Programming Interface,即应用程序编程接口,API 19对应的编程接口和API 23定义的编程接口存在差别,因为使用整型数字表示targetSdkVersion的属性值,容易记忆和便于比较它们之间的大小,高版本API编程接口可以兼容低版本API编程接口,反之则不行。

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

不知道开发者也没有注意到,为什么API 19开发的Android项目可以在Android 7.0系统的手机上运行,反之Android 4.x系统的手机可以运行API 24开发的Android项目,它们运行的效果是否一样呢?如果是Android 7.0系统运行API 24开发的应用程序,效果又是怎么样?这就让TeachCourse联想到了API 23开发的应用程序在低于Android 6.0系统上运行时,如果权限被禁用后,会提示如下图:

运行时权限

但是,如果API 23开发的应用程序在高于或等于Android 6.0系统的手机上运行时需要自己定义打印上述Toast,下面是完整的运行时权限申请的代码:


    private static final int REQUEST_CODE_PERMISSION=0x112;
    private void initPermission() {
        int flag= ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
        if(PackageManager.PERMISSION_GRANTED!=flag){
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA}, REQUEST_CODE_PERMISSION);
        }else{
            alterImageNew();
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (REQUEST_CODE_PERMISSION==requestCode){
            switch (grantResults[0]){
                case PackageManager.PERMISSION_DENIED:
                    boolean isSecondRequest=ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.CAMERA);
                    if(isSecondRequest)
                        ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},REQUEST_CODE_PERMISSION);
                    else
                        Toast.makeText(this, "拍照权限被禁用,请在权限管理修改", Toast.LENGTH_SHORT).show();
                    break;
                case PackageManager.PERMISSION_GRANTED:
                    alterImageNew();
                    break;
            }
        }
    }

如果需要显示类似于上面图片显示的Toast提示,开发者需要在onRequestPermissionResult回调方法中,打印拍照权限被禁用,请在权限管理修改这句话,在使用API 23应用程序编程接口开发的APP中都可以反复复制上面代码,仅将CAMERA替换成定义的权限参数,将alterImageNew()替换成拥有权限后要执行的代码。

举这个例子的目的,想要说明为什么在API 23版本开发的APP在低于Android 6.0系统不会执行上述代码的原因。

高版本的API定义了一些的编程接口,但是通常不需要开发者考虑是否高版本API开发的APP在低版本的Android系统的兼容性问题,APIAndroid系统是两个不一样的概念,API属于应用层的东西,Android系统属于底层的东西,开发者想要显示底层的演示效果,就需要使用API来完成,如果想要不同的演示效果,又需要考虑选择哪个版本的API,也就是文章的标题提到的:如何选择targetSdkVersion属性值的问题。

二、如何选择targetSdkVersion

一个Android系统,对外提供一套API,如何选择targetSdkVersion取决于应用程序需要实现的功能,如果你的应用程序使用API 7就可以实现的功能,可以不用考虑使用API 24,使用低版本API的其中一个好处,可以让更多的Android系统运行的效果保持一致,即兼容性更好,打个比方:API 7开发的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摈弃或新增一些类和方法时需要注意的其中一个问题。

API版本号和Android系统关系

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


    /**
     * 调用系统相机
     */
    private void goToTakePhoto() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            File file = new File(mSDCardPath, System.currentTimeMillis() + ".jpg");
            /**Android 7.0以上的方式**/
            Uri contentUri = getUriForFile(this, getString(R.string.install_apk_path), file);
            grantUriPermission(getPackageName(), contentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
            /**Android 7.0以前的方式**/
//            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
            startActivityForResult(intent, RESULT_CAPTURE_IMAGE);
        } else {
            Toast.makeText(this, "sdcard不存在", Toast.LENGTH_SHORT).show();
        }
    }

想要查看完整的例子,文章后面附上源码,可以下载测试。本来已经代码可以实现的拍照功能,API 24开发的APP在Android 7.0以上系统需要至少四个步骤:

  1. 在AndroidManifest.xml文件中定义一个FileProvider
  2. 指定写入或读取本地文件的目录
  3. 生成完整的URI
  4. 请求授予URI权限
  5. 实现手机拍照并保存本地功能

三、关于minSdkVersion和compileSdkVersion

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

minSdkVersion含义

继续在上述代码,造成的结果大于或等于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有什么用呢?选择最新的API版本,在编译的时候检查代码的错误和警告,提示开发者修改和优化,因为通常在Android项目中会引入第三方的支持库,支持库使用了23.1.1版本,compileSdkVersion的属性值至少为23.0.0,新版本的支持库的发布紧跟着对应的Android系统平台,能够更好的兼容。

四、targetSdkVersion、minSdkVersion和CompileSdkVersion之间的关系

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

targetSdkVersion区别

你会发现在使用Android Studio开发工具时,手动修改AndroidManifest.xml的属性值,使用Gradle构建后,将会被忽略,最终生成的是build.gradle配置文件指定的属性值。它们之间的关系如下:

minSdkVersion <= targetSdkVersion <= compileSdkVersion

参考资料:
https://developer.android.com/guide/topics/manifest/uses-sdk-element.html

ps:

Demo已上传GitHub,路径nougat\WriteToReadActivity.java

关注公众号 扫一扫二维码,加我QQ

如果文章对你有帮助,欢迎点击上方按钮关注作者

来源:TeachCourse每周一次,深入学习Android教程,关注(QQ1589359239或公众号TeachCourse)
转载请注明出处:http://teachcourse.cn/2360.html

资源分享

下载源码
Android SDK “Error when loading the SDK” Android SDK “Error when
Android开发之深入理解Android 7.0系统权限更改相关文档 Android开发之深入理解Android
解决代理账号或FQ:Genymotion离线安装包 解决代理账号或FQ:Genymotio
关于如何解决“NoClassDefFoundError”错误的问题? 关于如何解决“NoClassDefFo

发表评论

呲牙 憨笑 坏笑 偷笑 色 微笑 抓狂 睡觉 酷 流汗 鼓掌 大哭 可怜 疑问 晕 惊讶 得意 尴尬 发怒 奋斗 衰 骷髅 啤酒 吃饭 礼物 强 弱 握手 OK NO 勾引 拳头 差劲 爱你

表情