仅当 运行 次测试时出现 DexIndexOverflowException

DexIndexOverflowException Only When Running Tests

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

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

com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536 

Android application (APK) files contain executable bytecode files in the form of Dalvik Executable (DEX) files, which contain the compiled code used to run your app. The Dalvik Executable specification limits the total number of methods that can be referenced within a single DEX file to 65,536, including Android framework methods, library methods, and methods in your own code. Getting past this limit requires that you configure your app build process to generate more than one DEX file, known as a multidex configuration.

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

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

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

修改您的应用 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 class 添加到应用程序元素。

<?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

如果您的应用程序 class 正在扩展其他应用程序 class 而您不想或不能更改它,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>

结论

While the library fixes the DEX 64K problem in most cases, it should be treated as a last resort. Before attempting to use it, you should audit your project for unwanted dependencies and remove as much unused code as possible using ProGuard.

出现这个错误可能是因为你的项目和库中的函数太多了。 你可以:
- 启用 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 无效)。希望对你有帮助。

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

中使用如下一行
dependencies {
    ...
    androidTestCompile 'com.android.support:multidex:1.0.1'
}

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