DexIndexOverflowException Only When Running Tests
Asked Answered
R

4

14

I can successfully build and run my Android app in my debug and release variants with no problem. Yet, when I try to run my new unit tests (I never had them before), I get the dreaded DexIndexOverflowException. I suspect ProGuard is not being run with my unit tests, but it is with my normal debug and release buildTypes.

What do I need to do to run ProGuard in my unit test run configuration? I searched through the Gradle documentation, the ProGuard documentation, and the Android Studio documentation to figure this out yet I found nothing.

Rehm answered 24/10, 2015 at 0:3 Comment(3)
as you can't use ProGuard for running test, you will need to configure MultiDex : developer.android.com/tools/building/multidex.html ProGuard solve normally the multiDex by whitout knowing it : it only delete unused methods.Pyrope
add multiDexEnabled true to your gradle or comment this compile fileTree(dir: 'libs', include: ['*.jar'])Oldtime
@HugoGresse Since Android Gradle plugin version 1.2.0 you actually can can have Test-only ProGuard files.Indeterminable
L
21
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.

The Android plugin for Gradle available in Android SDK Build Tools 21.1 and higher supports multidex as part of your build configuration. Make sure you update the Android SDK Build Tools tools and the Android Support Repository to the latest version using the SDK Manager before attempting to configure your app for multidex.

Setting up your app development project to use a multidex configuration requires that you make a few modifications to your app development project. In particular you need to perform the following steps:

  1. Change your Gradle build configuration to enable multidex
  2. Modify your manifest to reference the MultiDexApplication class

Modify your app Gradle build file configuration to include the support library and enable multidex output .

    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' 
}

In your manifest add the MultiDexApplication class from the multidex support library to the application element.

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

Read Official Document about MultiDex

If your Application class is extending some other class and you don’t want to or can’t change it, override attachBaseContext() as shown below:

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

Then

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

Conclusion

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.

Landtag answered 30/10, 2015 at 6:54 Comment(2)
Bummer. Didn't want to have to enable MultiDex, but this does work. Thanks!Rehm
I don't really think this answer responds to the root of the problem. It sounds like the user is already fully aware of multi-dex issues with regards to non-test builds.Why the test build and not the production build? How do you enable proguard for test builds? My guess is that the second question sounds like a bad idea to begin with.Boycott
A
3

the error occurs maybe because of too many functions in your projects and library. You can:
- Enable multiple dex as @Intellij Amiya's answer
- Check libraries: specifying only the specific Google Play services APIs your app uses, instead of all of them.

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

Find and exclude duplicated dependencies: open your terminal and run:

gradle -q dependencies

It will show a list as below example:

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

You can see some dependencies with (*), you can exclude it from your gradle dependences:

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

Actually, for me, the excluding method works (multiple dex does not). Hope it helps.

Alvinalvina answered 30/10, 2015 at 7:48 Comment(1)
how will I know the exact name of module to exclude ?Hastings
V
1

Upgrading to gradle plugin 3.1.1 fixed the issue for me, as suggested in this answer

Veneering answered 13/4, 2018 at 10:49 Comment(0)
S
-1

If you only need multidex support for tests, you can enable it only for tests with a line like the following in your build.gradle:

dependencies {
    ...
    androidTestCompile 'com.android.support:multidex:1.0.1'
}
Sponson answered 27/6, 2016 at 13:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.