Understanding Multidex in Android

In Java, if we compile our code then that code is converted into a .class file by the compiler because our machine understands that .class file. The same is the process for the Android Application. In Android, the compiler converts our source code into DEX(Dalvik Executable) file.

So, in this blog, we will learn about Dex and Multidex in Android. Especially, this blog is for those Android developers who get 64K method limit exceeded error while building APK. This error comes due to DEX. So, in this blog, we will try to gain more knowledge about Dex and Multidex in Android.

The timeline of this blog is as follows:

  • Android build system
  • Multidex in Android
  • Multidex support for API level 20 or lower
  • Multidex support for API level 21 or higher
  • App configuration for Multidex
  • Limitations of Multidex support library
  • Conclusion

Android Build System

Before moving on to DEX, let's revise some concepts of build system of Android. Android compiles the resources and source code of our app, and packages then into APKs. Conversion of our project into an APK requires many tools and involve many processes. You can understand the build process with the help of the below diagram:

Picture courtesy : Android Developer website

The build process of a typical Android App can be summarized as below:

  1. The compilers convert the source code into DEX (Dalvik Executable) files, which include the bytecode that runs on Android devices.
  2. After having the DEX files, the APK Packager combines the DEX files and compiled resources into a single APK.
  3. After that, the APK Packager signs APK.
  4. Before generating the final APK, various methods are followed to optimize the code so as to avoid the unused code.

Multidex in Android

In Android, the compilers convert your source code into DEX files. This DEX file contains the compiled code used to run the app. But there is a limitation with the DEX file. The DEX file limits the total number of methods that can be referenced within a single DEX file to 64K i.e. 65,536 methods. So, you can't use more than 64K methods in a particular DEX file. These 64K methods include Android framework methods, library methods, and methods in our code also. This limit of 64K is referred to as the "64K reference limit".

So, if our app exceeds 65,536 methods, we will encounter a build error that indicates our app has reached the limit of the Android build architecture. The error is as follows :

Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

Older versions of the build system report a different error, which also indicates the same problem:

Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536

Both the above error are known as 64K reference limit i.e we are trying to use more than 64K methods in our code. So, here comes the role of Multidex support in our Android Project. Next time if you want to use more than 64K methods in your project then you can use Multidex to achieve this. In the next part of this blog, we will learn how to use the Multidex support for our project having more than 64K methods.

Multidex support for API level lesser than 21 i.e. Android 5.0

For executing app code, versions of Android lesser than Android 5.0 (API level 21) use the Dalvik runtime and limitation of using Dalvik is that you can't use more than one bytecode file per APK.

To add multidex support library to your project for API level lesser than 21, add the following dependency in your build.gradle file.

dependencies {
    implementation 'androidx:multidex:2.0.1'
}

If you aren't using AndroidX, add the following support library dependency instead:

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

By adding this library, your app can manage the access of additional DEX files that are present in your code. In other words, if you are having more than 64K methods, then you will be having more than one DEX file and these DEX files will be managed by using this library.

Multidex support for Api level 21 and higher

Your task becomes easier if you are making an app for Android version 5.0 (API level 21) or higher. API level 21 uses a runtime called ART which supports loading multiple DEX files from APK files. So, you don't need to add support library for multidex in Android 5.0 or higher.

What ART does is, it scans or finds all the .dex files available in your code and compiles them into a single .oat file.

App configuration for Multidesk

If you are getting some type od DEX error then before configuring your app to enable the use of 64K or more reference methods, you should try to reduce the total number of reference methods that are being used by our app. Try the following strategies to avoid using 64K reference methods:

  1. Manage dependencies: While importing some dependencies for our project, sometimes we import each and every library and use only a few of them. So, instead of keeping all those dependencies, we can keep only the required one. To learn more about dependency management through Gradle you can check our blog "Gradle tips and tricks for Android".
  2. Remove unused code: Enable code shrinking in your project. By doing so, we are not shipping unused code with our APK. TO know more about code shrinking, you can check our blog "Gradle tips and tricks for Android".

If you are done with the code shrinking part, then do the following modifications in your app project, to use Multidesk.

for SDK version 21 or higher, you need to set multiDexEnabled to true in your module-level build.gradle file, as shown here:

android {
    defaultConfig {
        ...
        minSdkVersion 21 
        targetSdkVersion 28
        multiDexEnabled true
    }
    ...
}

However, if your minSdkVersion is set to 20 or lower, then you must use the multidex support library as follows:

  • Modify the module-level build.gradle file to enable multidex and add the multidex library as a dependency, as shown here:
android {
    defaultConfig {
 ...
        minSdkVersion 15 
        targetSdkVersion 28
        multiDexEnabled true
 }
 ...
}

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

  • Depending on whether you override the Application class, perform one of the following:

1. If you do not override the Application class, edit your manifest file to set android:name in the <application> tag as follows:

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

2. If you do override the Application class, change it to extend MultiDexApplication (if possible) as follows:

public class MyApplication extends MultiDexApplication { ... }

3. Or if you do override the Application class but it's not possible to change the base class, then you can instead override the attachBaseContext() method and call MultiDex.install(this) to enable multidex:

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

So, when you build your app, one primary DEX file will be constructed and supporting DEX files will also be added to it. The primary DEX file is normally marked as classes.dex and other supporting DEX files as classes1.dex, classes2.dex, ... and so on.

At build time, all dex files will be searched and combined to form a .oat file.

Limitations on multidex support library

A good Android Developer know about the benefits of using some library but a profesional developer also knows the limitations of using that library

The multidex support library has some known limitations that we should be aware of before using it in our app. Some of the limitations are:

  • If your secondary DEX file is larger than the primary DEX file, then you may encounter some Application Not Responding (ANR) error. In this case, you should apply code srinking to minimize the size of DEX files and remove unused portions of code.
  • If you are targeting API levels lower than 21, test thoroughly on those versions of the platform, because your app might have issues at startup or when particular groups of classes are loaded.

Code Shrinking can reduce or possibly eliminate these issues.

Conclusion

If you are working on an Android application that includes more than 64K methods then to avoid the 64K reference limit, you can use Multidex in your application. I am sure that after reading this blog, you all are familiar with the Multidex property of Android. So implement this property in your project, but before doing so, make sure that your code is totally shrunk because code shrinking will help in reducing or possibly eliminating the Dex error.

Happy learning :)

Team MindOrks.