How to Design Android Apps for Modular Updates and Multi-Device Fragmentation
The Problem
I released my Android app last year. It worked perfectly on my test phone. Then users started complaining. The layout looked broken on their Samsung foldables. Buttons were cut off on tablets. The app crashed on Android Auto. And suddenly, a minor system update changed an API behavior I relied on.
The old assumptions I made were wrong:
- Android updates come once a year with full OS releases- Standard phone screen is 360dp width- API behavior stays stable between minor updates- One APK fits all devicesThe reality in 2026 is fundamentally different.
What Changed in Android
Android’s architecture shifted in ways that break traditional development approaches:
Modular System Updates
System-level packages now update independently from full OS upgrades. This means:
Traditional: One big OS update per year → Predictable behavior changes → Yearly architecture review
Now: Continuous component updates → Faster behavior changes across devices → Reduced control over version assumptions → Quarterly (or more frequent) review neededI can no longer assume my app runs on a “stable” Android version. A component update might change notification handling. Another might modify permission behavior. The platform evolves continuously.
Multi-Device Fragmentation
Fragmentation now means more than just OS versions. The device ecosystem exploded:
┌─────────────────────────────────────────────┐ │ │ Wearables │ 2-inch round screens (Wear OS) │ ───────────────│ │ │ │ Phones │ Compact screens (360dp typical) │ ───────────────│ │ │ │ Foldables │ Multiple states: folded → unfolded │ ───────────────│ Screen sizes change during use │ │ │ Tablets │ Medium to large screens (600dp - 900dp) │ ───────────────│ │ │ │ Automotive │ Wide landscape displays │ ───────────────│ Split-screen requirements │ │ │ IoT/TV │ Very large screens, limited input │ ──────────────────────────────────────────────┘Each category has different constraints. Wearables need glanceable UI. Foldables need layouts that adapt when the screen size changes mid-use. Automotive needs landscape-optimized designs with split-screen support.
Performance and Ranking Impact
Apps that don’t adapt face consequences beyond user complaints:
- Poor performance on foldables → Lower visibility- Non-responsive layouts → Negative reviews- Missing automotive support → Limited ecosystem reach- Large monolithic APKs → Longer install times, fewer installsGoogle Play now considers multi-device performance in ranking. Apps that work well across categories get more visibility.
The Solution: Adaptive Architecture
I rebuilt my app with three core principles:
1. Jetpack Libraries for Stability
Jetpack libraries provide backward-compatible behavior that survives platform updates:
┌─────────────────────────────────────────────────────────────────┐│ Your App Code │├─────────────────────────────────────────────────────────────────┤│ Jetpack Libraries ││ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │Activity │ │Fragment │ │Lifecycle │ │ViewModel │ ││ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ││ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │Navigation│ │Room │ │WorkManager│ │DataStore │ ││ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │├─────────────────────────────────────────────────────────────────┤│ Android Platform ││ (Continuous modular updates) │└─────────────────────────────────────────────────────────────────┘Jetpack abstracts platform changes. When Android modifies notification behavior, Jetpack’s WorkManager handles the transition. When lifecycle rules change, Jetpack’s Lifecycle components adapt.
Key libraries I now use:
- Activity/Fragment: Standardized component architecture- Lifecycle/ViewModel: Survive configuration changes (fold/unfold)- Navigation: Handle multi-screen flows across devices- WindowManager: Detect foldable states and postures- Room: Database that works across Android versions2. Window Size Classes for Adaptive Layouts
The old approach of fixed dimensions is broken. I used to write:
<LinearLayout android:layout_width="360dp" android:layout_height="match_parent" android:orientation="vertical">
<TextView android:layout_width="300dp" android:layout_height="wrap_content" android:text="Welcome"/>
<Button android:layout_width="280dp" android:layout_height="48dp" android:text="Continue"/></LinearLayout>This breaks immediately on foldables. When a user unfolds their device, the screen width changes from ~360dp to ~600dp+. The fixed 300dp TextView looks tiny. The 280dp button floats in empty space.
The correct approach uses ConstraintLayout with guidelines:
<androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent">
<!-- Guideline adapts to screen width --> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline_start" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintGuide_percent="0.05" />
<androidx.constraintlayout.widget.Guideline android:id="@+id/guideline_end" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintGuide_percent="0.95" />
<TextView android:id="@+id/title" android:layout_width="0dp" android:layout_height="wrap_content" android:text="Welcome" app:layout_constraintStart_toStartOf="@id/guideline_start" app:layout_constraintEnd_toEndOf="@id/guideline_end" app:layout_constraintTop_toTopOf="parent" />
<Button android:id="@+id/continue_btn" android:layout_width="0dp" android:layout_height="wrap_content" android:text="Continue" app:layout_constraintStart_toStartOf="@id/guideline_start" app:layout_constraintEnd_toEndOf="@id/guideline_end" app:layout_constraintTop_toBottomOf="@id/title" android:layout_marginTop="16dp" /></androidx.constraintlayout.widget.ConstraintLayout>The 0dp width with constraints makes elements fill available space. Guidelines at 5% and 95% create consistent margins regardless of screen size.
But layout alone isn’t enough. Different device categories need different UI structures. Window size classes solve this:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)
val windowSizeClass = calculateWindowSizeClass(this)
when (windowSizeClass.widthSizeClass) { WindowWidthSizeClass.COMPACT -> { // Single column layout for phones // Typical width: 0-599dp setContentView(R.layout.layout_compact) } WindowWidthSizeClass.MEDIUM -> { // Two column layout for tablets/foldables // Typical width: 600-839dp setContentView(R.layout.layout_medium) } WindowWidthSizeClass.EXPANDED -> { // Three column layout for large screens // Typical width: 840dp+ setContentView(R.layout.layout_expanded) } } }}The size class boundaries are meaningful:
COMPACT (0-599dp): - Most phones in portrait - Foldables in folded state - Single column, vertical navigation
MEDIUM (600-839dp): - Tablets in portrait - Foldables in unfolded portrait - Large phones - Two columns possible
EXPANDED (840dp+): - Tablets in landscape - Foldables in unfolded landscape - Desktop-class Chrome OS - Three+ columns, persistent navigationThis approach handles foldable transitions automatically. When a user unfolds their device, the size class changes from COMPACT to MEDIUM. The layout switches accordingly.
3. Modular Feature Delivery
Monolithic APKs create multiple problems:
- Large install size → Users skip install- All features loaded → Memory pressure on low-end devices- Single update cycle → Any change requires full APK rebuild- No device-specific optimization → Wear OS gets phone codeDynamic Feature Modules solve these:
┌─────────────────────────────────────────────┐ │ Base Module │ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │ │ Core UI │ │ Auth │ │ Settings │ │ │ └───────────┘ └───────────┘ └───────────┘ │ │ ┌───────────┐ ┌───────────┐ │ │ │ Navigation│ │ Network │ │ │ └───────────┘ └───────────┘ │ └─────────────────────────────────────────────┘ │ ┌───────────────┼───────────────┐ │ │ │ ┌───────▼───────┐ ┌─────▼─────┐ ┌──────▼──────┐ │ Maps Feature │ │ Chat │ │ Automotive │ │ Module │ │ Module │ │ Module │ └───────────────┘ └───────────┘ └─────────────┘ │ │ │ Download on Download on Only for demand demand Android AutoBenefits:
1. Smaller initial install → More installs2. Device-specific modules → Wear OS doesn't download phone features3. On-demand loading → Features load when user needs them4. Faster updates → Change one module, not entire APKCommon Mistakes I Made
Mistake 1: Testing Only on Phones
WRONG:- Test on Pixel phone- Release to all devices- Users complain about tablet layout
RIGHT:- Test on phone, tablet emulator, foldable emulator- Use Android Studio's Device Manager- Test Automotive in desktop head unit emulator- Test Wear OS on round screen emulatorAndroid Studio provides emulators for every device category. Testing across categories catches layout issues before release.
Mistake 2: Hardcoding Dimensions
WRONG:android:layout_width="360dp"android:padding="16dp"
RIGHT:android:layout_width="match_parent" // or 0dp with constraintsandroid:padding="@dimen/screen_margin" // Define in dimens.xml with qualifiersI now define dimensions in resource files with screen size qualifiers:
<resources> <dimen name="screen_margin">16dp</dimen> <dimen name="card_width">0dp</dimen></resources>
<!-- res/values-w600dp/dimens.xml (medium screens) --><resources> <dimen name="screen_margin">24dp</dimen> <dimen name="card_width">300dp</dimen></resources>
<!-- res/values-w840dp/dimens.xml (large screens) --><resources> <dimen name="screen_margin">32dp</dimen> <dimen name="card_width">400dp</dimen></resources>Mistake 3: Assuming API Stability
WRONG:// Assume this API behavior is stablenotificationManager.notify(id, notification)// Works today, might change next week
RIGHT:// Use Jetpack wrapperNotificationManagerCompat.from(context).notify(id, notification)// Jetpack handles platform changesEvery platform API I use gets wrapped in Jetpack or a compatibility layer.
Mistake 4: Ignoring Foldable State Changes
WRONG:- Layout fixed at onCreate- No handling for screen size changes during use- User unfolds device → layout breaks
RIGHT:- Listen for configuration changes- Use WindowManager library for foldable state- Recalculate size class on device posture changeclass MainActivity : AppCompatActivity() { private val windowManager = WindowManager(this)
override fun onCreate(savedInstanceState: Bundle?) { windowManager.addLayoutChangeListener { layoutInfo -> when (layoutInfo.displayFeatures.find { it is FoldingFeature }) { is FoldingFeature -> { // Device is folded or in tabletop posture updateLayoutForFoldState(layoutInfo) } null -> { // No fold feature, standard display updateLayoutForStandardDisplay() } } } }}Implementation Checklist
I use this checklist before releasing:
Phase 1: Architecture Review[ ] All platform APIs wrapped in Jetpack[ ] No hardcoded dimensions[ ] Configuration change handling implemented[ ] Window size class detection in place
Phase 2: Layout Testing[ ] COMPACT layout verified (phone, folded)[ ] MEDIUM layout verified (tablet portrait, unfolded portrait)[ ] EXPANDED layout verified (tablet landscape, Chrome OS)[ ] Fold state transitions tested[ ] Guidelines and constraints used, not fixed values
Phase 3: Device Category Testing[ ] Phone (multiple sizes)[ ] Foldable (folded and unfolded states)[ ] Tablet (portrait and landscape)[ ] Wear OS (if applicable)[ ] Android Auto (if applicable)
Phase 4: Module Structure[ ] Base module contains only core features[ ] Optional features in dynamic modules[ ] Device-specific modules conditionally delivered[ ] Install size optimizedSummary
Android in 2026 requires a fundamental shift in how we build apps. The platform updates continuously. The device ecosystem spans wearables to automotive. Old assumptions about stable versions and standard phone screens no longer hold.
The solution is adaptive architecture:
- Jetpack libraries abstract platform changes and provide stable behavior
- Window size classes handle layout across screen categories
- Modular feature delivery optimizes for device types and install size
Apps that don’t adapt face user complaints, store ranking penalties, and ecosystem exclusion. Apps built with these principles work across phones, foldables, tablets, wearables, and automotive systems.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 Android Window Size Classes
- 👨💻 Jetpack Libraries Overview
- 👨💻 Dynamic Feature Modules
- 👨💻 ConstraintLayout Guide
- 👨💻 Material Design 3
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments