Android 库项目 com.android.dex.DexException: 多个 dex 文件定义 Lcom/google/gson/JsonSerializer

Android Library project com.android.dex.DexException: Multiple dex files define Lcom/google/gson/JsonSerializer

我正在 Android Studio 中编写一个库项目。我的 gradle 文件包括 gson 排球播放服务等...
将我的库嵌入项目时,我得到:

com.android.dex.DexException: Multiple dex files define Lcom/google/gson/JsonSerializer;

有人可以解释 gradle 创建库项目时的工作原理吗?
我应该如何解释集成我的 SDK 的开发人员,exclude 模块如何工作,以及为什么它在包含我的 aar 的应用程序中不起作用?

Gradle 无法神奇地解决这个问题 - 在您的 SDK 和用户的应用程序中可能存在同一个库的不同版本 - 它们无法合并或以某种方式区分。

我还开发了 SDK,它使用了几个流行的第三方库。我只是声明我使用了它们,如果用户也需要它们,则不必在他自己的应用程序中为这些依赖项提供 jar。我认为只要您在 SDK 中提供这些库的最新版本就可以了。

  1. 我能想到的避免冲突的唯一好方法是更改​​导入库中的 class 名称 - 但这真的很乏味和累人。您也可以使用 gradle shadow plugin 之类的东西来重新定位包,但这对我来说似乎有风险。它看起来像这样:

shadowJar { relocate 'com.google.gson', 'shadow.com.google.gson' }

  1. 您的开发人员也可以解压您的库,删除 gson 并将其重新打包回来。但是如果他使用另一个版本的 gson,你的库可能会崩溃。

  2. 哦,是的,您还可以将您的 SDK 作为源代码而不是 JAR 分发——这样用户就可以将它添加到他们的应用程序中并使用他们想要的任何库。但通常你不想把你的 SDK 代码放在 public 中(即使通过库 jar 也很容易逆向...)。

dx 的 --multi-dex 选项与 pre-dexing 库项目不兼容。因此,如果您的应用程序使用库项目,则需要先禁用预索引,然后才能使用 --multi-dex.

更新您的 IDE

有两种情况需要考虑

  • 首先,如果你在app/build.gradle

    中声明了Gson,请考虑删除它

    依赖项{ 编译 'com.google.code.gson:gson:2.4' }

  • 其次,如果你还没有在你的 app/build.gradle 您可能需要调查哪些库重复声明 Gson 依赖。然后您可以从该库中排除 Gson。 您可能需要查看此 Excluding transitive dependencies

在这里,我将提供一个从库中排除appcompat-v7的例子

运行这个命令查看依赖图表树

./gradlew app:dependencies

它将像下面的示例一样显示依赖关系树

|    \--- com.mikepenz:materialdrawer:4.6.3
|         +--- com.android.support:appcompat-v7:23.1.1 (*)
|         +--- com.android.support:recyclerview-v7:23.1.1 (*)
|         +--- com.mikepenz:materialize:0.5.1
|         |    \--- com.android.support:appcompat-v7:23.1.1 (*)
|         +--- com.mikepenz:iconics-core:2.5.3
|         |    \--- com.android.support:appcompat-v7:23.1.1 (*)
|         \--- com.android.support:support-annotations:23.1.1

在您发现库声明重复依赖项之后。你可以开始排除它了。

dependencies {
    compile("com.mikepenz:materialdrawer:4.6.3") {
        exclude module: 'appcompat-v7'
    }
}

如果删除 GSON 不适合您,请尝试在您的 build.gradle 文件中启用 multidex 支持:

android {
   ...
   ...
         defaultConfig {
             ...
             ...
             // Enabling multidex support.
             multiDexEnabled true
         }
}