Native Library Optimization
AndroidNative libraries (.so files) shipping unnecessary CPU architectures. Filtering to ARM-only or using App Bundles can reduce native library size by 50% or more.
Native libraries (.so files in the lib/ directory) are often the single largest contributor to APK size. Android supports four ABIs: armeabi-v7a (32-bit ARM), arm64-v8a (64-bit ARM), x86 (32-bit Intel), and x86_64 (64-bit Intel). By default, if a project or its dependencies include native code for all four architectures, the APK ships all four variants, even though a device only needs one. The x86/x86_64 variants are only needed for emulators, representing a negligible fraction of production devices. Additionally, unstripped .so files contain debug symbols that can be multiple times the size of the actual machine code.
Why this happens
Fat APKs: Without ABI filtering, Gradle bundles native libraries for all supported architectures, quadrupling native library storage.
Third-party SDK bloat: SDKs like video players, ML frameworks, or WebRTC ship native binaries for all ABIs. A single SDK can add 10-30 MB per architecture.
Debug symbols in release builds: Without proper stripping, .so files contain symbol tables and DWARF info that inflate their size by 2-5x.
Duplicate native dependencies: Multiple libraries may bundle the same underlying native code (e.g., multiple SDKs each shipping their own copy of libc++_shared.so).
Size impact
Removing unnecessary architectures is one of the highest-impact, lowest-effort optimizations for native-heavy Android apps.
Removing x86/x86_64
10-30 MB savings typical
Single-ABI filtering
Up to 70% native lib size reduction
Debug symbol stripping
2-5x size reduction per .so file
How we detect it
Inspects the lib/ directory of the APK to identify which ABI directories exist (armeabi-v7a, arm64-v8a, x86, x86_64) and the total size of each. Checks .so files for unstripped debug symbols using file metadata.
How to fix
1
Filter ABIs in Gradle
For APK-based distribution, restrict to ARM architectures only. x86/x86_64 are needed only for Intel-based emulators.
build.gradle.kts (app module)
android {
defaultConfig {
ndk {
abiFilters += listOf("armeabi-v7a", "arm64-v8a")
}
}
}2
Use Android App Bundle for automatic ABI splitting
When using AAB, Google Play automatically generates per-ABI configuration APKs, so users only download the native library for their device.
build.gradle.kts
android {
bundle {
abi {
enableSplit = true // default for AAB
}
}
}3
Strip debug symbols from .so files
Debug symbols are stripped automatically in release builds by AGP. For manually-built native code, use the NDK strip tool.
$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip \
--strip-debug path/to/lib.so4
Upload debug symbols separately for crash reporting
Set debugSymbolLevel to FULL in your release build type so native crash reports can be symbolicated without shipping symbols in the APK.
build.gradle.kts
android {
buildTypes {
release {
ndk {
debugSymbolLevel = "FULL"
}
}
}
}Important: Do not remove arm64-v8a. Google Play requires 64-bit support since August 2019. Removing x86/x86_64 means emulators without ARM translation will not run the app. Modern emulators (API 30+) support ARM translation, but older images do not.
Powered by Bitrise, trusted by 8,500+ brands
Size Analyzer is built by Bitrise, the leading mobile DevOps platform used by over 400,000 developers at companies like Shopify, TripAdvisor, and BuzzFeed. Free forever. No signup required.
Bitrise provides a full-stack mobile DevOps solution that unites the tools, processes, and testing frameworks engineering teams need to ship best-in-class mobile experiences.