Android Studio项目运行正常但由于"多个dex文件而构建APK失败..."

时间:2017-12-14 12:06:36

标签: android android-library android-studio-3.0 dex

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

app
 |
 - lib-foo
 - lib-bar

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

现在,有趣的是:

  • lib-foo模块直接包含Java源文件com.foo.Foobar.java
  • lib-bar模块包含一个内联的.aar文件,来源为implementation files('libs/some-3rd-party-lib.aar'),而此库包含com.foo.Foobar.java

运行和调试这个项目工作正常,一个APK生成并在手机上正常运行。但是,当我尝试做"构建APK"它失败了

Multiple dex files define Lcom/foo/Foobar;

是的,该文件确实存在于两个地方,但我并不完全确定该怎么想。我可以想象" run"之间的一个区别。和#34;构建APK"会是使用proguard等,但这就是" Build APK"只是直接从AS运行应用程序失败,或者有什么区别?

是否允许在两个不同的库模块中的两个位置具有相同的源文件,其中文件仅在模块内部使用?我知道最后,整个类集合被合并到最终APK中的一个classes.jar,但是肯定必须对完全相同的类的重复项有某种容忍,否则每个人都会有冲突像apache-commons等在很多库中大量使用的东西?

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

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

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

1 个答案:

答案 0 :(得分:2)

DEX文件中有基于其完全限定的Java类名称的类。因此,当谈到Java类时,引用old movie and TV show,“对于任何给定的完全限定的Java类名称,只能有一个”。

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

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

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