【随心笔录】Android N 文件Uri传递,报出FileUriExposedException异常,使用FileProvider

1 篇文章 0 订阅
1 篇文章 0 订阅

一、问题原因

  • 报出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)拍照
//Android N 使用FileProvider
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);
    }

    // 指定照片保存路径(SD卡)
    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
    startActivityForResult(intent, CAMERA_WITH_DATA);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值