Android7.0 FileProvider

一、前言

Android 7.0有很多的变化,和我们开发者关联最大的,或者说必须要适配的就是去除项目中传递 file:// 类似格式的 Uri 了。

要应用间共享文件,您应发送一项 content:// URI,并授予 URI 临时访问权限。进行此授权的最简单方式是使用 FileProvider 类,

FileProvider 实际上是 ContentProvider 的一个子类,它的作用也比较明显,file://Uri 不给用,那么换个 Uri 为 content:// 来替代。

二、使用步骤

1、在AndroidManifest.xml中注册

<manifest>
    ...
    <application>
        ...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.developerhaoz.androidtrainingdemo.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths"
                />
        </provider>
        ...
    </application>
</manifest>

FileProvider 是 ContentProvider 的子类,所以要声明

2、指定文件的分享路径

FileProvider 只能为指定的目录中的文件生成内容 URI。要指定目录,就必须使用 <paths> 元素的子元素在 XML 中指定其存储区域和路径,我们先创建一个名为 res/xml/file_paths.xml 的新文件:

在 file_paths.xml 文件中,便可以指定文件存储的区域和路径。例如,以下路径元素告诉 FileProvider,你打算为私有文件区域的 images/ 子目录 请求内容 URI:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="myimages" path="images/"/>
    ...
</paths>

<paths> 必须包含以下元素中一个或者多个子元素:

<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="name" path="path" />
    <external-cache-path name="name" path="path" />
</paths>

2019-04-25 13:59:48.032 13704-13704/? D/dongjiejie: getFileDir----/data/user/0/packagename/files
2019-04-25 13:59:48.033 13704-13704/? D/dongjiejie: getCacheDir----/data/user/0/packagename/cache
2019-04-25 13:59:48.037 13704-13704/? D/dongjiejie: getExternalStorageDirectory---/storage/emulated/0
2019-04-25 13:59:48.040 13704-13704/? D/dongjiejie: getExternalFilesDirs-----/storage/emulated/0/Android/data/packagename/files
2019-04-25 13:59:48.042 13704-13704/? D/dongjiejie: getExternalCacheDirs-----/storage/emulated/0/Android/data/packagename/cache

每个节点都有两个属性:name、path

<external-path name="external" path="pictures"/>

代表的目录即为:Environment.getExternalStorageDirectory()/pictures, 当这么声明以后,代码可以使用你所声明的当前文件夹以及其子文件夹

3、配置工作已经全部完成了,后面就需要将之前传递的 file:// 替换成 FileProvoider 需要用到的 content://,这就需要用到 FileProvider.getUriForFile() 方法了

public static Uri getUriForFile(Context context, String authority, File file) {
        final PathStrategy strategy = getPathStrategy(context, authority);
        return strategy.getUriForFile(file);
    }

可以看到 getUriForFile(),需要传入 一个
authority 的参数,这正是我们前面在 AndroidManifest.xml 文件中配置的 android:authorities 参数,调用这个方法会自动得到一个 file:// 转换成 content:// 的一个 Uri 对象,可以供我们直接使用

4、给Uri授予临时权限

例如:7.0上调用安装界面:

private void installApk(String apkName) {
        FileUtils mFileUtils = new FileUtils();
        Uri mUri;
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(Intent.ACTION_VIEW);
        //7.0系统开始认为直接使用本地Uri是不安全的 所以以FileProvider共享给外部提高安全性
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            mUri = FileProvider.getUriForFile(this, "com.manager.carmanager.fileProvider", mFileUtils.getApksFile(apkName));
        } else {
            mUri = Uri.fromFile(mFileUtils.getApksFile(apkName));
        }
        //添加这一句表示对目标应用临时授权该Uri所代表的文件
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setDataAndType(mUri,
                "application/vnd.android.package-archive");
        startActivityForResult(intent, 10025);
    }

 

总结:

Android 7.0 禁止在应用外部公开 file:// URI,所以我们必须使用 content:// 替代 file://,这时主要需要 FileProvider 的支持,而因为 FileProvider 是 ContentProvider 的子类,所以需要在 AndroidManifest.xml 文件中进行注册,而又因为需要对真实的 filepath 进行映射,所以需要编写一个 xml 文档,用于描述可使用的文件夹目录,以及通过 name 去映射该文件夹目录。当我们生成一个 content:// 的 Uri 对象之后,还需要对这个 Uri 接收的 App 赋予对应的权限

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值