Production-grade Android app development guide covering native (Kotlin/Java), cross-platform (Flutter, RN, KMM), and hybrid architectures.
npx skills add https://github.com/lingxling/awesome-skills-cn --skill android-dev
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.
references/ directory)Choose based on team, requirements, and platform targets. Do not recommend iOS-specific paths.
Best for: Android-only apps, hardware-intensive features, best-in-class UX, new projects.
references/native-android.mdBest for: Existing Java codebases, teams without Kotlin experience, legacy app maintenance, incremental Kotlin migration.
references/java-android.mdBest for: Android + Web (+ desktop) from one codebase, fast iteration, pixel-perfect custom UI.
references/flutter.mdBest for: Web + Android code sharing, JS/TS teams, rich ecosystem.
references/react-native.mdBest for: Sharing business logic across Android + Desktop + Web while keeping native Android UI.
references/kmm.mdBest for: Web-first teams, simple apps, PWA-like content apps.
references/hybrid.md| 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 | ⚠️ | ✅ | ❌ |
Every production Android project must separate UI, business logic, and data into distinct, independently testable layers.
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
Native (MVVM + MVI):
StateFlow / SharedFlow for reactive statesealed class UiState + sealed class UiEventFlutter (BLoC or Riverpod):
Bloc or Cubit for business logic isolationAsyncNotifierProvider (Riverpod) for data + stateReact Native (Redux Toolkit or Zustand):
KMM:
commonMain holds domain + data layersexpect/actual for platform-specific implementations: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
Before writing screens, define:
MaterialTheme tokens; never hardcode colors/dimensionsCompositionLocal for theme, locale, hapticsremember / rememberSaveable correctly (saveable for UI state surviving rotation)LazyColumn/LazyVerticalGrid for lists; never Column with forEach for large dataLaunchedEffect, DisposableEffect, SideEffectcontentDescription or semantics { }TalkBack compatibility tested before every releasesp not dp for text)NavHost and SafeArgs equivalentgo_router with named routes and guardsNavigationProppopUpTo / launchSingleTopWindowSizeClass)WindowInfoTrackerWindowInsets handling required for Android 15+Kotlin:
data class, sealed class, object, enum class appropriately!! null assertions — use ?.let, ?: return, requireNotNull with messageCoroutineScope + Dispatcher explicitly; never GlobalScope@Stable / @Immutable on Compose state classes for smart recompositionJava:
@NonNull / @Nullable annotations on every method param and return typeObjects.requireNonNullbinding reference in Fragment's onDestroyView() to prevent memory leaksExecutorService (not AsyncTask — deprecated) for background work; or LiveData + Room's built-in threadingListAdapter + DiffUtil over manual notifyDataSetChanged() in RecyclerViewViewBinding — never findViewByIdDart (Flutter):
! without explicit null check abovecopyWithconst constructors on all stateless widgetsTypeScript (RN):
strict: true in tsconfig alwaysany — use unknown and narrowbuild.gradle.kts / pubspec.yaml / package.jsonActivity context stored in singletons)Never let exceptions propagate to the user silently or crash the app.
| 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 |
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.
Room / Drift / MMKV as single source of truthConnectivityManager and reflect in UI /\
/E2E\ ← 10% (UI tests: Espresso, Maestro, Appium)
/------\
/ Integr \ ← 20% (Repository, DB, API contract tests)
/----------\
/ Unit \ ← 70% (ViewModels, Use Cases, Utilities)
/--------------\
flutter_test + mocktail@testing-library/react-native + msw for API mockingMockWebServer (OkHttp)debug → dev API, logging on, no minification, debuggable
staging → staging API, logging on, minified, not debuggable
release → prod API, logging off, minified, signed
build.gradle.kts only — no Groovy DSL in new projectslibs.versions.toml) for all dependency versionsbuildConfig for environment-specific constantsPR 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.
FrameMetrics APIdraw() / onMeasure() / compositionderivedStateOf in Compose to avoid unnecessary recompositionsActivity / Context references in ViewModels or singletons| 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 |
Log.d in release builds)Follow this phase structure for any new Android project:
For stack-specific deep dives, read:
references/native-android.md — Kotlin, Compose, Room, Hilt, Coroutinesreferences/java-android.md — Java, XML Views, ViewBinding, LiveData, Retrofit, Room, Hilt, migration pathreferences/flutter.md — Dart, BLoC/Riverpod, Drift, go_routerreferences/react-native.md — TypeScript, RN architecture, Hermes, New Architecturereferences/kmm.md — KMM shared modules, SQLDelight, Ktor, Compose Multiplatformreferences/hybrid.md — Capacitor, Ionic, PWA considerationsIntegration with protocols.io API for managing scientific protocols. This skill should be used when working with protocols.io to search, create, update, or publish protocols; manage protocol steps and materials; handle discussions and comments; organize workspaces; upload and manage files; or integrate protocols.io functionality into workflows. Applicable for protocol discovery, collaborative protocol development, experiment tracking, lab protocol management, and scientific documentation.
Analyzes job descriptions and generates tailored resumes that highlight relevant experience, skills, and achievements to maximize interview chances
Generate Excalidraw diagrams from natural language descriptions. Use when asked to "create a diagram", "make a flowchart", "visualize a process", "draw a system architecture", "create a mind map", or "generate an Excalidraw file". Supports flowcharts, relationship diagrams, mind maps, and system architecture diagrams. Outputs .excalidraw JSON files that can be opened directly in Excalidraw.
Build and distribute Expo development clients locally or via TestFlight
Use when you have a written implementation plan to execute in a separate session with review checkpoints
Data structure for annotated matrices in single-cell analysis. Use when working with .h5ad files or integrating with the scverse ecosystem. This is the data format skill—for analysis workflows use scanpy; for probabilistic models use scvi-tools; for population-scale queries use cellxgene-census.
Benchling R&D platform integration. Access registry (DNA, proteins), inventory, ELN entries, workflows via API, build Benchling Apps, query Data Warehouse, for lab data management automation.
Comprehensive molecular biology toolkit. Use for sequence manipulation, file parsing (FASTA/GenBank/PDB), phylogenetics, and programmatic NCBI/PubMed access (Bio.Entrez). Best for batch processing, custom bioinformatics pipelines, BLAST automation. For quick lookups use gget; for multi-service integration use bioservices.
Take lingxling/android-dev from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.