DexIndexOverflowException 仅在运行测试时

DexIndexOverflowException Only When Running Tests

提问人:John D. 提问时间:10/24/2015 最后编辑:IntelliJ AmiyaJohn D. 更新时间:8/21/2018 访问量:6864

问:

我可以毫无问题地在我的调试和发布变体中成功构建和运行我的 Android 应用程序。然而,当我尝试运行我的新单元测试(我以前从未有过)时,我得到了可怕的 DexIndexOverflowException。我怀疑不是用我的单元测试运行的,而是用我正常的调试和发布 buildType 运行的。ProGuard

我需要做什么才能在单元测试运行配置中运行?我搜索了 Gradle 文档、文档和 Android Studio 文档来解决这个问题,但一无所获。ProGuardProGuard

Android 单元测试 android-gradle-plugin proguard

评论

0赞 Hugo Gresse 10/27/2015
由于您不能使用 ProGuard 运行测试,因此您需要配置 MultiDex:developer.android.com/tools/building/multidex.html ProGuard 通过知道它来正常解决 multiDex:它只会删除未使用的方法。
0赞 Rajesh 10/30/2015
将 multiDexEnabled true 添加到您的 gradle 或注释此编译文件Tree(dir: 'libs', include: ['*.jar'])
1赞 sschuberth 10/30/2015
@HugoGresse 从 Android Gradle 插件版本 1.2.0 开始,您实际上可以拥有仅限测试的 ProGuard 文件

答:

21赞 IntelliJ Amiya 10/30/2015 #1
com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536 

Android 应用程序 (APK) 文件包含可执行字节码文件 Dalvik 可执行文件 (DEX) 文件的形式,其中包含编译的 用于运行应用的代码。Dalvik 可执行文件规范限制 单个 DEX 中可引用的方法总数 文件到 65,536,包括 Android 框架方法、库方法、 和方法。要超过此限制,需要 您可以配置应用程序构建过程以生成多个 DEX 文件,称为 MultiDex 配置。

Android SDK Build Tools 21.1 及更高版本中提供的适用于 Gradle 的 Android 插件支持将 Multidex 作为构建配置的一部分。在尝试为 multidex 配置应用之前,请务必使用 SDK 管理器将 Android SDK 构建工具工具和 Android 支持存储库更新到最新版本。

将应用程序开发项目设置为使用 Multidex 配置需要对应用程序开发项目进行一些修改。具体而言,您需要执行以下步骤:

  1. 更改 Gradle 构建配置以启用 multidex
  2. 修改清单以引用 MultiDexApplication 类

修改您的应用 Gradle 构建文件配置以包含支持库并启用 multidex 输出。

    android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 25
        ...

        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.3' 
}

在清单中,将 MultiDexApplication 类从 multidex 支持库添加到 application 元素。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.multidex.myapplication">
    <application
     android:name="android.support.multidex.MultiDexApplication">

    </application>
</manifest>

阅读有关 MultiDex 的官方文档

如果你的 Application 类正在扩展其他类,而你不想或不能更改它,请重写 attachBaseContext(),如下所示:

public class MyApplication extends MultiDexApplication { 
   @Override 
   protected void attachBaseContext(Context base) { 
      super.attachBaseContext(base); 
      MultiDex.install(this); 
   } 
}

然后

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.multidex.myapplication">
    <application
     android:name=".MyApplication">
    </application>
</manifest>

结论

虽然该库在大多数情况下修复了 DEX 64K 问题,但它应该 被视为不得已。在尝试使用它之前,您应该 审核项目中不需要的依赖项,并删除尽可能多的未使用项 尽可能使用 ProGuard 编写代码。

评论

1赞 John D. 11/3/2015
无赖。不想启用 MultiDex,但这确实有效。谢谢!
2赞 methodsignature 1/12/2018
我真的不认为这个答案回应了问题的根源。听起来用户已经完全意识到与非测试构建有关的多 dex 问题。为什么是测试版本而不是生产版本?如何为测试版本启用 proguard?我的猜测是,第二个问题听起来像是一个坏主意。
3赞 Kingfisher Phuoc 10/30/2015 #2

发生此错误可能是因为项目和库中的函数过多。 您可以: - 启用多个 dex 作为 Amiya @Intellij答案
- 检查库:
仅指定您的应用使用的特定 Google Play 服务 API,而不是所有 API。

compile 'com.google.android.gms:play-services-ads:7.5.0'

查找并排除重复的依赖项:打开终端并运行:

gradle -q dependencies

它将显示一个列表,如下例所示:

+--- com.android.support:appcompat-v7:23.0.1
|    \--- com.android.support:support-v4:23.0.1
|         \--- com.android.support:support-annotations:23.0.1
+--- :dputility_library-1.1.2:
+--- com.google.android.gms:play-services-ads:7.5.0
|    +--- com.google.android.gms:play-services-base:7.5.0
|    |    \--- com.android.support:support-v4:22.0.0 -> 23.0.1 (*)
|    \--- com.google.android.gms:play-services-analytics:7.5.0
|         \--- com.google.android.gms:play-services-base:7.5.0 (*)
+--- com.jakewharton:butterknife:7.0.1
+--- com.afollestad:material-dialogs:0.7.6.0
|    +--- com.android.support:support-v4:22.2.0 -> 23.0.1 (*)
|    +--- com.android.support:appcompat-v7:22.2.0 -> 23.0.1 (*)
|    +--- com.android.support:recyclerview-v7:22.2.0
|    |    +--- com.android.support:support-annotations:22.2.0 -> 23.0.1
|    |    \--- com.android.support:support-v4:22.2.0 -> 23.0.1 (*)
|    \--- com.android.support:support-annotations:22.2.0 -> 23.0.1

您可以使用 (*) 查看一些依赖项,您可以将其从 gradle 依赖项中排除:

compile('com.google.android.gms:play-services-ads:7.5.0')
{
    exclude module: 'support-v4'
    exclude module: 'play-services-base'
}

实际上,对我来说,排除方法有效(多个 dex 不起作用)。希望对你有所帮助。

评论

0赞 Nabeel K 4/23/2018
我怎么知道要排除的模块的确切名称?
-1赞 Tad 6/27/2016 #3

如果您只需要对测试提供 multidex 支持,则只能为测试启用它,并在 :build.gradle

dependencies {
    ...
    androidTestCompile 'com.android.support:multidex:1.0.1'
}
1赞 Maragues 4/13/2018 #4

升级到 gradle 插件 3.1.1 为我解决了这个问题,如本答案所示