弄清楚INSTALL FAILED CONFLICTING PROVIDER问题
现象
安装应用的时候会提示安装失败,提示信息是INSTALL FAILED CONFLICTING PROVIDER,如下图所示:

究其原因
根据英文我们可以直观的知道因为provider的问题,在Android中provider的authority
要求必须是唯一的,比如你在定义一个provider
时需要为它指定一个唯一的authority
。如果你在安装一个带有provider
的应用时,系统会检查当前已安装应用的authority
是否和你要安装应用的authority
相同,如果相同则会弹出上述警告,并且安装失败。
这种问题多出现在接入第三方SDK、多个项目共用一个Module或Library,并且用到了provider。
解决方案
1. 简单粗暴
修改provider的
authority
,确保authority的命名唯一。这样以硬编码的形式进行修改,会很麻烦,每次新建项目添加已有的Module或Library都要修改他们包含的provider的authority。不建议这样使用硬编码的形式进行解决这个问题。这里就不过多陈述了。2.以柔克刚
在定义provider的时候,authority使用软编码。这样即使多个项目引用同一个Module或Library,其定义的provider的名字都不用进行修改了。
举例:
1 2 3 4 5 6 7 8 9 | <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/> </provider> |
上述代码中通过${applicationId}.fileprovider的形式来指定provider的authorities,所以该provider的authorities会根据applicationId的不同而不同,从而避免了authorities的冲突问题。
接着大家心中会有疑问?那authorities的URI不能在代码里声明常量了,那怎么获取呢?只要肯想,还是有办法的。
直接上代码:
Java
1 2 3 4 5 6 7 8 9 10 11 | public class ProviderUtils { public static String getAuthority(Context context, String providerClassName) { try { ComponentName componentName = new ComponentName(context.getApplicationContext(), providerClassName); ProviderInfo providerInfo = context.getPackageManager().getProviderInfo(componentName, 0); return providerInfo.authority; } catch (PackageManager.NameNotFoundException e) { return providerClassName; } } } |
Kotlin
1 2 3 4 5 6 7 8 9 10 11 12 | @JvmStatic fun getAuthority(context: Context?, providerClassName: String): String { return context?.let { try { val componentName = ComponentName(context.applicationContext, providerClassName) val providerInfo = context.packageManager.getProviderInfo(componentName, 0) providerInfo.authority } catch (e: Exception) { providerClassName } } ?: "" } |
使用的时候代码展示如下:
1 | FileProvider.getUriForFile(pContext, ProviderUtil.getAuthority(pContext, FileProvider::class.java.name), pFile) |
OK,这样就一劳永逸了,再创建新的项目直接使用共用的Module或Library,就不用担心Provider冲突的问题了。
我在这里强烈建议大家使用以柔克刚的方案。
推荐阅读: