Skip to content

FileProvider冲突 #80

Open
Open
@alwaystest

Description

@alwaystest

FileProvider冲突

标签(空格分隔): Android


Android N以上为了提高文件共享的安全性,引入了FileProvider,基于ContentProvider来实现。

在集成某个SDK的时候,发现里面针对FileProvider的写法是这样的:

<application>
    ...
    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths"/>
    </provider>
    ...
</application>

问题就在于provider的name是直接使用了Support V4包下的对应的实现类。
当另一个Lib也有同样的实现方式的时候,在MergeAndroidManifest的过程中就会提示冲突。

一种解决办法是使用tools:replace之类的声明去做替换,除非Dev明确知道自己在做什么,否则很容易因为缺少对应的path声明而导致出错。
使用tools:replace声明的原理在这里有说 https://developer.android.com/studio/build/manifest-merge
原理就是告诉MergeTool遇到冲突的时候选择哪一个。

另一种办法,看到有的文章说新建一个FileProvider,继承自android.support.v4.content.FileProvider就好了,里面什么都不需要做就好。然后在Manifest里面把name指定给新建的FileProvider。看完之后其实挺懵的,为什么新建一个就能解决冲突,什么冲突都能解决吗?

其实解决的原理是这样的,两个provider的声明中,name都是android.support.v4.content.FileProvider,就相当于在一个AndroidManifest中声明了两次同一个Activity。因为FileProvider实际上是ContentProvider,也是四大组件之一嘛,同一个组件声明两次,两次声明中要是一模一样倒还好说,直接Merge就好了,不会出错,但是一旦两个声明中某个属性不同,那MergeTool就不知道怎么选了,那就报错,我处理不了,你行你上。
换个名字,实际上是声明了两个不同的组件,不存在Merge的问题。

但是对于ContendProvider,声明了两个authorities相同的provider,能行吗?不行。
可能有人遇到过安装两个App的时候,因为Provider的authorities相同而导致第二个应用不能安装的。原因就是一旦允许安装,那就没有办法根据uri找出来到底应该从哪个Provider中获取数据了。
fileProvider生成的uri的格式是这样的

content://{authorities}/xxxxx

如果两个FileProvider的authorities声明成一样的,就没有办法区分应该找哪个FileProvider去获取文件了。

两个App的时候是这样。一个App中声明了两个一样的authorities的provider呢?

在Pixel 2XL,Android Studio 3.2上测试。应用可以正常编译,安装,但是到了使用的过程中,就会出现问题。

当两个FileProvider声明的resource不同的时候,系统通过URI找到的FileProvider如果刚好是声明了对应resource的Provider还好,一旦到的是另一个,在生成URI的过程中就会发现FileProvider的resource声明中就没有这个路径(声明在另一个正确匹配的FileProvider中声明啦),这是一个非法分享,Crash。

系统怎么找对应的FileProvider呢?我大胆的猜,按照AndroidManifest里声明的顺序,从上往下,哪个authorities先匹配,就用哪个。

所以即使在同一个应用中,也要保证authorities不能冲突呀。

看起来是个小问题。知识系统不连贯的情况下,很难想清楚。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @alwaystest

        Issue actions

          FileProvider冲突 · Issue #80 · alwaystest/Blog