一、问题原因
- 报出FileUriExposedException异常,官网上搜索,发现在Android N的behavior-changes里面,有一些关于 FileUriExposedException 异常的描述:
- 对于面向 Android N 的应用,Android 框架执行的 StrictMode,API 禁止向您的应用外公开 file://URI。
如果一项包含文件 URI 的 Intent 离开您的应用,应用失败,并出现 FileUriExposedException异常。 - 若要在应用间共享文件,您应发送一项 content://URI,并授予 URI临时访问权限。
进行此授权的最简单方式是使用 FileProvider类。 如需有关权限和共享文件的更多信息,
请参阅共享文件。
- 也就是说,对于应用间共享文件这块,Android N中做了强制性要求。
二.解决步骤
1.要用到类:android.support.v4.content.FileProvider
- 在清单文件AndroidManifest.xml里面注册这个provider,注册如下:
<provider
android:authorities="app包名.android7.fileprovider" //个人解释:权限字符串,唯一就行
android:name="android.support.v4.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
//resource中的@xml/file_paths是我们接下来要添加的文件
</provider>
2.file_paths.xml文件
- 在res文件下新增xml文件,新建file_paths.xml。
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path
name="root"
path="" />
<files-path
name="files"
path="" />
<cache-path
name="cache"
path="" />
<external-path
name="external"
path="" />
<external-files-path
name="external-file-path"
path="" />
<external-cache-path
name="external-cache-path"
path="" />
</paths>
3.使用工具类FileProvider7
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import java.io.File;
public class FileProvider7 {
public static Uri getUriForFile(Context context, File file) {
Uri fileUri = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
fileUri = getUriForFile24(context, file);
} else {
fileUri = Uri.fromFile(file);
}
return fileUri;
}
private static Uri getUriForFile24(Context context, File file) {
return android.support.v4.content.FileProvider.getUriForFile(context, "app包名.android7.fileprovider", file);
}
public static void setIntentDataAndType(Context context, Intent intent, String type, File file, boolean writeAble) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setDataAndType(getUriForFile(context, file), type);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (writeAble) {
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
} else {
intent.setDataAndType(Uri.fromFile(file), type);
}
}
}
4.使用
(1)拍照
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
Uri imageUri = FileProvider7.getUriForFile(context, new File(Environment.getExternalStorageDirectory(), FileManager.SaveCameraPath() + name));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
} else {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, CAMERA_WITH_DATA);
}