Roles of minifyEnabled and shrinkResources and common pitfalls

Tests R8 code shrinking vs resource stripping and runtime risks. Outline: minifyEnabled shrinks code; shrinkResources removes unused assets and requires minifyEnabled; dynamic access like getIdentifier() crashes; keep resources with tools:keep or keep.xml.
WHAT THIS TESTS: Whether you understand the two distinct stages of Android release build optimization and their dependency chain. Interviewers want to see that you know minifyEnabled is about code and shrinkResources is about assets, and that you have been burned by or at least understand the runtime risks of dynamic resource access.
A GOOD ANSWER COVERS four things in order. First, define minifyEnabled as the Gradle flag that enables R8 to perform code shrinking, optimization, and name obfuscation. It analyzes bytecode to remove unused classes, methods, and fields. Second, define shrinkResources as the flag that strips unused resources from the packaged APK or AAB. Third, state the critical dependency: shrinkResources only works when minifyEnabled is true because the resource shrinker relies on the code shrinkers reachability graph to know which resources are referenced from code. Fourth, describe the common pitfall and mitigation. The pitfall is that resources accessed dynamically via methods like getIdentifier, reflection, or certain data binding patterns are invisible to static analysis, so the shrinker removes them and the app crashes with ResourceNotFoundException at runtime. The mitigation is to explicitly keep those resources using the tools:keep attribute directly in resource XML files or by creating a res/raw/keep.xml file with keep directives. Refactoring away from dynamic resource lookup is the cleanest long term fix.
COMMON WRONG ANSWERS include treating the two flags as if they do the same thing, saying shrinkResources removes code, or claiming shrinkResources works independently without minifyEnabled. Another red flag is suggesting you should simply disable shrinkResources in production to avoid bugs rather than using keep rules. Saying you have never used shrinkResources because it is too risky also signals a lack of production build ownership.
LIKELY FOLLOW-UPS: How would you debug which resources were removed? The interviewer might ask about the res/raw/keep.xml syntax or how to use the tools:shrinkMode attribute set to strict versus safe. They may also ask how app bundles affect this, or how library modules handle resource shrinking. Another angle is asking how you would measure APK size impact before and after enabling these flags.
ONE CONCRETE EXAMPLE: Suppose your app has a feature module that inflates layouts dynamically based on server responses using getIdentifier("layout_" + serverType, "layout", packageName). With shrinkResources true, R8 sees no direct references to R.layout.layout_premium or R.layout.layout_basic in compiled code, so the resource shrinker strips them. When the server returns premium, the app crashes. To fix it, you add tools:keep="@layout/layout_premium,@layout/layout_basic" to a keep.xml in res/raw, or you add tools:keep on the root tag of those layout files if they are referenced indirectly. This tells the shrinker to retain them despite the lack of static references.
Source: developer.android.com
Read the original → developer.android.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.