Analyzing and Splitting Android APK Packages with dexSplitter
The article explains how iQiyi created the open‑source dexSplitter tool to analyze Android APK composition, generate per‑module sub‑dex files using ProGuard/R8 mappings, and continuously monitor size growth, offering clear module‑level size statistics despite a modest overall dex size increase.
Wikipedia defines an APK (Android application package) as the file format used by the Android operating system to distribute and install mobile applications and middleware.
iQiyi releases frequent updates, leading to rapid growth of APK size, which can negatively affect user experience.
To quantify the composition of an APK, identify the contribution of each business module, and create a systematic reduction plan, iQiyi conducted a detailed study of APK components and developed a tool called dexSplitter for continuous monitoring of version growth.
The article describes the problem, design ideas, and implementation steps. The core code has been open‑sourced on GitHub: https://github.com/iqiyi/dexSplitter.
Core Issues
The APK structure can be divided into:
AndroidManifest.xml (manifest file)
assets (static resources)
META-INF (signature and certificate information)
res (resource files)
classes.dex (executable bytecode)
resources.arsc (resource index table)
Splitting focuses on the resource directories (res, assets) and the source code (classes.dex). While Android’s AAPT/AAPT2 can analyze resources, the main challenge is splitting the classes.dex file.
Existing Analysis Approaches
Some apps (e.g., Alibaba’s Atlas, Ctrip’s DynamicAPK) already modularize business logic into separate .so ‑like zip files, making size analysis straightforward. Most apps, however, rely on Google’s native multidex solution, which automatically generates multiple dex files.
From the Android compilation perspective, dex generation involves two steps:
Java source → obfuscated .class files
.class files → .dex files
Common dex analysis tools include dex2jar (convert dex to jar) and jd‑gui (view source).
Because dex files undergo obfuscation, compression, and optimization, extracting a one‑to‑one mapping between classes and original source files is unreliable for size attribution.
Technical Idea
The solution draws inspiration from Android’s multidexkeep file, which lists classes that must remain in the main dex. By creating a similar subDexKeep configuration for each business module and using the mapping file to match obfuscated class names, separate sub‑dex files can be generated.
Design and Implementation
1. Generate the ProGuard/R8 mapping file during the normal build process. 2. Classify classes by business module and record them in a configuration file. 3. Trim the mapping file to retain only needed entries, filtering out internal classes using the $ marker. 4. Modify the dex generation tool (dx.jar) or the Gradle Android plugin to recognize the new configuration and produce corresponding sub‑dex files. 5. Optionally adjust the Gradle packaging logic to rename dex files according to business modules.
Two implementation paths are presented:
Modify the dx tool (lightweight, fewer source changes).
Modify the Android Gradle plugin (allows deeper integration, including naming adjustments).
Effect
Comparisons between native packaging and dexSplitter‑enhanced packaging show that the latter provides clear statistics on the size contribution of each business dex segment. Although the total dex size may increase by 5‑9% due to reduced merging and optimization, the overhead is acceptable.
Benefits
Using dexSplitter, iQiyi continuously monitors APK size changes across versions, producing quantitative reports for modules such as the player, payment, and core libraries. The open‑source project on GitHub includes the implementation details, inviting contributions from the community.
iQIYI Technical Product Team
The technical product team of iQIYI
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.