Android resources and runtime selection
Resources separate identity from representation
Your code asks for a stable resource ID such as R.string.checkout_title. Android chooses the best representation for the current locale, night mode, density, API level, and other configuration.
Code asks for R.string.checkout_title
│
current configuration = Tamil + night + tablet
│
Android selects the best matching value
:::warning Android-only chapter
The resource compiler, R, Resources, configuration, and manifest examples require an Android project.
:::
Resource types
res/
├─ values/ strings, colors, dimensions, styles
├─ layout/ View XML layouts
├─ drawable/ vectors, shapes, images
├─ mipmap/ launcher icons
├─ font/ font resources
├─ menu/ menu definitions
├─ navigation/ navigation graphs
├─ raw/ raw files with generated IDs
└─ xml/ general structured XML configuration
Files in assets/ retain file-like paths and do not receive normal R IDs. Choose res/raw when a generated ID/resource stream is useful; choose assets for original hierarchy/names and AssetManager access.
Default and alternative resources
values/strings.xml default
values-ta/strings.xml Tamil
values-night/colors.xml dark theme
drawable-hdpi/product.png high-density bitmap
layout-sw600dp/checkout.xml View layout for sufficient width
Every required resource needs a safe default unless the resource system explicitly guarantees another fallback. A string existing only in values-en can fail on an unsupported locale because no default value exists.
How selection works
Android does not count matching qualifiers and pick the directory with the most. It:
- removes alternatives that contradict the device configuration;
- evaluates qualifier types in documented precedence order;
- narrows candidates using the first relevant higher-precedence qualifier;
- continues until the best match remains;
- handles density using closest-match/scaling rules.
The official resource guide emphasizes that qualifier precedence matters more than the number of exact matches.
Practical selection example
Available:
drawable/banner.xml
drawable-en/banner.xml
drawable-night/banner.xml
drawable-en-night/banner.xml
Device: English + night mode.
Result: drawable-en-night/banner.xml is the best compatible candidate. If it were missing, precedence/fallback rules—not arbitrary filename order—determine the result.
Qualifier directory order matters
drawable-night-hdpi/ ✅ valid qualifier order
drawable-hdpi-night/ ❌ ignored/invalid ordering
Do not invent combinations from intuition. Android Studio and official qualifier tables encode a defined order.
Version qualifiers
values/styles.xml
values-v31/styles.xml
The v31 value is considered only where that API-level configuration is supported. Always keep a default compatible resource for lower versions.
❌ Avoid duplicating values unnecessarily
If the default works on all versions, do not copy it into every values-vXX folder. Alternatives should represent actual differences; duplication creates drift.
Resource references and themes
<TextView
android:text="@string/checkout_title"
android:textColor="?attr/colorOnSurface" />
@string/...references a concrete resource identity.?attr/...asks the current theme to resolve an attribute.
Theme attributes let a reusable component adapt to light/dark/brand themes without hardcoding colors.
❌ Hardcoded semantic color
android:textColor="#000000"
This may disappear in dark mode or violate brand/accessibility decisions.
✅ Theme semantic attribute
android:textColor="?attr/colorOnSurface"
Resource merge is different from runtime selection
At build time, resources from app source sets, build variants, and libraries are merged. At runtime, Android selects among the alternatives packaged into the chosen variant.
Build merge: which resources enter this APK?
Runtime resolution: which packaged alternative matches this device now?
Resource shrinking caveat
Release shrinking can remove resources considered unused. Indirect/dynamic name lookup such as getIdentifier() is harder for tools to analyze and makes refactoring/shrinking unsafe.
✅ Prefer direct generated references
imageView.setImageResource(R.drawable.order_shipped)
Use keep configuration only for justified indirect access and test the minified release—not merely debug.
Android resources give code a stable ID while the runtime selects the best packaged alternative for the current configuration. Selection eliminates incompatible candidates and applies defined qualifier precedence; it does not simply choose the directory with the most qualifiers. I always provide required defaults, order qualifiers correctly, use theme attributes for semantic styling, distinguish build-time merging from runtime resolution, and test minified release resources.