Android 7.0配置fileprovider共享文件 解决FileUriExposedException

一.前言

从 Android N(7.0) 开始,将严格执行 StrictMode 模式,也就是说,将对安全做更严格的校验。而从 Android N 开始,将不允许在 App 间,使用 file:// 的方式,传递一个 File ,否者会抛出 FileUriExposedException 的错误,会直接引发 Crash。

但是,既然官方对文件的分享做了一个这么强硬的修改(直接抛出异常),实际上也提供了解决方案,那就是 FileProvider,通过 content:// 的模式替换掉 file:// ,同时,需要开发者主动升级 targetSdkVersion 到 24 才会执行此策略,也留给了开发者升级的时间。


二、如何使用 FileProvider

FileProvider 是 Android support v4 包下,提供的一个 ContentProvider 的子类,用于向其他 App 分享文件,并且是在 v4 包下,所以只要引入了 v4 包,就可以做到全版本兼容。

既然 FileProvider 本质上就是一个 ContentProvider ,它其实也继承了 ContentProvider 的特性。ContentProvider 其实就是在可控的范围内,向外部其他的 App 分享数据。而 FileProvider 将这样的数据变成了一个 File 文件而已。

在 App 间对 file:// 的分享做了严格的校验之后,其实也是出于安全考虑,这就导致了,所有包含 file:// 的URI 的 Intent 离开你的 App ,都受此限制。所以说,只要你的 App 内,通过一个 Intent 传递了一个 file:// 的 Uri ,就需要小心使用了。

最常用的使用场景

  调用系统相机

  调用系统相片裁剪

  调用系统去安装apk

具体使用

   1.在 AndroidManifest 中配置


              android:name="android.support.v4.content.FileProvider"
            android:authorities="com.bwt.textile.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
                            android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
   


 provider 标签下,配置了几个属性:

  •    name :配置当前 FileProvider 的实现类。
  •    authorities:配置一个 FileProvider 的名字,它在当前系统内需要是唯一值。
  •    exported:表示该 FileProvider 是否需要公开出去,这里不需要,所以是 false。
  •    granUriPermissions:是否允许授权文件的临时访问权限。这里需要,所以是 true。

   可以看到 name 属性就是标记当前 FileProvider 的实现类,对于一个 App Module 而言,如果只是自己使用,可以      直接使用 v4 包下的 FileProvider,但是如果是作为一个 Lib Module 来供其他项目使用,最好还是重新空继承一个      FileProvider ,这里填写我们的继承类即可。


 2. 指定可分享的文件路径

   在配置 Provider 的时候,还需要额外配置一个 标签,它用于配置 FileProvider 支持分享出去的目          录。这个 标签的 name 值是固定的,resource 需要指向一个 根节点为 paths 的 xml 资源文件。


                        name="files_root" />
                        name="external_storage_root" />

  •    root-path:表示根目录,『/』。
  •    files-path:表示 content.getFileDir() 获取到的目录。
  •    cache-path:表示 content.getCacheDir() 获取到的目录
  •    external-path:表示Environment.getExternalStorageDirectory() 指向的目录。
  •    external-files-path:表示 ContextCompat.getExternalFilesDirs() 获取到的目录。
  •    external-cache-path:表示 ContextCompat.getExternalCacheDirs() 获取到的目录。
   点(.) 表示是空

 3.使用 content://

   配置工作已经全部完成,后面就需要将之前传递的 file:// 替换成 FileProvider 需要的 content:// ,这就需要用到            FileProvider.getUriForFile()  方法了,以下是它的完整签名。

// 安装apk
public static void installApk(Context context, String fileName) {
 Intent intent = new Intent(Intent.ACTION_VIEW);//判断版本 Android 7.0以上需要使用FileProvider if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//调用FileProvider.getUriForFile获得Uri
            Uri contentUri = FileProvider.getUriForFile(context, "com.bwt.textile.fileprovider", 
                    new File(fileName));
            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
        } else {
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setDataAndType(Uri.parse("file://" + fileName),
                    "application/vnd.android.package-archive");
        }
        context.startActivity(intent);
   }
 这样就OK了


 总结来说就是Android7.0以后需要用fileprovider来对文件获取临时授权(重启或APP关掉之后授权消失)
 使用分三步
   1.配置AndroidManifest
   2.配置路径
   3.使用FileProvider.getUriForFile() 方法获取新的uri(格式为 content:// )



你可能感兴趣的:(android,安卓,app)