解决Android7.0系统 调用系统相机、系统播放器播放视频、切图兼容问题,报异常android.os.FileUriExposedException

来源:互联网 发布:mac 命令行上传文件 编辑:程序博客网 时间:2024/06/05 14:09

Android7.0以前获取本地文件uri用的Uri.fromFile(new File(filePath)); 后会得到一个file://,这种方式呢7.0及以后的系统版本就用不了,且会报一个异常:

android.os.FileUriExposedException
file:///storage/emulated/0/Android/data/com.alex.demo/cache/.tmp/show.mp4 exposed beyond app through Intent.getData()

举个例子:

String filePath = "/storage/emulated/0/Android/data/com.alex.demo/cache/.temp.jpg";Uri uri = Uri.fromFile(new File(filePath));这个uri打印出来就是"file:///storage/emulated/0/Android/data/com.alex.demo/cache/.temp.jpg" 

注意:文件路径和uri路径是不一样的,注意区分,文件路径时没有"file://"前缀的哦


Android7.0及以上系统版本由于共享文件权限的限制,方法不一样了,需要用FileProvider.getUriForFile()

举个例子:

String filePath = "/storage/emulated/0/Android/data/com.alex.demo/cache/.temp.jpg";Uri uri = FileProvider.getUriForFile(BaseApplication.getApplication(), BaseApplication.getApplication().getPackageName() + ".FileProvider", new File(filePath));这个uri打印出来是"content://com.alex.demo.FileProvider/external_storage_root/cache/.temp.jpg";

下面介绍下我们常用的几个功能的具体代码,保证目前的主流版本都可以兼容使用。

首先声明:com.alex.demo为项目的包名,以下需要包名的地方替换即可

第一步、

 在AndroidManifest.xml中加上摄像头、读写磁盘的权限,如下

<uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


第二步、

 在AndroidManifest.xml中加上自定义权限的ContentProvider,如下

<provider            android:name="android.support.v4.content.FileProvider"            android:authorities="com.alex.demo.FileProvider"            android:exported="false"            android:grantUriPermissions="true">            <meta-data                android:name="android.support.FILE_PROVIDER_PATHS"                android:resource="@xml/file_paths" />        </provider>

android:authorities="com.alex.demo.FileProvider" 自定义的权限
android:exported="false" 是否设置为独立进程
android:grantUriPermissions="true" 是否拥有共享文件的临时权限
android:resource="@xml/external_storage_root" 共享文件的文件根目录,名字可以自定义

第三步、

在项目res目录下创建一个xml文件夹,里面创建一个file_paths.xml文件,上一步定义的什么名称,这里就什么名称,如图:


<?xml version="1.0" encoding="utf-8"?><paths>    <external-path        name="external_storage_root"        path="." /></paths>

name="external_storage_root" 这个是根目录名称,可以自定义

好了,基本工作准备好,下面开始具体的使用吧


1、调用系统相机

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);            String filePath = ShowConfig.getCacheFolderPath() + File.separator + ".temp.jpg";            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {                mOriginUri = FileProvider.getUriForFile(BaseApplication.getApplication(), BaseApplication.getApplication().getPackageName() + ".FileProvider",                        new File(filePath));            } else {                mOriginUri = Uri.fromFile(new File(filePath));            }            intent.putExtra(MediaStore.EXTRA_OUTPUT, mOriginUri);            if(mAttachedFragment == null)                mAttachedActivity.startActivityForResult(intent, REQUEST_CROP_CAM_IMG_CODE);            else                mAttachedFragment.startActivityForResult(intent, REQUEST_CROP_CAM_IMG_CODE);

2、调用系统播放器播放视频

Intent intent = new Intent();            intent.setAction(android.content.Intent.ACTION_VIEW);            File file = FileUtils.createFile(mSelectedVideoPath);            Uri uri;            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);                Uri contentUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".FileProvider", file);                intent.setDataAndType(contentUri, "video/*");            } else {                uri = Uri.fromFile(file);                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                intent.setDataAndType(uri, "video/*");            }            startActivity(intent);

3、切图

Intent intent = new Intent("com.android.camera.action.CROP");                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);                intent.setDataAndType(uri, "image/*");                Uri customUri = null;                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {                    customUri = FileProvider.getUriForFile(BaseApplication.getApplication(), BaseApplication.getApplication().getPackageName() + ".FileProvider",                            new File(mLocalAvatarImagePath));                } else {                    customUri = Uri.fromFile(new File(mLocalAvatarImagePath));                }                intent.putExtra("output", customUri);                intent.putExtra("crop", "true");                intent.putExtra("aspectX", 1);  // 裁剪框比例                intent.putExtra("aspectY", 0.75);//            intent.putExtra("outputX", mOutputWidth);  // 输出图片大小//            intent.putExtra("outputY", mOutputHeight);                intent.putExtra("scale", true);  // 去黑边                intent.putExtra("scaleUpIfNeeded", true);  // 去黑边                if(mAttachedFragment == null)                    mAttachedActivity.startActivityForResult(intent, REQUEST_UPLOAD_IMG_CODE);                else                    mAttachedFragment.startActivityForResult(intent, REQUEST_UPLOAD_IMG_CODE);


4、用系统安装器安装APK

Uri fileUri = null;                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {                                fileUri = FileProvider.getUriForFile(BaseApplication.getApplication(), BaseApplication.getApplication().getPackageName() + ".FileProvider",                                        new File(filePath));                            } else {                                fileUri = Uri.fromFile(new File(filePath));                            }                            Intent installIntent = new Intent(Intent.ACTION_VIEW);                            installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                            installIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);                            installIntent.setAction(Intent.ACTION_VIEW);                            installIntent.setDataAndType(fileUri,                                    "application/vnd.android.package-archive");                            context.startActivity(installIntent);


注意:通过content类型的uri和file类型的uri来获取文件的时候要注意方法的不同







2 0
原创粉丝点击