As the Android platform has continued to grow, so has the size of Android apps. When your application and the libraries references reach a certain size, you encounter build errors that indicate your
app has reached a limit of the Android app build architecture. Earlier versions of the build system report this error as follows
More recent versions of the Android build system display a different error, which is an indication of the same problem:
Both these error conditions display a common number: 65,536. This number is significant in that it represents that total number of references that can be invoked by the code within a single Dalvik Executable (dec) bytecode file. IF you have built an Android app and received this error, then this document is for you, which explains how to move past this limitation and continues building your app.
In many cases these high numbers are reached by including 3rd-party libraries. Here is a summary of some popular libraries that is included:
app has reached a limit of the Android app build architecture. Earlier versions of the build system report this error as follows
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536
More recent versions of the Android build system display a different error, which is an indication of the same problem:
trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.
Both these error conditions display a common number: 65,536. This number is significant in that it represents that total number of references that can be invoked by the code within a single Dalvik Executable (dec) bytecode file. IF you have built an Android app and received this error, then this document is for you, which explains how to move past this limitation and continues building your app.
In many cases these high numbers are reached by including 3rd-party libraries. Here is a summary of some popular libraries that is included:
Name | Maven Artifact | Overall Method Count |
---|---|---|
Google Play Services | play-services:6.1.11 | 29,460 |
Guava | guava:18.0 | 14,842 |
AppCompat V7 | appcompat-v7:21.0.0 | 12,324 |
Android Support V4 | support-v4:21.0.0 | 8,078 |
Jackson | jackson-jaxrs-json-provider:2.4.3 | 6,731 |
Joda-Time | joda-time:2.5 | 5,025 |
Apache Commons Lang3 | commons-lang3:3.3.2 | 3,582 |
Apache Commons IO | commons-io:2.4 | 1,571 |
Gson | gson:2.3 | 1,243 |
Solution
MultiDex
In many cases MultiDex allows you to use multiple Dex files contained within on APK. With a few steps, your classes will split automatically into several DEX files i.e classes.dex, classes2.dex, classes3.dex etc in cas you reach the ethos index limit.
To integrate MultiDex into your application follow below steps.
First step:
Enable mult-dex mode in your builds - A component of the Android build tools named dx, which is executed during the build process as part of the dex task now accepts a -multi-dex flag.
Add -multi-dex options to dx command line to allow the generation of several dex files when method index limit is about to be reached. In order to achieve that add following line of code in your build.gradle file.
android {
defaultConfig
//Enabling multidex support.
multiDexEnabled true
}
}
This essentially modifies all dex* tasks i.e dexDebug, dexRelease and adds the -multi-dex flag to the arguments list when executing dx.
After doing this, a build should generate an APK file with multiple DEX files.
Second step:
Now we would be loading these classes at runtime. For Android L or higher (5.0+) this is natively supported, for devices running API level 20 or lower, we need to make another small effort. Luckily, the Android Support Library (revision 21) is shipped with MultiDex support. The package provides a utility that will take care of the class loading process from the additional DEX files on API levels 4 through 20. For API 21 or higher it does nothing, again, as it is natively supported. The package has the following description:
Monkey patches the application context classloader in order to load classes from more than one dex file. The primary classes.dex must contain the classes necessary for calling this class methods. Secondary dex files named classes2.dex, classes3.dex… found in the application APK will be added to the classloader after first call to install(Context).
This library provides compatibility for platforms with API level 4 through 20. This library does nothing on newer versions of the platform which provide built-in support for secondary dex files.
Take the android-support-multidex.jar file from your SDK folder under extras/android/support/multidex/library/libs folder, and add it as a dependency. Then is can be used in one of the following ways.
If you don't have a custom Application class registered, just set the following attribute on your application element in the manifest file
android:name="android.support.multidex.MultiDexApplication"
However, if you have a custom Application class registered, you can either make that class extend MultiDexApplication instead of Application, or simply override attachBaseContext() like so :
@Override protected void attachBaseContext(Context base) {
super.attachBaseContext(base)
MultiDex.install(this)
}
Thats it, now your project should no longer be affected by 65K
limitation.
android {
defaultConfig
//Enabling multidex support.
multiDexEnabled true
}
}
Second step:
Monkey patches the application context classloader in order to load classes from more than one dex file. The primary classes.dex must contain the classes necessary for calling this class methods. Secondary dex files named classes2.dex, classes3.dex… found in the application APK will be added to the classloader after first call to install(Context).
This library provides compatibility for platforms with API level 4 through 20. This library does nothing on newer versions of the platform which provide built-in support for secondary dex files.
Take the android-support-multidex.jar file from your SDK folder under extras/android/support/multidex/library/libs folder, and add it as a dependency. Then is can be used in one of the following ways.
If you don't have a custom Application class registered, just set the following attribute on your application element in the manifest file
android:name="android.support.multidex.MultiDexApplication"
However, if you have a custom Application class registered, you can either make that class extend MultiDexApplication instead of Application, or simply override attachBaseContext() like so :
@Override protected void attachBaseContext(Context base) {
super.attachBaseContext(base)
MultiDex.install(this)
}
Thats it, now your project should no longer be affected by 65K
limitation.
android:name="android.support.multidex.MultiDexApplication"
@Override protected void attachBaseContext(Context base) {
super.attachBaseContext(base)
MultiDex.install(this)
}