Mobile Development 14 min read

How to Shrink Android APKs: Proven Tips from WeChat’s Build System

This article explains how WeChat reduces Android APK size and ensures installability by optimizing the build process with Buck, monitoring resources, removing unused assets, compressing images, tweaking string encoding, managing native libraries, and handling dex and memory limits.

WeChat Client Technology Team
WeChat Client Technology Team
WeChat Client Technology Team
How to Shrink Android APKs: Proven Tips from WeChat’s Build System

1. Build Process Overview

WeChat originally built APKs with Ant or Gradle, which lack sufficient parallelism for multi‑library projects. They switched to Facebook's open‑source build tool Buck , dramatically speeding up compilation.

On top of Buck, two main improvements were made:

EclipseToBuck : automatically generates Buck scripts so developers don’t need to write them manually.

Monitoring each module’s linear memory, method count, and resource size in the multi‑library structure.

2. Tips for Reducing APK Size

2.1 APK Monitoring

A custom monitoring tool tracks:

Changes in the number of methods per DEX file.

Linear memory variations of each module.

Conversion of PNGs without an alpha channel to JPG to save space.

Lossy compression for large files, especially image resources.

Total APK size and file count changes.

Added or removed files and their size differences.

Monitoring is performed daily (comparing the latest build with the previous day) and between versions (comparing the release candidate with the current production APK), with alerts sent to the bug system when regressions are detected.

2.2 Removing Unused Resources

Unused XML, PNG, ID, and string resources are identified using lint rules UnusedResources and UnusedIds. Because the default lint checks do not fully support a multi‑library setup, WeChat customized the rules to improve detection.

2.3 Image Processing

Key recommendations:

Images larger than 50 KB should be lossy‑compressed (e.g., JPEG with optimized settings or PNG with pngquant).

All assets should be pre‑processed with aapt crunch.

Be aware that crunch can increase size for some images; in such cases, keep the original file. .9.png files must not be replaced after crunching because the black border is removed.

Convert non‑transparent PNGs to JPG.

2.4 String Encoding

Resources.arsc contains a deduplicated string pool. Since Android 2.2 (API Level 8), the default encoding switched from UTF‑16 to UTF‑8, which reduces size for pure ASCII strings but may increase size for CJK characters. If UTF‑8 inflates the resources.arsc, force UTF‑16 with the --utf16 flag in aapt.

bool getUTF16StringsOption() {
    return mWantUTF16 || !isMinSdkAtLeast(SDK_FROYO);
}

2.5 File Compression and 7‑Zip

APK files are ZIP archives; each entry can be stored using either Deflate (compressed) or Stored (uncompressed). Large media files (e.g., .jpg, .png, .gif) are typically stored uncompressed because they are already compressed. The following extensions are excluded from compression:

static const char* kNoCompressExt[] = {".jpg", ".jpeg", ".png", ".gif", ".wav", ".mp2", ".mp3", ".ogg", ".aac", ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet", ".rtttl", ".imy", ".xmf", ".mp4", ".m4a", ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2", ".amr", ".awb", ".wma", ".wmv"};

Note that on Android 2.3 and earlier, any compressed resource larger than 1 MB causes AssetManager to throw an exception.

2.6 C++ .so Libraries

Switching from static linking to stlport_shared reduces APK size by sharing common C++ code across modules and also saves memory at runtime.

2.7 Dynamic Language Packs

WeChat supports over 20 languages, inflating resources.arsc to >5 MB. By keeping only the default language (Chinese) in the base APK and delivering other language packs on demand, the APK size can be cut by more than half.

2.8 Resource Obfuscation

Using a custom resource‑obfuscation tool (independent of source code) can shrink resource names, making reverse engineering harder and reducing APK size by roughly 1 MB.

2.9 Continuous Delivery

Modular architecture and dynamic loading allow rarely used features (e.g., mini‑games) to be delivered on demand, further decreasing the base APK size. Removing unused features is the most effective way to cut size.

3. Ensuring Installability

3.1 Dex Method Limit (65 536)

If the method count exceeds the limit, split the code into multiple DEX files.

function dex-method-count() {
  cat $1 | head -c 92 | tail -c 4 | hexdump -e '1/4 "%d
"'
}

3.2 Compressed Resource Size Limit

Compressed resources must be smaller than 1 MB to avoid installation failures on older Android versions.

3.3 Linear Memory Limit

During dexopt, the system reserves 5–16 MB of linear memory. Exceeding this limit causes dexopt to fail. WeChat targets a maximum of 4 MB per DEX, though on some Android 2.3 devices failures occur above 3.5 MB. Buck’s asm-debug-all tool is used to calculate the linear memory footprint of each class.

mobile developmentPerformanceAndroidBuild ToolsAPK OptimizationSize reduction
WeChat Client Technology Team
Written by

WeChat Client Technology Team

Official account of the WeChat mobile client development team, sharing development experience, cutting‑edge tech, and little‑known stories across Android, iOS, macOS, Windows Phone, and Windows.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.