Resource Shrinking
AndroidUnused resources (drawables, layouts, strings) shipping in production. Resource shrinking combined with locale filtering can reduce app size by up to 50%.
Android resource shrinking is a build-time process that removes unused resources (drawables, layouts, strings, colors, dimensions, etc.) from the final APK. It works in conjunction with R8 code shrinking: after R8 removes unreachable code, the resource shrinker identifies resources no longer referenced by the remaining code. Starting with AGP 8.12.0, optimized resource shrinking combines code and resource analysis in a single R8 pass. Additionally, resourceConfigurations allows stripping unused locale and density resources that third-party libraries bundle.
Why this happens
Library locale bloat: Libraries like AppCompat, Material Components, and Google Play Services include string translations for 70+ languages. If your app supports only 3 languages, the other translations still ship.
Unused drawable densities: Even if your app only targets modern phones (xxhdpi/xxxhdpi), libraries may include ldpi/mdpi/hdpi variants.
Development residue: Resources created during development (test layouts, experimental drawables, placeholder strings) remain in res/ after the code that used them is deleted.
Dynamic resource loading: Code using Resources.getIdentifier() prevents the shrinker from detecting true usage, keeping resources alive unnecessarily in safe mode.
Size impact
Resource shrinking is especially impactful for apps with heavy library dependencies that bundle translations and density-specific assets for all configurations.
Optimized shrinking (AGP 8.12+)
Up to 50% reduction
shrinkResources + resConfigs
App can reach ~1/3 original size
How we detect it
Lint inspection "Unused Resources" scans the project for unreferenced resources. When resource shrinking is enabled, the build outputs a log of removed resources at build/outputs/mapping/release/resources.txt.
How to fix
1
Enable resource shrinking
Set isShrinkResources to true in your release build type. Requires isMinifyEnabled to be true.
build.gradle.kts (app module)
android {
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
}2
Filter locale resources
Specify only the languages your app actually supports. This strips all other locale resources from dependencies.
build.gradle.kts
android {
defaultConfig {
androidResources {
localeFilters += listOf("en", "de", "fr", "ja")
}
}
}3
Enable strict shrink mode
Safe mode (default) is conservative and keeps resources whose names could be constructed dynamically. Strict mode removes everything not explicitly referenced.
res/raw/keep.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:shrinkMode="strict"
tools:keep="@layout/l_used_*,@drawable/ic_dynamic_*"
tools:discard="@layout/unused_layout,@drawable/test_*" />4
Enable optimized resource shrinking (AGP 8.12.0+)
Combines code and resource analysis in a single R8 pass for better removal of unused resources.
gradle.properties
android.r8.optimizedResourceShrinking=trueImportant: isMinifyEnabled is mandatory for resource shrinking to work. Strict mode can break apps that load resources dynamically by name (plugin architectures, theming engines, A/B testing). Add explicit tools:keep entries for dynamically-loaded resources. Resource shrinking removes unused resources from both your app and its library dependencies.
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.