好久没更新了嘿嘿 最近懒 项目要收尾 一直懒懒的测试 看RXJava什么的
手机系统更新7.0 无意中发现调用相机报错Failed to find configured root that contains 搜索手机储存中的文件也报错
在5.0和6.0的测试机上都没有这个问题 于是翻看7.0的API
得知 谷歌推荐的方法是:
用FileProvider来生成一个content://格式的URI
首先在manifest中声明一个provider。name(即类名)为android.support.v4.content.FileProvider。
其中android:name="android.support.v4.content.FileProvider" android:authorities="com.sy.myapp.fileprovider" android:exported="false" android:grantUriPermissions="true"> android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
authorities
可以自定义。为了避免和其它app冲突,最好带上自己app的包名(我随便起了个名字)
然后 在res/xml/下创建file_paths.xml。
xml version="1.0" encoding="utf-8"?>再使用文件URI的时候name="camera_photos" path="" />
File mTmpFile;
FileProvider.getUriForFile(getActivity(), "com.sy.myapp.fileprovider", mTmpFile);就可以了
我读取的是图片文件 本来file_paths.xml 应该是
xml version="1.0" encoding="utf-8"?>但是这个会报错 无法获取外置SD卡name="camera_photos" path="" />
所以直接使用root-path
从Android官方文档上可以看出FileProvider提供以下几种path类型:
<files-path path="" name="camera_photos" />
该方式提供在应用的内部存储区的文件/子目录的文件。它对应Context.getFilesDir返回的路径:eg:"/data/data/com.jph.simple/files"。
<cache-path name="name" path="path" />
该方式提供在应用的内部存储区的缓存子目录的文件。它对应getCacheDir返回的路径:eg:“/data/data/com.jph.simple/cache”;
<external-path name="name" path="path" />
该方式提供在外部存储区域根目录下的文件。它对应Environment.getExternalStorageDirectory返回的路径:eg:"/storage/emulated/0";
<external-files-path name="name" path="path" />
该方式提供在应用的外部存储区根目录的下的文件。它对应Context#getExternalFilesDir(String) Context.getExternalFilesDir(null)返回的路径。eg:"/storage/emulated/0/Android/data/com.jph.simple/files"。
<external-cache-path name="name" path="path" />
该方式提供在应用的外部缓存区根目录的文件。它对应Context.getExternalCacheDir()返回的路径。eg:"/storage/emulated/0/Android/data/com.jph.simple/cache"。
以上便是Android官方文档上介绍的FileProvider所有支持的所以path类型,这些类型在Android手机内部存储区文件共享是可以行的通的,但对于外置SD卡是不行的,如果你想通过FileProvider.getUriForFile()
获取一个外置SD卡的Uri则会报出如下异常:
从Android官方文档中没有找到FileProvider对外置SD卡的支持的任何说明,下面我们就从FileProvider的源码中找找是否有突破口,在FileProvider的源码源码中发现下面一段代码:
private static PathStrategy parsePathStrategy(Context context, String authority)
...
int type;
while ((type = in.next()) != END_DOCUMENT) {
if (type == START_TAG) {
final String tag = in.getName();
final String name = in.getAttributeValue(null, ATTR_NAME);
String path = in.getAttributeValue(null, ATTR_PATH);
File target = null;
if (TAG_ROOT_PATH.equals(tag)) {
target = buildPath(DEVICE_ROOT, path);
} else if (TAG_FILES_PATH.equals(tag)) {
target = buildPath(context.getFilesDir(), path);
} else if (TAG_CACHE_PATH.equals(tag)) {
target = buildPath(context.getCacheDir(), path);
} else if (TAG_EXTERNAL.equals(tag)) {
target = buildPath(Environment.getExternalStorageDirectory(), path);
}
if (target != null) {
strat.addRoot(name, target);
}
}
}
return strat;
}
从上述代码中可以看出FileProvider支持的path类型中有个TAG_ROOT_PATH
,它对应的值为root-path
,root-path
在Android官方文档中是没有提及的,但我们不妨试一下,将FileProvider的path设置成root-path
,看能否支持外置SD卡:
xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<root-path path="" name="camera_photos" />
paths>
resources>
然后我们能将在FileProvider类中设置断点,查看root-path
究竟代表什么:
从上图可以看出root-path
代表/
也就是Android设备的根目录,该目录下包含着手机内部存储器,外置SD卡等所有文件的目录。
然后我们允许程序,发现将path设置为root-path
解决了FileProvider无法使用外置SD卡的问题。
PS:root-path参数在以后的更新有可能会删除 使用时请注意