天使漫步IT工作室

android file provider 完全解析

一、关于Android 7.0 FileProvider

二、那些地方需要FileProvider?

凡是关于文件的访问(写操作)以及使用Intent传递uri的读操作都需要FileProvider。

出现以上这些api或者符号的地方都应该考虑使用FileProvider进行适配,否则会出现以下异常:

java.io.FileNotFoundException: No content provider

java.lang.IllegalArgumentException: Failed to find configured root that contains

uncaughtException:Failed to find configured root that contains

三、如何使用FileProvider

使用FileProvider需要注意三点:在Manifest.xml中定义一个Provider、在一个xml定义允许Provider临时授权的路径(并配置到Manifest.xml中),最后在代码中传入在Manifest.xml中定义的Provider。即:

第一步:在Manifest.xml中定义Provider


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

1、其中需要注意的是android:authorities的格式等于app的包名+Provider命名(此命名不区分大小写),例如:

若包名为:com.angel.app,Provider命名为:fileProvider
那么:android:authorities = "com.angel.app.fileProvider"

2、android:resource的值为第二步定义的临时授权路径集合。

第二步:在xml中定义临时授权路径集合。

在res中新建xml文件夹,然后在xml文件夹中新建file_paths.xml文件,在该xml中定义要临时授权的路径。

例如:

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

    <!-- /storage/emulated/0/Download/${applicationId}/.beta/apk-->
    <external-path
        name="beta_external_path"
        path="Download/"/>
    <!--/storage/emulated/0/Android/data/${applicationId}/files/apk/-->
    <external-path
        name="beta_external_files_path"
        path="Android/data/"/>
    <!-- external-path = /storage/emulated/0 -->
    <external-path
        name="files"
        path="Android/data/com.xxx/file/"/> //报名底下的file

    <external-path
        name="external_image_files_path"
        path="DCIM/"/>

    <!-- 代表cache目录下的所有文件-->
    <cache-path
        name="cache_path"
        path="."/>

</paths>

在paths规则下,能够定义的标签有五个,分别是:external-pathexternal-files-pathexternal-cache-pathfiles-pathcache-path

那么这些标签对应那些路径呢?又对应哪些API呢?

1、external-path 对应根目录为/storage/emulated/0的路径,即Environment.getExternalStorageDirectory()获取的路径。
2、cache-path 对应于根目录为getCacheDir() api获取的路径。
3、files-path 对应于根目录为Context.getFilesDir()获取的路径。

以上三个是app最常用的访问路径、其余的符号可以通过查询google文档获知。

回到上面配置,name可以是任意命名,只要xml文件定义域内不冲突即可,path值为在标签根目录下授权的具体路径,如external-path中的path为Download/,那么授权的路径就是:/storage/emulated/0/Download/下所有的文件。

即最终授权的路径为:external-path代表的根路径 + path定义的路径。

第三步:在代码中使用FileProvider

使用FileProvider的代码很简单,只需要在生成uri的时候调用一下FileProvider.getUriForFile 类似的api即可。例如:

// 最后通知图库更新
        Uri contentUri;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            contentUri = FileProvider.getUriForFile(context, "com.xxx.fileProvider", file);
        } else {
            contentUri = Uri.parse("file://" + file.getAbsolutePath());
        }
        context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, contentUri));

在getUriForFile中使用到的authority参数即为Manifest中定义的authorities的值(需要和Manifest保持一致)。

上面代码对低版本提供的兼容代码,因为android N以下无需进行额外的适配。

四、最后总结

java.io.FileNotFoundException: No content provider: /storage/emulated/0/Android/data/

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »