Multidexing in Unreal Engine 4

When your app is growing, also its needs. Google Play, Facebook, analytics systems, advertising, crash reporters and more are put into the build and at some point the infamous “64k methods” problem occurs. Why? According to the Android Developer’s User Guide:

"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."


In other words – you can’t have more than 65,536 methods in Your java code (and it’s not so difficult to do this, because the full Google Play SDK uses about half of this limit).

Dealing with this problem is rather easy… if you are using Gradle. Unfortunatelly Unreal Engine 4 still uses Ant. So, what do we do when the “64k problem” hits us? Do we cry and fall into despair? No, no, no… This is how you can fix this:

Identifying a p roblem

First of all, we need to know when the “64k methods” actually occurs? At the beginning I suggest to change Ant Verbosity value in Project Settings -> Android to Verbose. Thanks to this you will be able to see more information about what is happening during the building process.


If Android build fails, we must look for such information in our output log:


If the com.android.dex.DexIndexOverflowException occurs, then we know we have the “64k methods” problem.

Unreal Engine 4 plugin

Thanks to the collaboration with gameDNA there is a plugin, which enables multidexing! You can download it from here. If you are interested in how it works – I invite you to further reading.

Multidexing in Unreal Engine 4.17

Starting from version 4.17 Unreal Engine supports Gradle build system instead of Ant. Thanks to this supporting multidexing is much easier. For details read MultiDex_UPL_Android.xml file from MultiDex plugin.

Building mechanism when using Ant

The whole building system is based on a single xml file located in android-sdk/tools/ant/build.xml. To change the default behavior of the build mechanism we must override methods from this file. To do this we use a custom_rules.xml file, which can be found in the Engine/Build/Android/Java/custom_rules.xml location. Because we don’t want to make a mess inside this file we will import the separate custom rules to it. Simply add
<import file="custom_rules_multidex.xml" optional="true" />
line at the end of the <project> block.

Custom_rules_multidex

The whole custom_rules_multidex.xml file can be downloaded from here.

Put it into the same directory where custom_rules.xml is.

The main idea is to override the default -dex target, so it will use the dex-helper-multi macro (instead of the default dex-helper macro) to perform a dexing process with a --multi-dex option.

--multi-dex option allows the dexing process to create secondary dex files next to the primary one.

To make this work the multidex-main-dex-list.txt file must be passed to the --main-dex-list parameter of the --dex operation. It contains a list of classes that must be inside the primary dex file. You can download this file from here. Put it into the same directory where custom_rules.xml is.

The last, but not least: the -post-package-resources target is created in order to pack the second dex file.

Loading the second dex file

At this point the APK has multiple dex files and by default only primary one is loaded at the start of the application.

To inform Android that the app has multiple dex files the Manifest must be modified. In Project Settings -> Android find the “Extra Tags for <application> node” field and insert
android:name="android.support.multidex.MultiDexApplication"


You also have to put the android-support-multidex.jar library into the Engine/Build/Android/Java/libs directory.

Proguard

To prevent Proguard from stripping the multidex support library add this to the end of the Engine/Build/Android/Java/proguard-project.txt file
-keep class android.support.multidex.** {
    *;
}

Out of memory error

If you’ve encountered the java.lang.OutOfMemoryError it means the java virtual machine has not enough memory to build the code. To increase it set up the environment variable _JAVA_OPTIONS with the value -Xmx1024m -Xms256m -Xss8m.

-Xmx is a maximum size of the java virtual machine, -Xms is an initial size of the java virtual machine and -Xss is a size of the stack.

You might need to increase the -Xmx value to something between 1024m and 2048m.

Final words

After making changes in the Java related files in the Engine it is a good practice is to delete a YourGame/Intermediate/Android directory, because Unreal Engine 4 likes to cache too many files.
At this point the building process should go smoothly and the game should work with all of the libraries you have!

Limitations

  • The method I’ve just presented will make every build multidex. If you have a project that doesn’t need multidexing the build will fail! You can simply remove the import of the custom_rules_multidex.xml file from custom_rules.xml then.
  • The custom_rules_multidex.xml supports only two dex files! If you (somehow) need more than that, you must fix the -post-package-resources target to pack all additional dex files.