Android Gradle依赖冲突解决方案 - 以集成友盟推送(U-Push SDK)与阿里云移动用户反馈(Mobile Feedback SDK)为例

目录

一、冲突类型1:你依赖它,我也依赖它

1.1、错误提示信息与分析

1.2、解决方案

二、冲突类型2:你中有我,我中有你

2.1、错误提示信息与分析

2.2、解决方案

三、总结


    当您向应用项目添加多个依赖项时,这些「直接依赖」和「间接/传递依赖项」之间可能会相互冲突,在出现类似情况时,build项目的时候就会报错。那么我们怎么解决这类冲突呢?一般情况下,我们可以把这类冲突做个分类,然后分情况来解决。

一、冲突类型1:你依赖它,我也依赖它

项目依赖了A库,同时还依赖B库,A和B各自同时依赖了C库。

    项目通过 implement 引入的依赖项之间看似没有直接关系,但是他们的各自的间接依赖的 JAR 包发送了重叠,在编译项目的过程中就会报错。笔者的Android端APP集成了友盟推送(U-Push SDK),同时还集成了阿里云移动用户反馈(Mobile Feedback SDK):

implementation 'com.umeng.umsdk:push:6.5.5'

implementation 'com.aliyun.ams:alicloud-android-feedback:3.3.7'

1.1、错误提示信息与分析

    项目build(环境:Android Studio版本:Dolphin | 2021.3.1 Patch 1,macOS)过程中的报错内容,本来是一大片的红色错误项,这里只贴出了一部分错误,其实任何类文件冲突都会罗列在Android studio的bulid的event log里,但是我们看其中任何一个错误项都可以找到发生冲突的相关依赖,可能比较老的Adroid Studio版本没有这些提示信息:

Duplicate class com.alibaba.sdk.android.beacon.Beacon found in modules alicloud-android-beacon-1.0.7.jar (com.aliyun.ams:alicloud-android-beacon:1.0.7) and alicloud_beacon-1.0.5.jar (com.umeng.umsdk:alicloud_beacon:1.0.5)

....... 

Duplicate class com.ta.utdid2.device.UTDevice found in modules alicloud-android-utdid-2.5.2.jar (com.aliyun.ams:alicloud-android-utdid:2.5.2) and utdid-1.5.2.3.jar (com.umeng.umsdk:utdid:1.5.2.3)

........

上面的日志提示:

com.aliyun.ams:alicloud-android-beacon:1.0.7com.umeng.umsdk:alicloud_beacon:1.0.5冲突,都包括类文件:com.alibaba.sdk.android.beacon.Beacon

com.aliyun.ams:alicloud-android-utdid:2.5.2com.umeng.umsdk:utdid:1.5.2.3冲突,都包括了类文件:com.ta.utdid2.device.UTDevice

    那么项目app moudle 的build.gradle文件里并没有implement上面这些冲突jar包,所以可以判断是间接依赖导致了冲突,所以接下来需要找出它们的依赖关系。这里有两个方式:

方式1:Gradle task工具查看

    按照如图目录找到dependencise双击,会在Run控制台输出打印,见下图-1。

图 - 1

方式2:Terminal控制台输入命令查看

 在windows/Android studio Terminal中使用这个命令:

gradlew :app:dependencies

在MacOS/Android studio Terminal中使用这个命令:

./gradlew :app:dependencies

    通过上面两个方式,我们可以看到整个项目引用依赖的关系图谱,然后再通过「ctrl +find」命令查找上面发生冲突的依赖。类似下图,我们可以找到发生冲突的alicloud-android-beacon:1.0.7alicloud_beacon:1.0.5 ,可以看到他们分别是项目build.gradle文件里: implement com.aliyun.ams:alicloud-android-feedback:3.3.7implement com.umeng.umsdk:push:6.5.5 引入的间接依赖。见下图 - 2和图 - 3:

图 - 2

图 - 3

    然后在展开项目的External Libraries里面这两个JAR包,看下它们都包括的类文件,可以看到这两个JAR都包含了类文件:a.class, b.class, Beacon.class, 所有重复的类文件都会导致build过程中报错,见下图-4和图-5:

图 - 4

图 - 5

依赖冲突:

    上面的分析了com.aliyun.ams:alicloud-android-beacon:1.0.7com.umeng.umsdk:alicloud_beacon:1.0.5依赖关系和JAR包,现在把其它两个发生冲突的com.aliyun.ams:alicloud-android-utdid:2.5.2com.umeng.umsdk:utdid:1.5.2.3依赖关系和JAR包全部合并放到一张大图里面来展示,它们之间的冲突关系就更清晰了,见图-6和图-7:

依赖关系 图 - 6

JAR包类重复 图 - 7

1.2、解决方案

    通过上面的分析,可以清楚地知道下面的依赖关系:

com.umeng.umsdk:push:6.5.5 引入间接依赖:

 com.umeng.umsdk:alicloud_beacon:1.0.5 与 com.umeng.umsdk:utdid:1.5.2.3

com.aliyun.ams:alicloud-android-feedback:3.3.7 引入间接依赖:

com.aliyun.ams:alicloud-android-beacon:1.0.7 与 com.aliyun.ams:alicloud-android-utdid:2.5.2

    那么解决方式就是将发生冲突的依赖留下其中之一就可以了,这里我用 gradle 的 exclued 方式排除版本较低的JAR依赖包,选择留下版本更高的JAR依赖包。com.umeng.umsdk:push:6.5.5 引入的两个依赖库JAR版本更低,所以可以采用如下方式来排除:

    implementation ('com.umeng.umsdk:push:6.5.5') {
        exclude group:'com.umeng.umsdk', module:'alicloud_beacon'
        exclude group:'com.umeng.umsdk', module:'utdid'
    }

    以 com.umeng.umsdk:alicloud_beacon:1.0.5 为例,com.umeng.umsdk 代表 group,alicloud_beacon 代表 moudle,注意:module: '内容',内容部分不要带上版本号,笔者因为带上了版本号(错误写法: moudle: 'alicloud_beacon:1.0.5')导致exclude无效,白白浪费了不少时间来查找原因。

二、冲突类型2:你中有我,我中有你

项目依赖了A库,同时还依赖B库,A与B的JAR包里包括了相同的类文件。

2.1、错误提示信息与分析

    笔者在更早的时候,集成的是友盟的U-Push 6.01 和 阿里云的Feedback3.3.1,在build项目过程中也因为依赖冲突报错,点击Android Studio (环境:AS 3.01版本,macOS) -  RUN 报异常信息:

java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex

    然后网上查错误原因,gradle 添加了:multiDexEnabled true 仍然无解,于是怀疑是依赖冲突导致的,通过 命令 gradlew :app:dependencies (windows)或 ./gradlew :app:dependencies(macOS) 查依赖关系也没有发现有重复依赖(冲突类型1),因为 Android studio 的版本比较低,也没有直接在gradle eveng log里提示哪些依赖有冲突,我们可以用下面的命令来输出gradle过程中详细的日志来查找问题:

gradle :app:your-task-name --stacktrace | --debug

例如:

gradle :app:assembleKaolaDebug --stacktrace | --debug

    然后就可以发现更加精确的错误提示:

Caused by: com.android.dex.DexException: Multiple dex files define Lcom/alibaba/sdk/android/utils/b;

    根据这里的提示可以知道是类文件发送冲突了,虽然没有明确告诉那些依赖的库有冲突,但是也可以按图索骥的查到根源了,展开项目下的External Libraries目录,发现umeng push 6.0.1包括package【com.alibaba.sdk.android.utils】,而恰好alicloud-android-feedback引入的间接依赖包【'com.aliyun.ams:alicloud-android-utils:1.1.5'】也包括了【com.alibaba.sdk.android.utils】,类重复导致了上述错误。

2.2、解决方案

    这个冲突类型的特点是:你中有我,我中有你。相当于两个JAR包里面的只有部分类文件有重复,这种情况,就不能简单用exclude方式来解决了。这里的解决方案是将push-6.0.1.jar里与其他JAR包冲突的类文件剔除掉,重新打包成aar的格式,拷贝到libs目录下再重新导入项目。

步骤1:找到external libraries/push-6.0.1.jar的存储位置,以笔者的macOs为例:

/Users/[your-user-name]/.gradle/caches/transforms-2/files-2.1/05c726c1eeb84fe6c912e712075a18bd/push-6.5.5

    将push-6.0.1.aar 转成.zip,解压为push-6.0.1, 将里面的classes.jar解压,删除所有重复导致冲突的类文件,重新打包为classes.jar。

步骤2:将push-6.0.1文件夹重新打包为aar, 命令【 jar cvf push-6.0.1.aar -C push-6.0.1/ .】

步骤3:导入项目:implementation(name: 'push-6.0.1', ext: 'aar')

 参考:

1、android 友盟和阿里sdk冲突:https://www.cnblogs.com/fatherloveyou/p/9145401.html。

2、把文件或者文件夹打包成jar https://blog.csdn.net/zz_ddup/article/details/80118466

3、记android依赖排除:https://www.jianshu.com/p/8c6c688b7f0c

三、总结

我们开发过程中,项目越来越庞大,业务变的更加复杂,引入的库也很多,总会碰到冲突的情况,我们要善于利用工具和一些常用的gradle命令来帮助我们快速分析和解决问题。

猜你喜欢

转载自blog.csdn.net/crazestone0614/article/details/127952950