使用Gradle构建约定插件时动态功能模块出现重复条目问题
问题背景
项目包含基础模块与动态功能模块,从Gradle脚本插件(apply from:)迁移到构建约定插件(includeBuild 'build-conventions')后,执行./gradlew bundleDebug时触发以下错误:
- What went wrong:
Execution failed for task ':app:packageDebugBundle'.A failure occurred while executing com.android.build.gradle.internal.tasks.PackageBundleTask$BundleToolWorkAction
Modules 'base' and '‹dynamicfeature1›' contain entry 'root/google/protobuf/struct.proto' with different content.
排查确认:
- 基础模块依赖
com.google.protobuf:protobuf-javalite:3.17.3,动态模块因引入firebase-firestore,依赖版本被提升至3.19.2;迁移前版本差异已存在,但动态模块的AAB未包含该proto文件,因此无冲突。 - 移除动态模块的
firebase-firestore依赖或手动给基础模块指定高版本依赖可临时解决问题,但不够高效。 - 问题触发点为将
com.android.tools.build:gradle版本配置从根build.gradle移至build-conventions/build.gradle。
原因分析
将AGP版本配置迁移到构建约定插件后,模块间的依赖解析与资源打包逻辑发生了变化:
- 迁移前,根
build.gradle中的全局AGP版本配置会统一模块的依赖解析规则,可能默认让基础模块的依赖版本覆盖动态模块,或AGP打包逻辑自动忽略动态模块中的重复proto文件。 - 迁移后,AGP的应用时机改为通过约定插件分发,导致动态模块中被版本提升的protobuf-javalite的proto文件被打包进AAB,与基础模块的旧版本文件产生冲突。
解决方案
1. 全局统一依赖版本(推荐)
通过Gradle依赖约束强制所有模块使用同一版本的protobuf-javalite,从根源消除版本差异:
在根项目的build.gradle或构建约定插件的依赖管理块中添加:
allprojects { dependencies { constraints { implementation("com.google.protobuf:protobuf-javalite:3.19.2") } } }
若约束不生效,可使用强制解析策略:
allprojects { configurations.all { resolutionStrategy.force "com.google.protobuf:protobuf-javalite:3.19.2" } }
2. 排除动态模块中的重复proto文件
若暂时无法统一版本,可配置动态模块的打包规则排除冲突文件:
在动态功能模块的build.gradle中添加:
android { packagingOptions { exclude 'root/google/protobuf/struct.proto' } }
注意:此方法仅解决当前冲突,后续出现其他proto文件冲突需重复配置,属于临时方案。
3. 规范构建约定插件的AGP配置
确保所有模块使用相同版本的AGP:
在build-conventions/build.gradle中统一声明AGP插件版本并设为apply false:
plugins { id 'com.android.application' version 'your-agp-version' apply false id 'com.android.library' version 'your-agp-version' apply false id 'com.android.dynamic-feature' version 'your-agp-version' apply false }
然后在各模块的build.gradle中通过插件DSL引入对应AGP插件,避免因AGP版本不一致导致的解析逻辑差异。
内容的提问来源于stack exchange,提问作者fikr4n

