关于FileProvider文件共享机制及配置共享方法
尊重作者原创作品,转载请注明出处http://blog.csdn.net/qq_36273967/article/details/72632633
开场白:首先,感谢大家能够来到我的博客观看我的博文,这篇博文也是我写的第一篇博文!好的,先介绍下我自己吧!我学习android开发已经快一年了,说不上是什么大神级别,只能够算一个刚脱掉菜鸟名号的学生,之所以开始写博客,是因为自己在学习android开发这一年里摸爬滚打走了不少的弯路!想把自己在学习及实践中遇到的坑帮助后者填补,让大家避免少走弯路,最后祝大家工作愉快,学业有成。好了废话不多说开始步入正题. 今天我们的主角是FileProvider.首先我为什么介绍FileProvider呢?因为前段时间我在开发项目的时候需要用到一个文件的Uri真实地址,得到Uri后我在真机上测试没有问题,后来我又将项目拉到模拟器上跑,可是程序直接抛出了FileUriExposedException异常,仔细琢磨以后终于知道异常抛出的真相!原来在android7.0以及后续版本如果直接使用Uri.fromFile获得的Uri,系统认为是不安全的,会抛出FileUriExposedException异常,所以我们的主角出常了。 先介绍一下Filprovider,FileProvider是一种特殊的内容提供器,如果还有同学不知道内容提供器的可以去学习ContentProvider这里就不做讲解了。FileProvider有着和ContentProvider相同的机制对数据进行保护,它可以选择性的将封装好了的uri共享给外部从而提升数据的安全。 了解FileProvider以后那么我们怎么才能够获取到我们想要的uri呢?其实很简单,就直接调用这个类的一个静态方法FileProvider.getUriForFile(Context context,String authority,File file);第一个参数是我们的上下文,第二个参数是一个自定义的String字符串,第三个参数就是我们想获取Uri的文件当然我们在实际开发当中规范的写法就是:
if(Build.VERSION.SDK_INT>=24){
Uri uri = FileProvider.getUriForFile(MainActivity.this,"com.example.administrator.lifehelp.fileProvider",file);
}else{
Uri uri = Uri.fromFile(file);
}
首先我们要进行判断当前sdk的级别,android7.0对应的就是24,因为这个机制在7.0才出现的,所以我们在7.0版本中使用的getUriForFile方法获取到uri而低于7.0版本的就直接使用Uri.fromFile进行获取
在AndroidManifest文件中我们注册了FileProvider,其中android:name指定了注册ContentProvider的包名这里填入我们所使用的FileProvider的包名就可以了,android:authorities用来标识provider的唯一标识,这里填写的值填入我们在调用getUriForFile的第二个参数,第三个参数是否向外导入,就是其他的应用能否使用,竟然我们的FileProvider是为安全机制所生,当然我们不可能让它能够向外导入让其它应用来调用它,这里必须设置false否则就会抛出
Caused by: java.lang.SecurityException: Provider must not be exported
at android.support.v4.content.FileProvider.attachInfo(FileProvider.java:369)
at android.app.ActivityThread.installProvider(ActivityThread.java:5633)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:5205)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5135)
at android.app.ActivityThread.-wrap1(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1646)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5939)
at java.lang.reflect.Method.invoke(Native Method)
第四个参数grantUriPermission授予临时权限,用来控制共享文件的访问权限,竟然不能向外导入,我们就要使用临时权限。meta-data用于配置匹配共享文件的路径,为什么需要设置共享文件的路径呢?因为通过fileProvider给我们返回的uri是进行封装过的,所以我们必须配置它的共享路径才能够解析出来,第一个参数android.support.FILE_PROVIDER_PATHS是固定的,第二个参数是我们引入的xml资源文件,先创建这个资源文件右击res文件->New->Directory命名为xml,之后在这个xml文件夹里面创建一个xml文件,其名自定义:
在xml文件中,我们定义了根节点为paths,这里我们需要注意的是子节点这里在强调几点,我们为什么要设置这个xml。规则就是因为我上面说过了,fileProvider会把文件的真实路径隐藏,会把它转换成content://uri,因此我们需要设定它的转换规则,还有一点就是我们的必须将转换规则的xml文件放在xml文件夹否则会抛出
java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/com.test/cache/testDemo.txt
好了关于fileProvider的使用就介绍到此处,如果还有疑问的同学欢迎在下面评论,我会及时解答,学习是一种循循渐进的规则,有疑问的地方多读几遍就了解了,最后祝大家学习和工作愉快!