Skip to main content

Solution for the ANT Packaging 65536 Problem

During Unity ANT packaging, multiple dex packages can result in the "method count exceeds 65536" error (a single dex package supports up to 65536 methods). See Google website to better understand this problem.

Image: Appendix_DexMerger_65536

There are two methods to solve this problem:

  • Use Gradle packaging and enable the Multidex option. See Google website for specific instructions.
  • Manually merge JAR packages and res files and import a multidex.jar.

When using an earlier version of Unity that does not support Gradle packaging, use ANT packaging and manually merge the JAR packages and resources. However, the Google website does not currently provide corresponding tools. To solve this problem, Player Network SDK provides the INTLUtils tool to package JAR packages and res files.

Manual Merger Principle

In the Android compilation process, all Java methods are written to dex files. If you do not enable Multidex, there will only be one classes.dex file in the APK.

After enabling Multidex, Gradle packaging will group Java methods, placing the most important Java methods (those that are required during startup) in dex1 (also called classes.dex) and placing other Java methods in dex2 (classes2.dex), dex3 (classes3.dex), and so on.

In principle, manual merging simulates the grouping method in Gradle packaging.

After simple sorting, the process is as follows:

  1. Group Ant projects.
    Divide into group 1, group 2, and so on.

  2. Manually merge group 2, group 3, and other groups into dex2, dex3, and so on.

  3. Place group 1 in Unity.

  4. Use Unity to package the group and output the APK.

  5. Merge dex2, dex3, and so on into the APK.

  6. Re-sign the APK.

Merger Process

note

ANT projects do not only contain Java methods but also AndroidManifest.xml files and res files. These files must also be packaged into the APK by using Unity.

INTLUtils provides functions including:

  1. Merge the JAR packages of all Ant projects into a dex file

  2. Merge the AndroidManifest.xml files of all Ant projects

  3. Merge the res files of all Ant projects

After organizing the files, the process for merging the AndroidManifest.xml files and res files is as follows:

  1. Group Ant projects. Divide into group 1, group 2, and so on.

  2. Place all the groups except group 1 together, merge the AndroidManifest.xml and res files, and copy the merged files to group 1.

  3. Manually merge group 2, group 3, and other groups into dex2, dex3, and so on.

  4. Place group 1 in Unity.

  5. Use Unity to package the files and output the APK.

  6. Merge dex2, dex3, and so on into the APK.

  7. Re-sign the APK.

Operation Guide

Copy the packages to be merged to the INTLUtils directory

Image: Appendix DexMerger Copy Android

Do the following:

  1. Configure the primary AndroidManifest.xml file.

    The manifest property in the primary AndroidManifest.xml file must contain the property xmlns:tools="http://schemas.android.com/tools", and package must be changed to the name of the demo package.

    Image: Appendix DexMerger AndroidManifest

    Image: Appendix DexMerger AndroidManifest File

  2. Copy external layer JAR packages to the libs directory.

    The libs directory serves as the primary JAR directory of Unity and is packaged with group 1.

    Package the multidex-1.0.3.jar file to the libs directory and place the multidex file in dex1.

    Image: Appendix DexMerger libs

Ant Grouping

Place the external layer AndroidManifest.xml file and libs directory in group 1. Other projects can be placed in any group following a simple grouping rule of creating 4 MB groups (not including the .so file size which may reach several MB each and does not affect the Java method count). Ensure that a single dex file does not contain more than 65536 methods.

The group quantity is determined by the method count.

Image: Appendix DexMerger Split

Merge AndroidManifest and resource except group 1

  1. Place all the groups except for group 1 together, such as group 2 and group 3.

  2. Copy the AndroidManifest.xml file from group 1 to the groups outside branch 1 (in order to write the AndroidMainfest.xml files in other groups to the primary AndroidManifest.xml file) and create the libs folder.

    Image: Appendix DexMerger 2-5

  3. Use INTLUtils to merge AndroidManifest.xml and res files.

    java -jar INTLUtils.jar -unityRoot ./2-5 -buildTools /Users/lucasfan/Library/Android/sdk/build-tools/28.0.3 -output ./output2-5

    Image: Appendix DexMerger output2-5

  4. Copy the generated AndroidManifest.xml and res files to group 1.

    Image: Appendix DexMerger new1

Generate dex2,dex3,...

  1. Add a blank AndroidManifest.xml and libs folder in each group.

    The manifest property in the AndroidManifest.xml file must contain the property xmlns:tools="http://schemas.android.com/tools", and package must be changed to the name of the demo package.

  2. Use INTLUtils to merge Java methods.

    java -jar INTLUtils.jar -unityRoot ./2 -buildTools /Users/lucasfan/Library/Android/sdk/build-tools/28.0.3 -output ./output2

Image: Appendix DexMerger Dex2

Place group 1 back in Unity

Image: Appendix DexMerger Unity

Use Unity to package an Android APK

Image: Appendix DexMerger APK

Merge dex2, dex3, and so on into the APK

The names of dex files generated by the tool are in the format classes2.dex, classes3.dex, and so on.

Use aapt to merge dex files into the APK.

aapt a test.apk classes2.dex

Place the APK and dex files in directories at the same level. This ensures that the dex files are added to the root directory of the APK.

Re-sign the APK

apksigner sign --ks debug.keystore --ks-key-alias XXXX --ks-pass pass:XXXX --key-pass pass:XXXX -out test-signed.apk test.apk

Note that, if the password contains special characters such as exclamation points (!), add \ before these characters, for example, --ks-pass pass:\!1234.

INTLUtils Parameter Description

  • -mainProject, the main project. It does not have to be configured when unityRoot has been set.

  • -subProject, the subproject(s), with multiple projects separated by commas. It does not have to be configured when unityRoot has been set.

  • -buildTools, Android build tools directory (required).

  • -output, the output directory (optional).

  • -package, the target package name (optional). Set to the main project's package name by default.

  • -unityRoot, the standard Android Unity project directory (optional). Setting this parameter is equivalent to setting both -mainProject and -subProject.

  • -useD8, whether to use the D8 compiler (optional). The DX compiler is used by default. Set to 1 to enable the D8 compiler.

  • -androidJar, the android.jar path of the Android SDK, is required when the D8 compiler is used. Path: android_sdk/platforms/api-level/android.jar.

FAQs

A JAR that depends on JDK1.8 failed to generate a dex file

When you use the DX tool to compile a JAR file and generate a dex file, you will see an error message like the one below:

: invalid opcode ba - invokedynamic requires --min-sdk-version >= 26 (currently 13)

This occurs because the JDK1.8 JAR packages generated by DX cannot be converted to dex files. Use the D8 compiler instead.

Set useD8 to 1 and set androidJarto enable the D8 compiler.