美文网首页AndroidAndroid收藏集
Android 7.0 + FileProvider 访问隐私文

Android 7.0 + FileProvider 访问隐私文

作者: 12313凯皇 | 来源:发表于2019-07-18 17:02 被阅读0次

    参考文章:android 7.0+ FileProvider 访问隐私文件 相册、相机、安装应用的适配

    一、概述

    Android 7.0 开始,Android SDK 中的 StrictMode 策略禁止开发人员在应用外部公开 file:// URI。具体表现为,当我们在应用中使用包含 file:// URIIntent离开自己的应用时,程序会发生FileUriExposedException异常
    这里我们要使用到的 FileProvider,就是 ContentProvider 的一个特殊子类,帮助我们将访问受限的 file:// URI转化为可以授权共享的 content:// URI

    简单来说就是在Android 7.0及以上机型中如果需要访问手机文件,那么必须使用 FileProvider来进行适配,否则程序会报错。

    二、使用

    1. AndroidManifest.xml注册FileProvider
    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/files_paths" />
    </provider>
    

    • 这里的authorities可以自己定义,不过后面需要用到,只要保证前后一致即可。
    • resource内的xml文件是用来配置文件路径的,文件名可自定义。
    1. src\main\res\xml\文件夹下创建对应的files_paths.xml文件
    <!--files_paths.xml-->
    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
       <!--此处的name可以随便取-->
        <external-path
            name="external_storage_root"
            path="."/>
        <external-files-path name="document" path="Documents"/>
        <external-files-path name="download" path="Download" />
        <external-files-path name="pictures" path="Pictures" />
    </paths>
    

    xml中元素必须包含一到多个子元素。这些子元素用于指定共享文件的目录路径,必须是这些元素之一:

    • <files-path>:内部存储空间应用私有目录下的 files/目录,等同于 Context.getFilesDir()所获取的目录路径;
    • <cache-path>:内部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getCacheDir() 所获取的目录路径;
    • <external-path>:外部存储空间根目录,等同于 Environment.getExternalStorageDirectory()所获取的目录路径;
    • <external-files-path>:外部存储空间应用私有目录下的files/ 目录,等同于Context.getExternalFilesDir(null) 所获取的目录路径;
    • <external-cache-path>:外部存储空间应用私有目录下的cache/目录,等同于 Context.getExternalCacheDir()
    1. 使用FileProvider进行转换:
    //注意此处的 第二个参数必须与 Manifest文件中Provider 的 android:authorities 一致
    Uri contentUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".FileProvider", outputFile);
    

    此处需要传进三个参数,第一参数是context上下文,第二个参数是FileProvider,必须与 AndroidManifest.xml文件中Provider的 android:authorities一致,第三个参数是file文件对象。

    下面再放上一个例子

    Intent intent = new Intent();
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setAction(Intent.ACTION_VIEW);
    String type = MimeTypesTools.getMimeType(context, path);
    File file = new File(path);
    Uri uri;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        uri = FileProvider.getUriForFile(mContext, 
        //添加这一句表示对目标应用临时授权该Uri所代表的文件
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);BuildConfig.APPLICATION_ID+".fileprovider", file);
    }else {
        uri = Uri.fromFile(file);
    }
    intent.setDataAndType(uri, type);
    context.startActivity(intent);
    

    划重点!!
    一定要给Intent加一个flag——Intent.FLAG_GRANT_READ_URI_PERMISSION,否则会报Permission Denial的错,当然7.0以下的机型是不需要的。

    相关文章

      网友评论

        本文标题:Android 7.0 + FileProvider 访问隐私文

        本文链接:https://www.haomeiwen.com/subject/uxallctx.html