Android targetSdkVersion改为25引入问题实例分析:动态权限、FileUriExposedException

以前工作开发的app因为历史原因,targetSdkVersion一直停留在21,即android 5.0。而compileSdkVersion则偶有升级,目前停留在23.0.1。最近有机会从0开始搭建一个崭新的app,根据android的建议,complieSdkVersion和targetSdkVersion采用了最新的版本25。开发中较多代码从上个app移植,但出现了一些新的问题。

6.0动态权限问题

app中包含从图库选取图片视频及拍照的工作,6.0以上手机测试时出现了crash。根据日志信息,提示缺少READ_EXTERNAL_STORAGE权限。

//Manifest中明确申请了该权限

该问题出现的原因是6.0 (API 23) 之前,应用的权限在安装时全部授予,运行时不再询问用户;在6.0 或更高版本对权限进行了分类,对某些涉及到用户隐私的权限可在运行时根据用户的需要动态授予。
android系统将权限分为几个等级,如正常权限和危险权限。其中危险权限如下,需要在运行时动态申请。


Android targetSdkVersion改为25引入问题实例分析:动态权限、FileUriExposedException_第1张图片
image.png

解决方法是访问图库、拍照前,动态申请权限。代码如下:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if(this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                    || this.checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
                    || this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions( new String[]{
                        Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},100);

            } else {
                //加载media
            }
} else {
            //加载media
}

7.0拍照问题

测试中发现,7.0手机点击拍照crash。出错的拍照代码如下:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String fCapturePicture = new File(getExternalCacheDir(), PICTURE_NAME + System.currentTimeMillis() + ".jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(fCapturePicture));
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent, REQUEST_CODE_CAPTURE_PICTURE);

根据出错日志,拍照时出现FileUriExposedException异常。
问题原因:安卓为了提高私有文件的安全性,在targetSdk版本为N或者以后版本的app中,其私有目录将会限制访问。
第一种解决方法,使用ContentProvider方式传递uri:

ContentValues contentValues = new ContentValues(1);
contentValues.put(MediaStore.Images.Media.DATA, fCapturePicture.getAbsolutePath());
Uri uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);

第二种解决方法,使用FileProvider解决:
具体可参考http://www.jianshu.com/p/68a4e8132fcd

总结

同样的代码,不同的targetSdkVersion会导致不同的行为结果。采用高版本的最新的targetSdk,才可以体验到安卓系统最新的设计和行为。建议complileSdkVersion、targetSdkVersion都保持为最新版本

你可能感兴趣的:(Android targetSdkVersion改为25引入问题实例分析:动态权限、FileUriExposedException)