Android Studio 项目运行正常,但由于 "multiple dex files..." 而构建 APK 失败

Android Studio project runs fine but build APK fails due to "multiple dex files..."

使用 Android Studio 3.0,我有一个具有以下布局的 Android 应用程序项目:

app
 |
 - lib-foo
 - lib-bar

所以我有一个应用程序模块,分别使用两个名为 lib-foolib-bar 的库模块。

现在,有趣的部分来了:

运行 并且调试该项目工作正常,已生成 APK 并在 phone 上运行良好。但是,当我尝试执行 "Build APK" 时,它失败并显示

Multiple dex files define Lcom/foo/Foobar;

是的,该文件确实存在于两个地方,但我不完全确定对此有何看法。我可以想象 "run" 和 "Build APK" 之间的一个区别是使用混淆器等,但是 "Build APK" 失败的原因是 运行 应用程序直接来自AS 工程,或者有什么区别?

是否不允许在两个地方有相同的源文件,在两个不同的库模块中,文件只在模块内部使用?我知道最后,整个 classes 集合在最终的 APK 中合并为一个 classes.jar,但是对于完全相同 [=58= 的重复项肯定会有某种容忍度], 否则每个人都会对很多库中大量使用的 apache-commons 等东西产生冲突?

或者实际上在两个不同的模块内部允许重复的文件,但它是 .aar 文件的静态直接包含搞砸了事情?

我该如何解决这个问题?如果我控制了第 3 方库,我想我可以将公共文件提取为另一个包含最小公分母的库,并将其作为 gradle 依赖项从需要它们的两个模块中获取,但我没有控制第 3 方库。也许将第 3 方库放在 Maven 上并将其作为版本化依赖项而不是作为静态文件来获取它就可以了,如果这只是由这种内联 .aar 包含引起的一些错误(大量猜测)?

我想了解为什么会失败,为什么直接从 AS 运行 应用程序不会失败,以及如何解决它。我不想将 com.foo.Foobar.java 重命名为 com.foo.MyRenamedFooBar.java 以消除冲突。

根据完全限定的 Java class 名称,DEX 文件中有 classes。因此,当谈到 Java classes 时,为任何给定的完全限定 Java class 引用 old movie and TV show、"there can only be one"名字.

对于来自工件存储库的依赖项——你的 apache-commons 场景——Gradle 可以消除它并且只包含一次依赖项。但是,这适用于工件级别。因此,例如,如果您的应用程序依赖于 apache-commons and 在其源代码中有一个来自 apache-commons 的 Java class,则将有两个副本class(一个来自依赖项,一个来自源),Gradle 对此无能为力。

通常,如果您有超过 2 个 class 具有相同的完全限定 class 名称,您将遇到某种构建错误。 Android Studio 3.0 大大改进了对这种情况的检测,因为我们从 Stack Overflow 上报告的重复 class 中得到 很多 的新构建错误。

您显然遇到了 Android Studio 未检测到它的边缘情况,至少在所有情况下都是如此(例如,Instant 运行 未检测到它)。如果您可以创建可重现的测试用例,提交问题,工具团队可能会解决它。