仅在运行测试时出现 DexIndexOverflowException

Posted

技术标签:

【中文标题】仅在运行测试时出现 DexIndexOverflowException【英文标题】:DexIndexOverflowException Only When Running Tests 【发布时间】:2022-01-25 20:09:29 【问题描述】:

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

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

【问题讨论】:

因为你不能使用 ProGuard 来运行测试,你需要配置 MultiDex :developer.android.com/tools/building/multidex.html ProGuard 在不知不觉中解决了 multiDex:它只删除未使用的方法。 将 multiDexEnabled true 添加到您的 gradle 或注释此编译文件Tree(dir: 'libs', include: ['*.jar']) @HugoGresse 从 Android Gradle 插件版本 1.2.0 开始,您实际上可以拥有Test-only ProGuard files。 【参考方案1】:
com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536 

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

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

将您的应用开发项目设置为使用 multidex 配置需要您对应用开发项目进行一些修改。特别是您需要执行以下步骤:

    更改 Gradle 构建配置以启用 multidex 修改清单以引用 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' 

在您的清单中,将 multidex 支持库中的 MultiDexApplication 类添加到应用程序元素。

<?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 类正在扩展某个其他类并且您不想或无法更改它,override 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 编写代码。

【讨论】:

无赖。不想启用 MultiDex,但这确实有效。谢谢! 我真的不认为这个答案能解决问题的根源。听起来用户已经完全意识到关于非测试构建的多 dex 问题。为什么是测试构建而不是生产构建?您如何为测试构建启用 proguard?我的猜测是,第二个问题一开始听起来是个坏主意。【参考方案2】:

错误的发生可能是因为您的项目和库中的函数过多。 你可以: - 启用 multiple dex 作为 @Intellij Amiya 的答案 - 检查库: 仅指定您的应用使用的特定 Google Play 服务 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 无效)。希望对您有所帮助。

【讨论】:

我如何知道要排除的模块的确切名称?【参考方案3】:

按照in this answer的建议,升级到 gradle 插件 3.1.1 为我解决了这个问题

【讨论】:

【参考方案4】:

如果您只需要对测试的 multidex 支持,您可以只为在 build.gradle 中使用如下行的测试启用它:

dependencies 
    ...
    androidTestCompile 'com.android.support:multidex:1.0.1'

【讨论】:

以上是关于仅在运行测试时出现 DexIndexOverflowException的主要内容,如果未能解决你的问题,请参考以下文章

仅在调试代码时出现进程中的 hsqldb 错误

运行 Gradle JUnit 测试时出现“地址已在使用:绑定”异常

仅在从 Windows 运行时出现 500 内部错误 (7)

Java Hibernate LazyInitializationException 仅在仅使用 JUnit 运行时出现

仅在发送标头时出现 Cors

OSX Finder中的“虚拟文件”仅在我的应用程序运行时出现,可能吗?