## 兼容文件权限7.0
对于第一次遇到7.0文件权限问题已经有1年多两年的时间了,相信大家也都知道需要适配,才能让应用之间共享文件的使用。
### 用法
我总结封装了一下,现在兼容文件权限只需要两步:
* 第一步:在manifest文件中配置
首先申明文件的读写权限
```
```
然后再在application标签中增加provider标签
```
```
保持这个不变,核心有两个地方:**1、`android:authorities`属性**,一般都是自己应用的包名+fileprovider中间用"."连接;**2、`android:resource`属性**,本库中我为了方便把所有的都定义了出来(要求v21版本以上的除外),稍后解释。
* 第二步:在需要传递或使用文件共享的地方转换Uri:
```
PermissionHelper.getUri(/*context*/this, intent, file);
```
这第二步,需要设置`authorities`属性和`FLAG_GRANT_READ_URI_PERMISSION` flag,我提供了以下几种方式:
```
public static Uri getUri(@NonNull Context context, @NonNull File file) {
return getUri(context, file, context.getPackageName() + ".fileprovider");
}
public static Uri getUri(@NonNull Context context, @NonNull File file, @NonNull String authority) {
return getUri(context, null, file, authority);
}
public static Uri getUri(@NonNull Context context, @NonNull Intent intent, @NonNull File file) {
return getUri(context, intent, file, context.getPackageName() + ".fileprovider");
}
public static Uri getUri(@NonNull Context context, Intent intent, @NonNull File file, @NonNull String authority) {
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (intent != null) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
uri = FileProvider.getUriForFile(context, authority, file);
} else {
uri = Uri.fromFile(file);
}
return uri;
}
```
代码很简单,就是设置和不设置flag和默认和不默认属性的两两组合。前两个是不设置flag的,后两个默认和不默认`authorities`属性的。最后一个方法就是实现核心,也挺简单,在7.0以后才加这些配置,不然直接使用`Uri.fromFile(file)`返回即可。
使用例子:例如使用intent打开相机应用,并传递一个文件过去的时候,就可以这样使用:
```
private void openCamera(String dir) {
File file = new File(dir, System.currentTimeMillis() + ".jpg");
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, PermissionHelper.getUri(/*context*/this, intent, file));
startActivity(intent);
}
```
这里的dir目录需要在第一步中的xml中申明的目录中存在。
### 目录结构
这里的目录有如下几个:
* file_paths.xml 对应Context.getFilesDir()目录
* cache_paths.xml 对应Context.getCacheDir()目录
* external_paths.xml 对应Environment.getExternalStorageDirectory()目录
* external_files_paths.xml 对应Context.getExternalFilesDir(String)目录
* external_cache_paths.xml 对应Context.getExternalCacheDir()目录
我将这些目录路径打印出来就是如下的结果:
```
filePath = /data/user/0/${packageName}/files
cachePath = /data/user/0/${packageName}/cache
externalPath = /storage/emulated/0
externalFilePath = /storage/emulated/0/Android/data/${packageName}/files
externalCachePath = /storage/emulated/0/Android/data/${packageName}/cache
```
### 扩展
当然,具体业务中最好还是不要把这个目录的所有文件都共享,因为这可能不安全,我这样写只是一个默认的,能不出问题的方案而已。
想要深入了解如何共享这些目录文件的话,可以去看看这两篇文章
[Setting up file sharing](https://developer.android.google.cn/training/secure-file-sharing/setup-sharing)
[FileProvider](https://developer.android.google.cn/reference/android/support/v4/content/FileProvider)