总结:Android问题集锦之安全组件类

2018-10-25  本文已影响41人  玉圣

一、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/"/>
上一篇下一篇

猜你喜欢

热点阅读