Skip to main content

android-dev

Production-grade Android app development guide covering native (Kotlin/Java), cross-platform (Flutter, RN, KMM), and hybrid architectures.

Jump to install

Source facts

Repository
ARareUsername/tbats-dev
Last source activity
July 12, 2026 at 11:51
Detected SKILL.md language
English
Stars
2
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
7 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
android-dev
description
Production-grade Android app development guide covering native (Kotlin/Java), cross-platform (Flutter, RN, KMM), and hybrid architectures.
risk
safe
source
community
date_added
2026-06-08
# 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: 1. **Color tokens** — Primary, secondary, surface, on-surface, error; light + dark variants 2. **Typography scale** — Display, headline, title, body, label (Material 3 type system) 3. **Spacing scale** — 4dp grid system (4, 8, 12, 16, 24, 32, 48dp) 4. **Shape tokens** — Corner radii per component family 5. **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) - [ ] New public APIs have KDoc / DartDoc / JSDoc - [ ] No hardcoded strings — use string resources / l10n - [ ] No hardcoded dimensions or colors outside design tokens - [ ] No blocking I/O on main thread - [ ] No memory leaks (no `Activity` context stored in singletons) - [ ] Coroutine scopes / streams properly cancelled / disposed - [ ] Feature flag guarding any non-trivial feature --- ## §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) ```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 environment-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
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub