美文网首页
总结:Android问题集锦之安全组件类

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

作者: 玉圣 | 来源:发表于2018-10-25 10:57 被阅读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/"/>
    

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/hrfcyftx.html