Resource Shrinking

Android

Unused 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=true

Important: 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.

Bitrise logo