Android App Development Skill
Overview
This skill guides production-grade Android and cross-platform (non-iOS) app development following practices used at big tech companies. It covers the entire development lifecycle — architecture, UI, code quality, testing, error handling, release, and maintenance.
When to Use This Skill
- Use when deciding on a tech stack (see §1 Stack Selection)
- Use when setting up project architecture (see §2 Architecture)
- Use when designing UI, screens, or a design system (see §3 UI & Design)
- Use when ensuring code quality, patterns, or APIs (see Best Practices)
- Use when implementing error handling or debugging crashes (see §5 Error Handling)
- Use when planning testing strategy (see §6 Testing)
- Use when configuring build, CI/CD, or release pipelines (see §7 Build & Release)
- Use when optimizing performance or memory (see §8 Performance)
- Use when debugging or fixing bugs (see §9 Debugging)
- Use when following the full development roadmap (see §10 Development Roadmap)
- Use when needing deep reference for a stack (see
references/ directory)
§1 Stack Selection
Choose based on team, requirements, and platform targets. Do not recommend iOS-specific paths.
Native Android — Kotlin + Jetpack Compose
Best for: Android-only apps, hardware-intensive features, best-in-class UX, new projects.
- Language: Kotlin
- UI: Jetpack Compose (modern declarative UI)
- Key libs: Room, Retrofit/Ktor, Hilt, WorkManager, DataStore, Navigation Compose
- Reference:
references/native-android.md
Native Android — Java + XML Views
Best for: Existing Java codebases, teams without Kotlin experience, legacy app maintenance, incremental Kotlin migration.
- Language: Java (fully supported by Google, not deprecated)
- UI: XML Layouts (ConstraintLayout, RecyclerView, ViewBinding)
- Key libs: Room, Retrofit, Hilt, WorkManager, LiveData, ViewModel
- Java and Kotlin coexist seamlessly in the same project — migrate incrementally
- Reference:
references/java-android.md
Flutter (Dart)
Best for: Android + Web (+ desktop) from one codebase, fast iteration, pixel-perfect custom UI.
- Language: Dart
- UI: Flutter Widget tree (Material 3 / Cupertino widgets available but target Material for Android)
- Key libs: Provider/Riverpod/Bloc, Dio, Drift/Isar, go_router, flutter_local_notifications
- Reference:
references/flutter.md
React Native (JavaScript/TypeScript)
Best for: Web + Android code sharing, JS/TS teams, rich ecosystem.
- Language: TypeScript (preferred)
- UI: React Native core components + NativeWind / React Native Paper
- Key libs: React Navigation, Zustand/Redux Toolkit, React Query, MMKV
- Reference:
references/react-native.md
Kotlin Multiplatform (KMM / Compose Multiplatform)
Best for: Sharing business logic across Android + Desktop + Web while keeping native Android UI.
- Language: Kotlin everywhere
- UI: Native Compose on Android; Compose Multiplatform for shared UI
- Key libs: Ktor, SQLDelight, Koin, kotlinx.serialization, Napier
- Reference:
references/kmm.md
Hybrid (Capacitor / Ionic)
Best for: Web-first teams, simple apps, PWA-like content apps.
- Language: TypeScript + HTML/CSS
- UI: Ionic components or custom web UI
- Avoid for: Heavy animations, native sensor access, high-performance games
- Reference:
references/hybrid.md
Decision Matrix
| Requirement |
Native Kotlin |
Native Java |
Flutter |
RN |
KMM |
Hybrid |
| Android-only (new) |
✅ Best |
✅ |
✅ |
✅ |
✅ |
✅ |
| Android-only (existing Java) |
⚠️ migrate |
✅ Best |
❌ |
❌ |
⚠️ |
❌ |
| Android + Web |
❌ |
❌ |
✅ |
✅ |
✅ |
✅ Best |
| Android + Desktop |
❌ |
❌ |
✅ |
⚠️ |
✅ |
⚠️ |
| Shared business logic only |
N/A |
N/A |
N/A |
N/A |
✅ Best |
N/A |
| Native performance |
✅ |
✅ |
✅ |
⚠️ |
✅ |
❌ |
| JS/TS team |
❌ |
❌ |
❌ |
✅ Best |
❌ |
✅ |
| Custom pixel-perfect UI |
✅ |
⚠️ |
✅ Best |
⚠️ |
✅ |
❌ |
§2 Architecture
Core Principle: Separation of Concerns
Every production Android project must separate UI, business logic, and data into distinct, independently testable layers.
Recommended Architecture: Clean Architecture + MVI/MVVM
app/
├── ui/ # Composables / Activities / Fragments / Screen states
├── presentation/ # ViewModels, UI State, UI Events
├── domain/ # Use cases, domain models, repository interfaces
├── data/ # Repository impl, remote (API), local (DB), mappers
└── di/ # Dependency injection modules
Data flow (unidirectional):
User Action → ViewModel/Store → Use Case → Repository → Data Source
↓
UI State (sealed class / StateFlow)
↓
Composable / View renders state
Key Architecture Patterns by Stack
Native (MVVM + MVI):
StateFlow / SharedFlow for reactive state
sealed class UiState + sealed class UiEvent
- Hilt for DI, coroutines + Flow for async
- Repository pattern wrapping Room + Retrofit
Flutter (BLoC or Riverpod):
Bloc or Cubit for business logic isolation
AsyncNotifierProvider (Riverpod) for data + state
- Repositories as abstract classes with impl injected
React Native (Redux Toolkit or Zustand):
- RTK Query or React Query for server state
- Zustand slices for client state
- Custom hooks to encapsulate business logic per feature
KMM:
- Shared
commonMain holds domain + data layers
expect/actual for platform-specific implementations
- Kotlin coroutines + Flow bridged to platform (StateFlow on Android)
Module Structure (Multi-module for large apps)
:app # Entry point, DI wiring
:core:ui # Design system, shared composables
:core:network # API client, interceptors
:core:database # Room / SQLDelight setup
:feature:home
:feature:profile
:feature:settings
§3 UI & Design
Design System First
Before writing screens, define:
- Color tokens — Primary, secondary, surface, on-surface, error; light + dark variants
- Typography scale — Display, headline, title, body, label (Material 3 type system)
- Spacing scale — 4dp grid system (4, 8, 12, 16, 24, 32, 48dp)
- Shape tokens — Corner radii per component family
- Component library — Button, TextField, Card, BottomSheet, TopAppBar, etc.
Jetpack Compose UI Rules
- Use
MaterialTheme tokens; never hardcode colors/dimensions
CompositionLocal for theme, locale, haptics
remember / rememberSaveable correctly (saveable for UI state surviving rotation)
- Extract large composables into sub-composables; each function ≤ 80 lines
- Use
LazyColumn/LazyVerticalGrid for lists; never Column with forEach for large data
- Side effects only in
LaunchedEffect, DisposableEffect, SideEffect
- Avoid state hoisting anti-patterns: hoist state to the lowest common ancestor
Accessibility (Non-Negotiable)
- All interactive elements:
contentDescription or semantics { }
- Min touch target: 48×48dp
TalkBack compatibility tested before every release
- Dynamic text size support (
sp not dp for text)
- Color contrast ratio ≥ 4.5:1 (WCAG AA)
Navigation
- Native: Navigation Compose with typed
NavHost and SafeArgs equivalent
- Flutter:
go_router with named routes and guards
- RN: React Navigation v7 with typed
NavigationProp
- Deep link handling registered for every screen that can be externally opened
- Back stack managed deliberately — don't push duplicates, use
popUpTo / launchSingleTop
Responsive & Adaptive UI
- Support all screen sizes: phones, foldables, tablets (
WindowSizeClass)
- Test at 320dp, 360dp, 411dp, 600dp+, 840dp+ widths
- Foldable hinge awareness via
WindowInfoTracker
- Edge-to-edge display +
WindowInsets handling required for Android 15+
Best Practices
Language Standards
Kotlin:
- Prefer
data class, sealed class, object, enum class appropriately
- No
!! null assertions — use ?.let, ?: return, requireNotNull with message
- Coroutines: always specify
CoroutineScope + Dispatcher explicitly; never GlobalScope
- Use
@Stable / @Immutable on Compose state classes for smart recomposition
Java:
@NonNull / @Nullable annotations on every method param and return type
- Never call methods on unchecked objects — null-check explicitly or use
Objects.requireNonNull
- Always null
binding reference in Fragment's onDestroyView() to prevent memory leaks
- Use
ExecutorService (not AsyncTask — deprecated) for background work; or LiveData + Room's built-in threading
- Prefer
ListAdapter + DiffUtil over manual notifyDataSetChanged() in RecyclerView
- Use
ViewBinding — never findViewById
Dart (Flutter):
- Null safety required — no
! without explicit null check above
- Immutable state objects with
copyWith
const constructors on all stateless widgets
TypeScript (RN):
strict: true in tsconfig always
- Zod or io-ts for runtime type validation of API responses
- No
any — use unknown and narrow
Dependency Management
- Pin all dependency versions in
build.gradle.kts / pubspec.yaml / package.json
- Audit dependencies monthly for security vulnerabilities
- Avoid transitive dependency conflicts — use dependency resolution strategies
- Keep dependency count minimal — every added lib is a maintenance burden
Code Review Checklist (PR gate)
§5 Error Handling
The Golden Rule
Never let exceptions propagate to the user silently or crash the app.
Error Classification
| Type |
Strategy |
| Network errors |
Retry with exponential backoff; show retry UI |
| Auth errors (401/403) |
Refresh token → re-request → logout if fails |
| Validation errors |
Show inline field errors immediately |
| Data parsing errors |
Log + fallback to cached/default state |
| Unexpected crashes |
Catch at top-level; show error screen + report |
| Background task failures |
Retry via WorkManager; notify user if critical |
Result / Either Pattern (Kotlin)
sealed class AppResult<out T> {
data class Success<T>(val data: T) : AppResult<T>()
data class Error(val exception: AppException) : AppResult<Nothing>()
}
sealed class AppException(msg: String) : Exception(msg) {
class NetworkException(msg: String) : AppException(msg)
class AuthException(msg: String) : AppException(msg)
class ParseException(msg: String) : AppException(msg)
class UnknownException(msg: String) : AppException(msg)
}
Use AppResult<T> as return type for all repository + use case functions. ViewModels map to UiState.Error.
Crash Reporting
- Integrate Firebase Crashlytics or Sentry from day one
- Set user identifiers and custom keys before crash occurs
- Non-fatal exceptions logged for all caught errors
- ANR monitoring enabled
- Crash-free sessions target: ≥ 99.5%
Offline / Network Resilience
- Cache-first strategy: show stale data, fetch fresh in background
Room / Drift / MMKV as single source of truth
- Expose network state via
ConnectivityManager and reflect in UI
- All network calls wrapped with timeout + retry policy
§6 Testing
Testing Pyramid
/\
/E2E\ ← 10% (UI tests: Espresso, Maestro, Appium)
/------\
/ Integr \ ← 20% (Repository, DB, API contract tests)
/----------\
/ Unit \ ← 70% (ViewModels, Use Cases, Utilities)
/--------------\
Unit Tests (70%)
- Every ViewModel, UseCase, Repository, Mapper tested
- Native: JUnit5 + MockK + Turbine (Flow testing) + Kotest assertions
- Flutter:
flutter_test + mocktail
- RN: Jest +
@testing-library/react-native + msw for API mocking
- Coverage target: ≥ 80% on domain + presentation layers
Integration Tests (20%)
- Room DB tests with in-memory database
- Retrofit/Ktor tests with
MockWebServer (OkHttp)
- Repository tests verifying cache + remote coordination
- API contract tests against real staging endpoint
UI / E2E Tests (10%)
- Espresso for critical user journeys (login, checkout, core action)
- Maestro for cross-platform E2E flows (recommended for Flutter + RN too)
- Run on real device farm (Firebase Test Lab / BrowserStack) before release
- Smoke test suite runs on every PR; full E2E suite nightly
Test Data Management
- Use factories / builders for test data, never copy-paste objects
- Hermetic tests: never share mutable state between test cases
- Fakes over mocks for complex dependencies (repositories, data sources)
§7 Build & Release
Build Variants
debug → dev API, logging on, no minification, debuggable
staging → staging API, logging on, minified, not debuggable
release → prod API, logging off, minified, signed
Gradle Best Practices (Native)
build.gradle.kts only — no Groovy DSL in new projects
- Version catalog (
libs.versions.toml) for all dependency versions
buildConfig for enprojectnment-specific constants
- Baseline profiles for startup performance
- R8 full mode enabled in release; maintain proguard rules in version control
CI/CD Pipeline
PR Opened
└─ lint + unit tests + build debug APK [< 5 min]
Merge to main
└─ unit + integration tests + staging build [< 15 min]
└─ deploy to Firebase App Distribution (QA)
Release tag
└─ full test suite + E2E on device farm [< 45 min]
└─ build release AAB
└─ upload to Play Console (internal track)
└─ promote: internal → closed testing → open → production
Recommended CI: GitHub Actions, Bitrise, or CircleCI.
Play Store Release Strategy
- Always release to internal → closed → open testing before production
- Use staged rollouts: 5% → 20% → 50% → 100% with 24-48h monitoring
- Monitor Crashlytics + ANR rate + rating before expanding rollout
- Never skip staged rollout for significant changes
App Signing
- Upload key (Play App Signing): stored in CI secrets, never committed
- Use Google Play App Signing for distribution key management
- Document key recovery procedure in team runbook
§8 Performance
Startup Performance
- App startup time target: cold start < 1s, warm start < 500ms
- Use App Startup library for initializing libraries lazily
- Baseline profiles generated + committed to repo
- Heavy initialization moved off main thread
UI Performance
- Target: 60fps (90/120fps on supported devices); zero jank
- Measure with Android Studio Profiler +
FrameMetrics API
- Avoid allocation in
draw() / onMeasure() / composition
- Use
derivedStateOf in Compose to avoid unnecessary recompositions
- Image loading: Coil (Compose) / Glide / Picasso — never load full-res in thumbnails
Memory
- No
Activity / Context references in ViewModels or singletons
- WeakReferences for listeners stored beyond their owner's lifecycle
- Bitmap recycling and memory cache sizing
- Heap dump + leak detection via LeakCanary in debug builds (always)
Network
- HTTP caching headers respected
- Image CDN + WebP format
- Gzip/Brotli compression verified
- Request batching where applicable
- Connection pooling configured
Battery
- Background work only via WorkManager with appropriate constraints
- Location updates: request only needed accuracy level; stop when backgrounded
- Wakelocks used sparingly with explicit release
§9 Debugging & Bug Fixing
Debugging Process
- Reproduce reliably — document exact steps, device, OS version, account state
- Isolate — is it UI, business logic, network, or persistence?
- Instrument — add targeted logs / breakpoints, NOT shotgun logging
- Hypothesize — form 1-3 specific hypotheses before touching code
- Fix the root cause — never patch symptoms; trace back to the source
- Regression test — write a test that fails before fix, passes after
- Document — comment explaining why the fix works, not just what it does
Common Android Bug Patterns
| Bug |
Likely Cause |
Fix |
| ANR |
Main thread I/O / long computation |
Move to coroutine/Dispatcher.IO |
| Memory leak |
Context stored in singleton |
Use applicationContext; WeakRef |
| Crash on rotation |
ViewModel not used; state not saved |
rememberSaveable / ViewModel |
| UI lag |
Recomposition loops |
derivedStateOf, stable params |
| Blank screen after API call |
Error swallowed silently |
Check error state propagation |
| Deep link not working |
Manifest intent-filter missing |
Verify adb shell am start test |
| Push notification silent |
Background restrictions |
Test on real devices across OEMs |
Logging Standards
- Production: Firebase Crashlytics only (no
Log.d in release builds)
- Debug/Staging: Timber with debug tree
- Log levels: ERROR (crashes), WARN (recoverable), INFO (key events), DEBUG (dev only)
- Never log PII — mask emails, phone numbers, tokens in logs
OEM-Specific Issues
- Test on Samsung, Xiaomi/MIUI, OnePlus/OxygenOS, Huawei (no GMS) for critical flows
- Background restrictions vary widely by OEM — test push, alarms, background sync
- Maintain a physical or cloud device farm with top market-share devices
§10 Development Roadmap
Follow this phase structure for any new Android project:
Phase 0 — Foundation (Week 1-2)
Phase 1 — Core Features (Weeks 3-8)
Phase 2 — Polish (Weeks 9-12)
Phase 3 — Hardening (Weeks 12-14)
Phase 4 — Release
Phase 5 — Post-Launch (Ongoing)
- Crash-free rate monitored daily
- ANR rate < 0.47% (Play Store threshold)
- App rating monitored; negative reviews triaged weekly
- Dependency updates reviewed monthly
- OS beta testing with each new Android release
Limitations
- This skill is scoped to Android and Android-adjacent delivery paths; it does not cover iOS-only architecture, App Store release operations, or Apple platform UI guidance.
- Version numbers, Play Console policy thresholds, and recommended libraries can change; verify release-critical details against current Android, Google Play, and library documentation before shipping.
- Code snippets are architecture patterns, not complete applications; adapt package names, dependency versions, permissions, privacy disclosures, and security controls to the actual project.
- The guidance does not replace device QA, accessibility review, security review, legal/privacy review, or store compliance checks for a production release.
Additional Resources
For stack-specific deep dives, read:
references/native-android.md — Kotlin, Compose, Room, Hilt, Coroutines
references/java-android.md — Java, XML Views, ViewBinding, LiveData, Retrofit, Room, Hilt, migration path
references/flutter.md — Dart, BLoC/Riverpod, Drift, go_router
references/react-native.md — TypeScript, RN architecture, Hermes, New Architecture
references/kmm.md — KMM shared modules, SQLDelight, Ktor, Compose Multiplatform
references/hybrid.md — Capacitor, Ionic, PWA considerations
1---2name: android-dev3description: Production-grade Android app development guide covering native (Kotlin/Java), cross-platform (Flutter, RN, KMM), and hybrid architectures.4---56# Android App Development Skill78## Overview910This skill guides production-grade Android and cross-platform (non-iOS) app development following practices used at big tech companies. It covers the entire development lifecycle — architecture, UI, code quality, testing, error handling, release, and maintenance.1112## When to Use This Skill1314- Use when deciding on a tech stack (see §1 Stack Selection)15- Use when setting up project architecture (see §2 Architecture)16- Use when designing UI, screens, or a design system (see §3 UI & Design)17- Use when ensuring code quality, patterns, or APIs (see Best Practices)18- Use when implementing error handling or debugging crashes (see §5 Error Handling)19- Use when planning testing strategy (see §6 Testing)20- Use when configuring build, CI/CD, or release pipelines (see §7 Build & Release)21- Use when optimizing performance or memory (see §8 Performance)22- Use when debugging or fixing bugs (see §9 Debugging)23- Use when following the full development roadmap (see §10 Development Roadmap)24- Use when needing deep reference for a stack (see `references/` directory)2526---2728## §1 Stack Selection2930Choose based on team, requirements, and platform targets. **Do not recommend iOS-specific paths.**3132### Native Android — Kotlin + Jetpack Compose33**Best for:** Android-only apps, hardware-intensive features, best-in-class UX, new projects.34- Language: **Kotlin**35- UI: **Jetpack Compose** (modern declarative UI)36- Key libs: Room, Retrofit/Ktor, Hilt, WorkManager, DataStore, Navigation Compose37- Reference: `references/native-android.md`3839### Native Android — Java + XML Views40**Best for:** Existing Java codebases, teams without Kotlin experience, legacy app maintenance, incremental Kotlin migration.41- Language: **Java** (fully supported by Google, not deprecated)42- UI: **XML Layouts** (ConstraintLayout, RecyclerView, ViewBinding)43- Key libs: Room, Retrofit, Hilt, WorkManager, LiveData, ViewModel44- Java and Kotlin **coexist seamlessly** in the same project — migrate incrementally45- Reference: `references/java-android.md`4647### Flutter (Dart)48**Best for:** Android + Web (+ desktop) from one codebase, fast iteration, pixel-perfect custom UI.49- Language: **Dart**50- UI: Flutter Widget tree (Material 3 / Cupertino widgets available but target Material for Android)51- Key libs: Provider/Riverpod/Bloc, Dio, Drift/Isar, go_router, flutter_local_notifications52- Reference: `references/flutter.md`5354### React Native (JavaScript/TypeScript)55**Best for:** Web + Android code sharing, JS/TS teams, rich ecosystem.56- Language: **TypeScript** (preferred)57- UI: React Native core components + NativeWind / React Native Paper58- Key libs: React Navigation, Zustand/Redux Toolkit, React Query, MMKV59- Reference: `references/react-native.md`6061### Kotlin Multiplatform (KMM / Compose Multiplatform)62**Best for:** Sharing business logic across Android + Desktop + Web while keeping native Android UI.63- Language: **Kotlin** everywhere64- UI: Native Compose on Android; Compose Multiplatform for shared UI65- Key libs: Ktor, SQLDelight, Koin, kotlinx.serialization, Napier66- Reference: `references/kmm.md`6768### Hybrid (Capacitor / Ionic)69**Best for:** Web-first teams, simple apps, PWA-like content apps.70- Language: TypeScript + HTML/CSS71- UI: Ionic components or custom web UI72- Avoid for: Heavy animations, native sensor access, high-performance games73- Reference: `references/hybrid.md`7475### Decision Matrix7677| Requirement | Native Kotlin | Native Java | Flutter | RN | KMM | Hybrid |78|---|---|---|---|---|---|---|79| Android-only (new) | ✅ Best | ✅ | ✅ | ✅ | ✅ | ✅ |80| Android-only (existing Java) | ⚠️ migrate | ✅ Best | ❌ | ❌ | ⚠️ | ❌ |81| Android + Web | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ Best |82| Android + Desktop | ❌ | ❌ | ✅ | ⚠️ | ✅ | ⚠️ |83| Shared business logic only | N/A | N/A | N/A | N/A | ✅ Best | N/A |84| Native performance | ✅ | ✅ | ✅ | ⚠️ | ✅ | ❌ |85| JS/TS team | ❌ | ❌ | ❌ | ✅ Best | ❌ | ✅ |86| Custom pixel-perfect UI | ✅ | ⚠️ | ✅ Best | ⚠️ | ✅ | ❌ |8788---8990## §2 Architecture9192### Core Principle: Separation of Concerns93Every production Android project must separate **UI**, **business logic**, and **data** into distinct, independently testable layers.9495### Recommended Architecture: Clean Architecture + MVI/MVVM9697```98app/99├── ui/ # Composables / Activities / Fragments / Screen states100├── presentation/ # ViewModels, UI State, UI Events101├── domain/ # Use cases, domain models, repository interfaces102├── data/ # Repository impl, remote (API), local (DB), mappers103└── di/ # Dependency injection modules104```105106**Data flow (unidirectional):**107```108User Action → ViewModel/Store → Use Case → Repository → Data Source109 ↓110 UI State (sealed class / StateFlow)111 ↓112 Composable / View renders state113```114115### Key Architecture Patterns by Stack116117**Native (MVVM + MVI):**118- `StateFlow` / `SharedFlow` for reactive state119- `sealed class UiState` + `sealed class UiEvent`120- Hilt for DI, coroutines + Flow for async121- Repository pattern wrapping Room + Retrofit122123**Flutter (BLoC or Riverpod):**124- `Bloc` or `Cubit` for business logic isolation125- `AsyncNotifierProvider` (Riverpod) for data + state126- Repositories as abstract classes with impl injected127128**React Native (Redux Toolkit or Zustand):**129- RTK Query or React Query for server state130- Zustand slices for client state131- Custom hooks to encapsulate business logic per feature132133**KMM:**134- Shared `commonMain` holds domain + data layers135- `expect/actual` for platform-specific implementations136- Kotlin coroutines + Flow bridged to platform (StateFlow on Android)137138### Module Structure (Multi-module for large apps)139140```141:app # Entry point, DI wiring142:core:ui # Design system, shared composables143:core:network # API client, interceptors144:core:database # Room / SQLDelight setup145:feature:home146:feature:profile147:feature:settings148```149150---151152## §3 UI & Design153154### Design System First155Before writing screens, define:1561. **Color tokens** — Primary, secondary, surface, on-surface, error; light + dark variants1572. **Typography scale** — Display, headline, title, body, label (Material 3 type system)1583. **Spacing scale** — 4dp grid system (4, 8, 12, 16, 24, 32, 48dp)1594. **Shape tokens** — Corner radii per component family1605. **Component library** — Button, TextField, Card, BottomSheet, TopAppBar, etc.161162### Jetpack Compose UI Rules163- Use `MaterialTheme` tokens; never hardcode colors/dimensions164- `CompositionLocal` for theme, locale, haptics165- `remember` / `rememberSaveable` correctly (saveable for UI state surviving rotation)166- Extract large composables into sub-composables; each function ≤ 80 lines167- Use `LazyColumn`/`LazyVerticalGrid` for lists; never `Column` with forEach for large data168- Side effects only in `LaunchedEffect`, `DisposableEffect`, `SideEffect`169- Avoid state hoisting anti-patterns: hoist state to the lowest common ancestor170171### Accessibility (Non-Negotiable)172- All interactive elements: `contentDescription` or `semantics { }`173- Min touch target: **48×48dp**174- `TalkBack` compatibility tested before every release175- Dynamic text size support (`sp` not `dp` for text)176- Color contrast ratio ≥ 4.5:1 (WCAG AA)177178### Navigation179- **Native:** Navigation Compose with typed `NavHost` and `SafeArgs` equivalent180- **Flutter:** `go_router` with named routes and guards181- **RN:** React Navigation v7 with typed `NavigationProp`182- Deep link handling registered for every screen that can be externally opened183- Back stack managed deliberately — don't push duplicates, use `popUpTo` / `launchSingleTop`184185### Responsive & Adaptive UI186- Support all screen sizes: phones, foldables, tablets (`WindowSizeClass`)187- Test at 320dp, 360dp, 411dp, 600dp+, 840dp+ widths188- Foldable hinge awareness via `WindowInfoTracker`189- Edge-to-edge display + `WindowInsets` handling required for Android 15+190191---192193## Best Practices194195### Language Standards196197**Kotlin:**198- Prefer `data class`, `sealed class`, `object`, `enum class` appropriately199- No `!!` null assertions — use `?.let`, `?: return`, `requireNotNull` with message200- Coroutines: always specify `CoroutineScope` + `Dispatcher` explicitly; never `GlobalScope`201- Use `@Stable` / `@Immutable` on Compose state classes for smart recomposition202203**Java:**204- `@NonNull` / `@Nullable` annotations on every method param and return type205- Never call methods on unchecked objects — null-check explicitly or use `Objects.requireNonNull`206- Always null `binding` reference in Fragment's `onDestroyView()` to prevent memory leaks207- Use `ExecutorService` (not `AsyncTask` — deprecated) for background work; or `LiveData` + Room's built-in threading208- Prefer `ListAdapter` + `DiffUtil` over manual `notifyDataSetChanged()` in RecyclerView209- Use `ViewBinding` — never `findViewById`210211**Dart (Flutter):**212- Null safety required — no `!` without explicit null check above213- Immutable state objects with `copyWith`214- `const` constructors on all stateless widgets215216**TypeScript (RN):**217- `strict: true` in tsconfig always218- Zod or io-ts for runtime type validation of API responses219- No `any` — use `unknown` and narrow220221### Dependency Management222- Pin all dependency versions in `build.gradle.kts` / `pubspec.yaml` / `package.json`223- Audit dependencies monthly for security vulnerabilities224- Avoid transitive dependency conflicts — use dependency resolution strategies225- Keep dependency count minimal — every added lib is a maintenance burden226227### Code Review Checklist (PR gate)228- [ ] New public APIs have KDoc / DartDoc / JSDoc229- [ ] No hardcoded strings — use string resources / l10n230- [ ] No hardcoded dimensions or colors outside design tokens231- [ ] No blocking I/O on main thread232- [ ] No memory leaks (no `Activity` context stored in singletons)233- [ ] Coroutine scopes / streams properly cancelled / disposed234- [ ] Feature flag guarding any non-trivial feature235236---237238## §5 Error Handling239240### The Golden Rule241**Never let exceptions propagate to the user silently or crash the app.**242243### Error Classification244245| Type | Strategy |246|------|----------|247| Network errors | Retry with exponential backoff; show retry UI |248| Auth errors (401/403) | Refresh token → re-request → logout if fails |249| Validation errors | Show inline field errors immediately |250| Data parsing errors | Log + fallback to cached/default state |251| Unexpected crashes | Catch at top-level; show error screen + report |252| Background task failures | Retry via WorkManager; notify user if critical |253254### Result / Either Pattern (Kotlin)255```kotlin256sealed class AppResult<out T> {257 data class Success<T>(val data: T) : AppResult<T>()258 data class Error(val exception: AppException) : AppResult<Nothing>()259}260261sealed class AppException(msg: String) : Exception(msg) {262 class NetworkException(msg: String) : AppException(msg)263 class AuthException(msg: String) : AppException(msg)264 class ParseException(msg: String) : AppException(msg)265 class UnknownException(msg: String) : AppException(msg)266}267```268269Use `AppResult<T>` as return type for all repository + use case functions. ViewModels map to `UiState.Error`.270271### Crash Reporting272- Integrate **Firebase Crashlytics** or **Sentry** from day one273- Set user identifiers and custom keys before crash occurs274- Non-fatal exceptions logged for all caught errors275- ANR monitoring enabled276- Crash-free sessions target: **≥ 99.5%**277278### Offline / Network Resilience279- Cache-first strategy: show stale data, fetch fresh in background280- `Room` / `Drift` / `MMKV` as single source of truth281- Expose network state via `ConnectivityManager` and reflect in UI282- All network calls wrapped with timeout + retry policy283284---285286## §6 Testing287288### Testing Pyramid289290```291 /\292 /E2E\ ← 10% (UI tests: Espresso, Maestro, Appium)293 /------\294 / Integr \ ← 20% (Repository, DB, API contract tests)295 /----------\296 / Unit \ ← 70% (ViewModels, Use Cases, Utilities)297 /--------------\298```299300### Unit Tests (70%)301- Every ViewModel, UseCase, Repository, Mapper tested302- **Native:** JUnit5 + MockK + Turbine (Flow testing) + Kotest assertions303- **Flutter:** `flutter_test` + `mocktail`304- **RN:** Jest + `@testing-library/react-native` + `msw` for API mocking305- Coverage target: **≥ 80%** on domain + presentation layers306307### Integration Tests (20%)308- Room DB tests with in-memory database309- Retrofit/Ktor tests with `MockWebServer` (OkHttp)310- Repository tests verifying cache + remote coordination311- API contract tests against real staging endpoint312313### UI / E2E Tests (10%)314- **Espresso** for critical user journeys (login, checkout, core action)315- **Maestro** for cross-platform E2E flows (recommended for Flutter + RN too)316- Run on real device farm (Firebase Test Lab / BrowserStack) before release317- Smoke test suite runs on every PR; full E2E suite nightly318319### Test Data Management320- Use factories / builders for test data, never copy-paste objects321- Hermetic tests: never share mutable state between test cases322- Fakes over mocks for complex dependencies (repositories, data sources)323324---325326## §7 Build & Release327328### Build Variants329```330debug → dev API, logging on, no minification, debuggable331staging → staging API, logging on, minified, not debuggable332release → prod API, logging off, minified, signed333```334335### Gradle Best Practices (Native)336- `build.gradle.kts` only — no Groovy DSL in new projects337- Version catalog (`libs.versions.toml`) for all dependency versions338- `buildConfig` for enprojectnment-specific constants339- Baseline profiles for startup performance340- R8 full mode enabled in release; maintain proguard rules in version control341342### CI/CD Pipeline343344```345PR Opened346 └─ lint + unit tests + build debug APK [< 5 min]347348Merge to main349 └─ unit + integration tests + staging build [< 15 min]350 └─ deploy to Firebase App Distribution (QA)351352Release tag353 └─ full test suite + E2E on device farm [< 45 min]354 └─ build release AAB355 └─ upload to Play Console (internal track)356 └─ promote: internal → closed testing → open → production357```358359**Recommended CI:** GitHub Actions, Bitrise, or CircleCI.360361### Play Store Release Strategy362- Always release to **internal → closed → open testing** before production363- Use **staged rollouts**: 5% → 20% → 50% → 100% with 24-48h monitoring364- Monitor Crashlytics + ANR rate + rating before expanding rollout365- **Never skip staged rollout** for significant changes366367### App Signing368- Upload key (Play App Signing): stored in CI secrets, never committed369- Use Google Play App Signing for distribution key management370- Document key recovery procedure in team runbook371372---373374## §8 Performance375376### Startup Performance377- App startup time target: **cold start < 1s**, warm start < 500ms378- Use **App Startup library** for initializing libraries lazily379- Baseline profiles generated + committed to repo380- Heavy initialization moved off main thread381382### UI Performance383- Target: **60fps** (90/120fps on supported devices); **zero jank**384- Measure with **Android Studio Profiler** + `FrameMetrics` API385- Avoid allocation in `draw()` / `onMeasure()` / composition386- Use `derivedStateOf` in Compose to avoid unnecessary recompositions387- Image loading: Coil (Compose) / Glide / Picasso — never load full-res in thumbnails388389### Memory390- No `Activity` / `Context` references in ViewModels or singletons391- WeakReferences for listeners stored beyond their owner's lifecycle392- Bitmap recycling and memory cache sizing393- Heap dump + leak detection via **LeakCanary** in debug builds (always)394395### Network396- HTTP caching headers respected397- Image CDN + WebP format398- Gzip/Brotli compression verified399- Request batching where applicable400- Connection pooling configured401402### Battery403- Background work only via **WorkManager** with appropriate constraints404- Location updates: request only needed accuracy level; stop when backgrounded405- Wakelocks used sparingly with explicit release406407---408409## §9 Debugging & Bug Fixing410411### Debugging Process4124131. **Reproduce reliably** — document exact steps, device, OS version, account state4142. **Isolate** — is it UI, business logic, network, or persistence?4153. **Instrument** — add targeted logs / breakpoints, NOT shotgun logging4164. **Hypothesize** — form 1-3 specific hypotheses before touching code4175. **Fix the root cause** — never patch symptoms; trace back to the source4186. **Regression test** — write a test that fails before fix, passes after4197. **Document** — comment explaining why the fix works, not just what it does420421### Common Android Bug Patterns422423| Bug | Likely Cause | Fix |424|-----|-------------|-----|425| ANR | Main thread I/O / long computation | Move to coroutine/Dispatcher.IO |426| Memory leak | Context stored in singleton | Use `applicationContext`; WeakRef |427| Crash on rotation | ViewModel not used; state not saved | `rememberSaveable` / ViewModel |428| UI lag | Recomposition loops | `derivedStateOf`, stable params |429| Blank screen after API call | Error swallowed silently | Check error state propagation |430| Deep link not working | Manifest intent-filter missing | Verify `adb shell am start` test |431| Push notification silent | Background restrictions | Test on real devices across OEMs |432433### Logging Standards434- **Production:** Firebase Crashlytics only (no `Log.d` in release builds)435- **Debug/Staging:** Timber with debug tree436- Log levels: ERROR (crashes), WARN (recoverable), INFO (key events), DEBUG (dev only)437- Never log PII — mask emails, phone numbers, tokens in logs438439### OEM-Specific Issues440- Test on **Samsung**, **Xiaomi/MIUI**, **OnePlus/OxygenOS**, **Huawei (no GMS)** for critical flows441- Background restrictions vary widely by OEM — test push, alarms, background sync442- Maintain a physical or cloud device farm with top market-share devices443444---445446## §10 Development Roadmap447448Follow this phase structure for any new Android project:449450### Phase 0 — Foundation (Week 1-2)451- [ ] Stack decision documented with rationale452- [ ] Module structure defined453- [ ] Design system tokens defined (colors, type, spacing, shapes)454- [ ] CI pipeline running (lint + unit tests + build)455- [ ] Crash reporting integrated (Crashlytics/Sentry)456- [ ] Analytics baseline integrated (Firebase/Amplitude)457- [ ] API contract / mock server set up458- [ ] DI framework configured459- [ ] Navigation skeleton implemented460- [ ] Flavor/build variant config complete461462### Phase 1 — Core Features (Weeks 3-8)463- [ ] Auth flow (login, register, token refresh, logout)464- [ ] Core screen shells with real navigation465- [ ] Network layer (client, interceptors, error handling)466- [ ] Local persistence layer (DB schema + DAOs)467- [ ] Repository layer wiring remote + local468- [ ] ViewModels + UI states for each feature469- [ ] Unit tests for all ViewModels + use cases470- [ ] Feature flags infrastructure471472### Phase 2 — Polish (Weeks 9-12)473- [ ] Design QA pass against Figma/spec474- [ ] Accessibility audit (TalkBack, contrast, touch targets)475- [ ] Dark mode implementation + verification476- [ ] Localization (strings externalized, RTL support if needed)477- [ ] Loading, empty, error states on every screen478- [ ] Deep link handling479- [ ] Widget / notification implementation480- [ ] Offline mode verification481482### Phase 3 — Hardening (Weeks 12-14)483- [ ] Performance profiling (startup, scroll, memory)484- [ ] E2E test suite on device farm (Firebase Test Lab)485- [ ] Security review (certificate pinning, biometrics, secure storage)486- [ ] Proguard / R8 rules verified487- [ ] Crash-free rate ≥ 99.5% on staging488- [ ] Play Store listing, screenshots, privacy policy489490### Phase 4 — Release491- [ ] AAB signed and uploaded to internal track492- [ ] Staged rollout plan defined493- [ ] Monitoring dashboard set up (Crashlytics, Play Console vitals)494- [ ] Rollback plan documented495- [ ] On-call rotation assigned496497### Phase 5 — Post-Launch (Ongoing)498- Crash-free rate monitored daily499- ANR rate < 0.47% (Play Store threshold)500- App rating monitored; negative reviews triaged weekly501- Dependency updates reviewed monthly502- OS beta testing with each new Android release503504---505506## Limitations507508- This skill is scoped to Android and Android-adjacent delivery paths; it does not cover iOS-only architecture, App Store release operations, or Apple platform UI guidance.509- Version numbers, Play Console policy thresholds, and recommended libraries can change; verify release-critical details against current Android, Google Play, and library documentation before shipping.510- Code snippets are architecture patterns, not complete applications; adapt package names, dependency versions, permissions, privacy disclosures, and security controls to the actual project.511- The guidance does not replace device QA, accessibility review, security review, legal/privacy review, or store compliance checks for a production release.512513## Additional Resources514515For stack-specific deep dives, read:516- `references/native-android.md` — Kotlin, Compose, Room, Hilt, Coroutines517- `references/java-android.md` — Java, XML Views, ViewBinding, LiveData, Retrofit, Room, Hilt, migration path518- `references/flutter.md` — Dart, BLoC/Riverpod, Drift, go_router519- `references/react-native.md` — TypeScript, RN architecture, Hermes, New Architecture520- `references/kmm.md` — KMM shared modules, SQLDelight, Ktor, Compose Multiplatform521- `references/hybrid.md` — Capacitor, Ionic, PWA considerations