How to Fix INSTALL_FAILED_DEXOPT on Android <3.0 with Custom Dex Splitting
This article explains why INSTALL_FAILED_DEXOPT occurs on Android versions below 3.0, details Google’s official multidex solution, and presents a custom automatic dex‑splitting and dynamic loading approach that overcomes method‑count and LinearAlloc limits while maintaining app performance.
Background
Shortly before a gray‑scale test, the project encountered INSTALL_FAILED_DEXOPT on Android devices below 3.0, causing installation failure. The root causes are the 65K method limit per DEX file and the LinearAlloc buffer limit used by DexOpt during installation.
Early Android versions used DexOpt to generate an optimized ODEX file, but DexOpt stored method IDs in a short‑sized linked list (max 65,536 methods) and relied on a fixed‑size LinearAlloc buffer (5 MB‑16 MB depending on the OS version). When these limits are exceeded, DexOpt crashes.
Although newer Android releases lifted the 65K limit and expanded LinearAlloc, compatibility with older devices still requires a workaround. The project therefore adopted a dex‑splitting strategy to keep the primary DEX and LinearAlloc usage within limits.
Google Official Solution
1. Dex Splitting
Google introduced multidex support in Android Build Tools 21.1. The Gradle configuration is:
android {
compileSdkVersion 21
buildToolsVersion "21.1.0"
defaultConfig {
minSdkVersion 14
targetSdkVersion 21
multiDexEnabled true
}
}
dependencies {
compile 'com.android.support:multidex:1.0.0'
}When using Ant, the Gradle settings must be translated to dx command‑line options. The key dx parameters are:
--multi-dex: enable multiple DEX files.
--main-dex-list=<file>: specify classes that must reside in the primary DEX.
--minimal-main-dex: include only the listed classes in the primary DEX.
By adding the hidden --set-max-idx-number parameter (e.g., 48000), the build produced a second DEX file.
During this process, Android SDK Tools added a "v4" suffix to density‑specific resource directories to ensure compatibility with API level 4 and above.
2. Dex Loading
Google’s android-support-multidex.jar loads secondary DEX files at runtime. It can be activated in three ways:
Declare android.support.multidex.MultiDexApplication in the manifest.
Extend MultiDexApplication with a custom Application class.
Call MultiDex.install(this) from attachBaseContext() or onCreate() of an existing Application subclass.
This approach works but forces all secondary DEX files to reside at the APK root and loads them synchronously at startup.
Custom Automatic Dex Splitting and Dynamic Loading
1. Dex Splitting
The custom solution automates three steps:
Generate main-dex-list by scanning the project before obfuscation.
After ProGuard obfuscation, map the original class names to the obfuscated ones using the mapping file.
Split compiled classes into primary and secondary groups, then invoke dx to produce separate DEX files, placing secondary DEX files (or JARs) in the assets directory.
Android SDK’s mainDexClasses script is leveraged to produce the initial list, while ProGuard’s shrink step retains entry‑point classes.
2. Dex Loading
Instead of the official jar, a custom loader uses DexClassLoader to load secondary DEX files from assets. The loader reflects into the host PathClassLoader to merge its DexPathList.Element array with that of the DexClassLoader, effectively injecting the secondary classes into the main class‑loading path.
Loading can be performed synchronously at startup (e.g., in attachBaseContext()) or on demand for specific features.
3. Installation and Runtime
After packaging, the APK installs successfully on Android 4.3 devices and runs without crashes on Android 2.3 after the custom loader is invoked.
Performance Impact
Synchronously loading secondary DEX files adds overhead to the first launch after installation because the system must run DexOpt on each secondary DEX. Measurements show approximately 1200 ms on a GT‑I8160 (Android 2.3) and 1000 ms on a N‑i9250 (Android 4.3). Subsequent launches are fast (≈10 ms and 4 ms respectively). The size of each secondary DEX directly influences this cost.
Future Work
Further startup‑time optimizations such as splash screens and pre‑DexOpt.
Improving the build‑script performance (from >7 minutes to <10 seconds after two optimizations).
Exploring asynchronous or on‑demand loading of secondary DEX files.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tencent TDS Service
TDS Service offers client and web front‑end developers and operators an intelligent low‑code platform, cross‑platform development framework, universal release platform, runtime container engine, monitoring and analysis platform, and a security‑privacy compliance suite.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
