总结:Android问题集锦之安全组件类
一、Provider
1、提示java.lang.IllegalArgumentException:
在使用一个第三方类库的时候,其中有打开相机拍照的功能,在其源码提供的demo测试中,使用相机拍照完全没有问题,但当我集成到自己的项目中,进行拍照的时候,就崩溃了,提示java.lang.IllegalArgumentException
的错误,详情错误为:Failed to find configured root that contains /storage/emulated/0/DCIM/camera/IMG_20181024_182102.jpg
我反复测试断点跟进,在下面的源码中发现了两个项目不一样的地方:
源码:[FileProvider.java #691]
@Override
public Uri getUriForFile(File file) {
String path;
try {
path = file.getCanonicalPath();
} catch (IOException e) {
throw new IllegalArgumentException("Failed to resolve canonical path for " + file);
}
// Find the most-specific root path
Map.Entry<String, File> mostSpecific = null;
for (Map.Entry<String, File> root : mRoots.entrySet()) {
final String rootPath = root.getValue().getPath();
if (path.startsWith(rootPath) && (mostSpecific == null
|| rootPath.length() > mostSpecific.getValue().getPath().length())) {
mostSpecific = root;
}
}
if (mostSpecific == null) {
throw new IllegalArgumentException(
"Failed to find configured root that contains " + path);
}
// Start at first char of path under root
final String rootPath = mostSpecific.getValue().getPath();
if (rootPath.endsWith("/")) {
path = path.substring(rootPath.length());
} else {
path = path.substring(rootPath.length() + 1);
}
// Encode the tag and path separately
path = Uri.encode(mostSpecific.getKey()) + '/' + Uri.encode(path, "/");
return new Uri.Builder().scheme("content")
.authority(mAuthority).encodedPath(path).build();
}
其中传入的file
参数值在两个项目中皆为
'/storage/emulated/0/DCIM/camera/IMG_20181024_182102.jpg'
而其中的mRoots集合在两个项目中包含值却不相同:
第三方demo项目中的值为:
'/storage/emulated/0'
我自己集成后的项目中的值为:
'/storage/emulated/0/Download'
'/storage/emulated/0/Android/data'
原因:
查阅了很多资料,都是关于java.lang.IllegalArgumentException
的相关解决办法,后来我再仔细查看了项目中配置的路径来源,及res/xml中的文件配置,发现了引入的第三方库的res/xml
和自己的项目中的res/xml
,两个目录下的文件名称竟然是相同的,都命名为 provider_paths.xml
其中第三方库的内容为:
<external-path name="external_files" path="."/>
而我的项目中的内容为:
<external-path name="beta_external_path" path="Download/"/>
<external-path name="beta_external_files_path" path="Android/data/"/>
结论:
由此发现mRoots中的值是我的项目中配置的provider_paths.xml中的两个节点内容。因此才使得在拍照的时候,无法获取到照片配置的路径和名称,才导致java.lang.IllegalArgumentException
的错误,无法找到匹配的文件路径。
当存在多个文件名相同的xml文件provider配置的时候,会查找首先匹配到的文件中的配置节点内容,导致第二个项目配置文件内容被忽略的现象。
解决:
方案一:
统一配置一个provider的xml文件,命名为provider_paths.xml
,将所有的路径名称配置在一起,如:
<external-path name="beta_external_path" path="Download/"/>
<external-path name="beta_external_files_path" path="Android/data/"/>
<external-path name="external_files" path="."/>
//........
方案一:
分别在不同的项目中配置不同的provider的xml文件,文件命名一定不能相同,命名如下:
项目一:
picture_provider_paths.xml
<external-path name="external_files" path="."/>
项目一:
bugly_provider_paths.xml
<external-path name="beta_external_path" path="Download/"/>
<external-path name="beta_external_files_path" path="Android/data/"/>