How Baidu App Shrinks Android APK Size with Advanced Resource Optimizations
This article details Baidu's multi‑step Android APK resource‑size reduction strategy, covering the structure of APK resources, built‑in AAPT2 optimizations, custom path and filename shortening, resource‑name collapsing, sparse entry encoding, image compression, duplicate‑resource handling, and the impact of AAB and Jetpack Compose on overall package size.
Background
Previous articles covered overall size‑reduction strategies and Dex line‑number shrinking. This third part concentrates on resource‑level optimizations for an Android APK/AAB, i.e., reducing the size of resources.arsc, the res/ directory and the assets/ directory.
APK resource layout
An APK contains three resource‑related sections:
res/ – compiled static resources (drawables, layouts, strings, etc.).
resources.arsc – binary index generated by AAPT2 that maps resource IDs to the best matching file.
assets/ – raw files accessed through AssetManager without compile‑time validation.
Built‑in AGP resource‑optimisation tasks
Android Gradle Plugin (AGP) registers two AAPT2‑based tasks:
OptimizeResourcesTask – runs after linkResources and before shrinking. By default it enables --shorten-resource-paths. The flags are defined in AAPT2OptimizeFlags:
enum class AAPT2OptimizeFlags(val flag: String) {
COLLAPSE_RESOURCE_NAMES("--collapse-resource-names"),
SHORTEN_RESOURCE_PATHS("--shorten-resource-paths"),
ENABLE_SPARSE_ENCODING("--enable-sparse-encoding")
}Additional flags can be turned on via android.enableResourceOptimizations = false or by setting enableResourceObfuscation in the task parameters.
Resource‑path shortening
Resource paths appear in four locations:
String pools inside resources.arsc.
SHA‑1 digests in MANIFEST.MF.
File entry name in the ZIP data section.
File name in the ZIP central directory.
Three of these locations are stored uncompressed, so each byte saved in the path yields roughly a 4× reduction in APK size.
Baidu’s custom optimiser rewrites every path to a deterministic hash‑based identifier, guaranteeing a one‑to‑one mapping for runtime lookup.
std::string ShortenFileName(const android::StringPiece& file_path, int output_length) {
std::size_t hash_num = std::hash<android::StringPiece>{}(file_path);
std::string result;
for (int i = 0; i < output_length; ++i) {
uint8_t sextet = hash_num & 0x3f;
hash_num >>= 6;
result += base64_chars[sextet];
}
return result;
}Directory and file‑name collapsing
All res/type[-qualifier] directories are collapsed to a single r/ prefix. File names are replaced by a three‑character base‑64 hash, preserving a deterministic mapping for the runtime.
Extension stripping
Only XML files under res/color and res/drawable need the .xml suffix for parsing; all other extensions are removed, saving at least four bytes per file.
bool ResourcePathShortener::Consume(IAaptContext* context, ResourceTable* table) {
if (util::StartsWith(res_subdir, "res/color") ||
util::StartsWith(res_subdir, "res/drawable")) {
if (util::StartsWith(extension, ".xml")) {
keep_extensions = true;
}
}
}Resource name collapsing
When --collapse-resource-names is enabled, every entry in the ResTable_entry name pool is replaced by a single placeholder string, except for resources listed in a whitelist (e.g., analytics that rely on the original name). This can shrink the resources.arsc string pool from several hundred kilobytes to a few bytes.
The --enable-sparse-encoding flag switches the arsc entry lookup from O(1) dense to O(log n) sparse, reducing the size of the arsc file at the cost of a modest lookup overhead.
Other AGP resource options
resConfigs – keeps only the specified configuration qualifiers (language, density, etc.) and discards the rest.
splits – generates separate APKs for each density; useful when AAB is not supported.
Custom optimisation pipeline
Baidu builds a second‑stage tool on top of AAPT2 that applies the following steps:
Rewrite resource paths using the hash algorithm described above.
Collapse directory hierarchy to r/ and shorten file names to three characters.
Strip extensions except for the required XML files.
Apply a whitelist for path‑preserving resources.
Optionally collapse all resource names to a single placeholder string.
Generate a mapping file (original ↔ obfuscated) for debugging or analytics.
Impact
In a typical Baidu APP with ~10 000 resources, path shortening alone saves ~40 KB (1 byte saved × 4 locations × 10 000). Directory and file‑name collapsing add a few more kilobytes, and name collapsing can reduce the resources.arsc string pool by >90 %.
Combined with lossless image compression (e.g., ImageOptim) and duplicate‑resource removal (MD5 hash comparison, OpenCV feature detection for similar images), the overall APK/AAB size can be reduced by several percent without affecting functionality.
References
https://developer.android.com/guide/topics/resources/providing-resources#ResourceTypes
https://developer.android.com/studio/command-line/aapt2
https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.2.0.txt
https://imageoptim.com/mac
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.
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.
