当前位置:   article > 正文

Android FileProvider介绍_android:process=":fileprovider

android:process=":fileprovider

Android 7.0 文件共享要使用FileProvider

对于面向Android 7.0的应用,Android框架执行的StrictMode API政策禁止在您的应用外部公开file://URI。如果一项包含文件URI的intent离开您的应用,则应用出现故障,并出现FileUriExposedException异常。

对于文件访问在Android 7.0以前可以使用file://uri的方式访问,但是这个地方有个问题,就是即使不是你自身应用产生的文件,只要知道对方的uri则就可以调用到,这样在安全性上就产生了风险。所以Android 7.0后新增了对文件跨进程访问的限制,这个限制会造成,如果使用file://uri的方式访问,则会出现android.os.FileUriExposedException的异常。

FileProvider简介

FileProvider是ContentProvider的一个特殊的子类,它让应用间共享文件变得更加容易,其通过创建一个Content URI来代替File URI。

一个Content URI 允许开发者可赋予一个临时的读或写权限。当创建一个包含Content URI的Intent的时候,为了能够让另一个应用也可以使用这个URI,你需要调用Intent.setFlags()来添加权限。只要接收Activity的栈是活跃的,则客户端应用就可以获取到这些权限。如果该Intent是用来启动一个Service,则只要该Service是正在运行的,则也可以获取到这些权限。

相比之下,如果想要通过File URI来控制权限,开发者必须修改底层文件系统的权限。这些权限会对任意的app开放,直到你修改了它。这种级别的访问基本上是不安全的。

通过Content URI来提高文件访问的安全性,使得FileProvider成为Android安全基础设置的一个关键部分。

FileProvider 使用

1、 AndroidManifest ,注册FileProvider

  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android">
  2. <application
  3. ...>
  4. <provider
  5. android:name="android.support.v4.content.FileProvider"
  6. android:authorities="org.unreal.update"
  7. android:grantUriPermissions="true"
  8. android:exported="false">
  9. <meta-data
  10. android:name="android.support.FILE_PROVIDER_PATHS"
  11. android:resource="@xml/update_files" />
  12. </provider>
  13. ...
  14. </application>
  15. </manifest>

android:authorities 参数,如同ContentProvider,此处需要你提供一个uri的authorities,以便于content://android:authorities/uri访问到,android:authorities可以随意定义。

2、 res下创建xml文件夹,并在xml文件夹下创建update_files.xml

  1. <resources xmlns:android="http://schemas.android.com/apk/res/android">
  2. <paths>
  3. <files-path path="files" name="files" />
  4. <cache-path path="files" name="cache" />
  5. <external-path path="files" name="external" />
  6. <external-files-path path="files" name="externalfiles"/>
  7. <!-- 此标签需要 support 25.0.0以上才可以使用-->
  8. <external-cache-path path="files" name="externalcache"/>
  9. </paths>
  10. </resources>

name:名称标志字符串,不可以同名!即key

path:文件夹“相对路径”,完整路径取决于当前的标签类型。

标签路径
……..* 代表 当前文件夹及其子文件夹
file-path物理路径为Context.getFilesDir() + /files/*
cache-path物理路径为Context.getCacheDir() + /files/*
external-path物理路径为Environment.getExternalStorageDirectory() + /files/*
external-files-path物理路径为Context.getExternalFilesDir(String) + /files/*
external-cache-path物理路径为Context.getExternalCacheDir() + /files/*

<paths>里边的元素必须是一下的一个或者多个:

<files-path name="name" path="path" /> 对应Context.getFilesDir() + “/path/”,即/data/data/<package-name>/files/path/。
<cache-path name="name" path="path" /> 对应Context.getCacheDir() + “/path/”,即/data/data/<package-name>/cache/path/。
<external-files-path name="name" path="path" /> 对应Context.getExternalFilesDir(null) + “/path/”,即/storage/emulated/0/Android/data/<package_name>/files/path/。
<external-cache-path name="name" path="path" /> 对应Context.getExternalCacheDir() + “/path/”,即/storage/emulated/0/Android/data/<package-name>/cache/path/。
<external-path name="name" path="path" /> 对应Environment.getExternalStorageDirectory() + “/path/”,即/storage/emulated/0/path/。
这些paths里边有相同的子元素,即name和path。

3、通过getUriForFile获取到uri

  1. data = FileProvider.getUriForFile(context,"之前在AndroidManifest中配置的android:authorities", "7.0后文件的路径");
  2. // 给目标应用一个临时授权
  3. intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
  4. | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

FLAG_GRANT_READ_URI_PERMISSION:表示读取权限; 
FLAG_GRANT_WRITE_URI_PERMISSION:表示写入权限; 
根据你的需求,是读取呢,还是写入自行选择

完!!!

示例: 安装Apk,兼容Android 7.0以上及以下版本

  1. private void installApk(File apk) {
  2. if (!apk.exists()) {
  3. return;
  4. }
  5. Uri data;
  6. Intent intent = new Intent(Intent.ACTION_VIEW);
  7. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  8. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
  9. // UpdateConfig.FILE_PROVIDER_AUTH 即是在清单文件中配置的authorities
  10. data = FileProvider.getUriForFile(context, UpdateConfig.FILE_PROVIDER_AUTH, apk);
  11. // 给目标应用一个临时授权
  12. intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  13. } else {
  14. data = Uri.fromFile(apk);
  15. }
  16. intent.setDataAndType(data, "application/vnd.android.package-archive");
  17. context.startActivity(intent);
  18. android.os.Process.killProcess(android.os.Process.myPid());
  19. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/669312
推荐阅读
相关标签
  

闽ICP备14008679号