Platform Notes
- Optional helper plugins may help in some environments, but they must not be treated as required for this skill.
Android Development Standards
Acknowledgement: Shared by Peter Bamuhigire, techguypeter.com, +256 784 464178.
Use When
- Android development standards for AI agent implementation. Kotlin-first, Jetpack Compose UI, MVVM + Clean Architecture, Hilt DI, comprehensive security, testing, and performance patterns. Use when building or reviewing Android applications...
Evidence Produced
| Category |
Artifact |
Format |
Example |
| Correctness |
Android feature test plan |
Markdown doc covering unit, instrumentation, and Compose tests |
docs/android/feature-tests-checkout.md |
| UX quality |
Accessibility audit |
Markdown doc covering TalkBack, semantics, and contrast |
docs/android/a11y-checkout.md |
References
- Use the
references/ directory for deep detail after reading the core workflow below.
references/android-ai-ml.md for on-device Android AI/ML, ML Kit, LiteRT, MediaPipe, AICore, and Gemini Nano.
references/android-biometric-login.md for AndroidX Biometric launch gates and CryptoObject-backed authentication.
references/android-pdf-export.md for native PdfDocument export and Android report PDF generation.
Load Order
- Load
world-class-engineering for shared production gates.
- Load
system-architecture-design when the Android app is part of a larger backend or multi-module system.
- Load this skill for Android implementation details.
- Load
android-ui-ux-design for every user-facing Android screen, especially premium, dashboard, onboarding, reporting, form, or revenue-critical flows.
- Load
vibe-security-skill and feature-specific skills as needed.
Production-grade Android development standards for AI-assisted implementation. Kotlin-first with Jetpack Compose, following modern Android best practices.
Core Stack: Kotlin 100% | Jetpack Compose (default UI toolkit) | MVVM + Clean Architecture | Hilt DI
Min SDK: 29 (Android 10) | Target SDK: 35 (Android 15)
Compatibility: Must run flawlessly on BOTH the minSdk (oldest supported) AND the latest stable Android release
Reference App: Now in Android - Google's official sample demonstrating these standards in a production-quality codebase
When to Use
- Building new Android applications or features
- Reviewing Android code for quality and standards compliance
- Generating Kotlin/Compose code via AI agents
- Setting up Android project structure
- Implementing security, testing, or performance patterns
- Integrating with REST APIs from Android clients
Backend Environments
Android apps connect to a PHP/MySQL backend deployed across three environments:
| Environment |
Base URL Pattern |
Database |
Notes |
| Development |
http://{LAN_IP}:{port}/DMS_web/api/ |
MySQL 8.4.7 (Windows WAMP) |
Use host machine's LAN IP, not localhost |
| Staging |
https://staging.{domain}/api/ |
MySQL 8.x (Ubuntu VPS) |
For QA and testing |
| Production |
https://{domain}/api/ |
MySQL 8.x (Debian VPS) |
Live users |
Configure base URLs using build flavors (dev, staging, prod) so the app targets the correct backend per build variant. All backends use utf8mb4_unicode_ci collation and MySQL 8.x.
Quick Reference
| Topic |
Reference File |
Covers |
| Project Structure |
references/project-structure.md |
Directory layout, module organization |
| Kotlin Conventions |
references/kotlin-conventions.md |
Coding style, Compose patterns |
| Architecture |
references/architecture-patterns.md |
MVVM, Clean Architecture layers |
| Dependency Injection |
references/dependency-injection.md |
Hilt modules, scoping, ViewModel injection |
| Security |
references/security.md |
Encrypted storage, biometrics, network security |
| UI Design System |
references/ui-design-system.md |
Tokens, components, Material 3 |
| Premium Android UX |
../android-ui-ux-design/SKILL.md |
Material 3 polish, mobile ergonomics, premium gate |
| Screen Patterns |
references/screen-patterns.md |
Complete screen templates, state handling |
| Testing |
references/testing.md |
Unit, UI, instrumentation tests |
| Build Configuration |
references/build-configuration.md |
Gradle KTS, Android Studio setup, dependencies, build types, build-speed tuning |
| API Integration |
references/api-integration.md |
Retrofit, error handling, repository pattern |
| Analytics & Performance |
references/analytics-performance.md |
Firebase, monitoring, optimization |
| AI Agent Guidelines |
references/ai-agent-guidelines.md |
Prompt templates, quality checklists |
Architecture Overview
Presentation Layer (Compose + ViewModels)
|
Domain Layer (Use Cases + Repository Interfaces)
|
Data Layer (Repository Impl + API + Room)
Layer Rules
- Presentation depends on Domain only
- Domain has no Android dependencies (pure Kotlin)
- Data implements Domain interfaces, handles API/DB
Package Structure
com.company.app/
core/ # Shared: DI, models, repositories, utils
data/ # Room DB, API services, data sources
presentation/ # Screens, ViewModels, components, navigation
theme/ # Design system tokens
Key Standards Summary
Kotlin
- 100% Kotlin, no Java for new code
- Coroutines + Flow for async (never callbacks)
- Sealed classes for UI state modeling
- Extension functions for utility code
Compose
- Jetpack Compose is the default UI toolkit for all new screens
- Views are allowed only for legacy interop or third-party View-only SDKs
- Stateless composables preferred (state hoisted to ViewModel)
LaunchedEffect for side effects, never in composition
collectAsStateWithLifecycle() for Flow collection
- Stable keys for
LazyColumn/LazyRow items
- Adaptive layouts mandatory — use
WindowSizeClass for phone/tablet/foldable
- Material 3 adaptive library:
androidx.compose.material3.adaptive:adaptive
Custom PNG Icons (Required)
- Use custom PNG icons only; do not use icon libraries
- Use
painterResource(R.drawable.<name>) or @drawable/<name>
- Maintain
PROJECT_ICONS.md in the project root
Follow the mobile-platform-operations skill (its mobile-custom-icons reference) for naming, directory rules, and tracking.
Charting (Vico Standard)
- Use Vico for all charting needs (line, bar, column, candle, etc.)
- Prefer the Compose module for new screens; use Views only when required
- Always follow the official guide for setup and current versions
- Reference the Vico sample module for patterns and styling
Report Tables (25+ Rows)
- Any report that can exceed 25 rows must render as a table, not cards
- Follow the
android-ui-ux-design skill (business reports over 25 rows use table-first or dense list patterns) for table-first guidance, and the professional-word-output skill for exported report tables.
Three Build Variants (Mandatory)
Every Android app MUST have exactly 3 build variants. This is non-negotiable.
| Variant |
Purpose |
APK Name |
Minified |
Install Target |
| debug (dev) |
Local development |
{AppName}-dev-{version}.apk |
No |
Emulator (default) |
| staging |
QA / pre-production |
{AppName}-staging-{version}.apk |
Yes (R8) |
Emulator (on request) |
| release (prod) |
Production / Play Store |
{AppName}-prod-{version}.apk |
Yes (R8) |
Device (manual) |
Rules:
- User must provide the staging and production API URLs for each project. Debug always points to the local dev server (
http://10.0.2.2/... for emulator or the host LAN IP).
- During active development, build only the variant you need — usually
debug. Do not build staging and release on every iteration.
- Default local loop:
./gradlew installDebug (or assembleDebug) for normal coding, UI work, and device testing.
- Build all 3 APKs only for release verification, QA handoff, CI, or when the user explicitly asks for all artifacts:
./gradlew assembleDebug assembleStaging assembleRelease
- If the user explicitly asks to test staging, install staging instead:
./gradlew installStaging
- APK naming uses a consistent prefix per app (e.g.,
DMS-dev-1.0.0.apk, DMS-staging-1.0.0.apk, DMS-prod-1.0.0.apk). Configure via the modern Android Components Variant API, not deprecated internal output classes.
- Staging inherits from release (R8 enabled, resource shrinking) but uses the debug signing config so it can be installed alongside dev on the same device.
- ProGuard rules must strip
Log.v, Log.d, Log.i, and println from staging and release builds.
- Never hardcode API URLs — always use
BuildConfig.API_BASE_URL (or similar) set per build type.
See references/build-configuration.md for the complete Gradle setup.
Always set API endpoints through BuildConfig.API_BASE_URL (or a similar generated constant) per build type or flavor. Never hardcode server URLs in app code.
Android Studio + Build Speed Baseline
Before doing deeper performance work, establish this baseline:
- Keep tools current — update Android Studio, SDK tools, Gradle, and AGP together when the project allows it.
- Use KSP instead of kapt wherever the library supports it.
kapt should be treated as legacy.
- Pin dependency and plugin versions — never use dynamic versions like
2.+ or latest.release.
- Disable Jetifier unless Build Analyzer proves the project still needs it.
- Enable configuration cache once the project and plugins are compatible.
- Use configuration-avoidance and lazy APIs in Gradle scripts; do not run expensive logic during configuration.
- Keep debug builds static — no dynamic version names, manifest placeholders, or generated values that force full rebuilds.
- Prefer modularization when the app is large enough that feature or core modules can compile independently.
- Use Build Analyzer and Gradle profiling before guessing. Measure first, then optimize the real bottleneck.
- Develop on API 24+ devices/emulators whenever possible for faster deployment loops.
Device & Android Version Compatibility (CRITICAL)
Our apps MUST work for the few people still holding older devices, but MUST ALSO WORK for those with newer/latest devices. Never test only on one Android version.
Mandatory rules:
enableEdgeToEdge() is REQUIRED — Call it in MainActivity.onCreate() before super.onCreate(). Android 15 (API 35) enforces edge-to-edge for apps targeting SDK 35. Without it, the app crashes immediately on Android 15 devices. This is non-negotiable.
- Do NOT set
window.statusBarColor directly — It is deprecated and conflicts with edge-to-edge. Let enableEdgeToEdge() handle system bar colors. Only control light/dark icon appearance via WindowCompat.getInsetsController().isAppearanceLightStatusBars.
- Test on at least two Android versions — Always verify on both the minSdk emulator (Android 10) AND a recent Android (14/15) emulator or device before shipping.
- Guard version-specific APIs — When using APIs added after minSdk, wrap them in
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.X) checks.
- Keep targetSdk current — Target the latest stable SDK (currently 35). Do not lag behind — Google Play requires recent targetSdk and newer Android versions enforce stricter behavior for apps that target them.
- Use
AppCompatActivity when locale switching is needed (AppCompatDelegate.setApplicationLocales()). Otherwise prefer ComponentActivity for pure Compose apps.
Correct MainActivity pattern:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen() // Before super
enableEdgeToEdge() // Before super — MANDATORY for targetSdk 35
super.onCreate(savedInstanceState)
setContent { ... }
}
}
Security
EncryptedSharedPreferences for sensitive data
- Certificate pinning for API calls — NEVER use placeholder pins (they cause
SSLPeerUnverifiedException). Extract real SHA-256 pins from servers using openssl before enabling. See references/security.md for the extraction command.
- For Let's Encrypt servers: always pin the intermediate CA (stable) alongside the leaf pin. Leaf pins rotate every 90 days on auto-renewal; intermediate CA pins survive renewals.
- Use
ENABLE_CERT_PINNING BuildConfig flag: false for dev, true for staging/prod
- Pin ALL server domains the app connects to (both staging AND production)
- Biometric authentication for sensitive operations
- No hardcoded secrets, use
BuildConfig fields
- ProGuard/R8 for release builds
Testing
- Unit tests for ViewModels and Use Cases (MockK)
- Compose UI tests for screens (ComposeTestRule)
- Turbine for Flow testing
- Hilt test rules for DI in tests
Performance
- StrictMode in debug builds
- Stable keys in lazy lists
derivedStateOf for expensive calculations
- Image loading via Coil with caching
- ProGuard + resource shrinking in release
- Build with
debug only during normal development; reserve full multi-variant builds for QA or release checks
- Use Build Analyzer before changing Gradle memory, GC, or plugin settings
- Prefer KSP-backed processors and remove
kapt unless there is no supported migration path
- Keep
android.enableJetifier=false unless a dependency audit proves otherwise
- Enable configuration cache only after checking plugin compatibility and fixing violations
Release Gate
Before calling an Android feature production-ready:
- Verify the main user journey on minSdk and latest Android.
- Verify offline, slow-network, and denied-permission behavior.
- Verify startup, scrolling, and list interactions against performance expectations.
- Verify crash reporting, analytics, and audit-sensitive actions are instrumented.
- Verify sensitive data never lands in logs, screenshots, or unsecured storage.
- Verify
android-ui-ux-design premium UX checks for navigation, touch targets, text scaling, TalkBack, state completeness, and platform-native polish.
Local Development Networking (WAMP)
- When developing on a local machine (Windows WAMP or Ubuntu), the Android emulator must reach the backend via the host machine's static LAN IP, not
localhost.
- Always document the static IP in dev setup notes and use it for
BASE_URL in the Android dev build.
- Verify firewall rules allow inbound connections to the WAMP HTTP port.
Google Play Review Readiness
- Use the
mobile-platform-operations skill (its google-play-store-review reference) before Play Console submission.
- Keep targetSdk current and background work compliant.
- Ensure Data Safety form matches SDKs and permissions.
- Provide a public privacy policy and link it in-app.
- Validate ads and IAP flows for transparency and user control.
Mandatory Theme Appearance Setting
Every Android app MUST include a theme appearance selector in its Tools/Settings section. This is a non-negotiable standard — users must be able to control the app's visual theme.
Requirements:
- Three options: System default (follows device setting), Light, Dark
- Default: System default — always respect the user's device-wide preference
- Location: Tools or Settings hub screen, under an "Appearance" section
- Persistence: Store in SharedPreferences (not encrypted — non-sensitive)
- Reactivity: Theme changes apply instantly without app restart (use StateFlow)
Implementation pattern:
// 1. ThemePreferences.kt (data/local/prefs/)
enum class ThemeMode(val key: String, val label: String) {
SYSTEM("system", "System default"),
LIGHT("light", "Light"),
DARK("dark", "Dark");
companion object {
fun fromKey(key: String): ThemeMode =
entries.firstOrNull { it.key == key } ?: SYSTEM
}
}
@Singleton
class ThemePreferences @Inject constructor(
@ApplicationContext context: Context
) {
private val prefs = context.getSharedPreferences("theme_prefs", Context.MODE_PRIVATE)
private val _themeMode = MutableStateFlow(loadThemeMode())
val themeMode: StateFlow<ThemeMode> = _themeMode.asStateFlow()
private fun loadThemeMode(): ThemeMode =
ThemeMode.fromKey(prefs.getString("theme_mode", "system") ?: "system")
fun setThemeMode(mode: ThemeMode) {
prefs.edit().putString("theme_mode", mode.key).apply()
_themeMode.value = mode
}
}
// 2. MainActivity.kt — resolve ThemeMode to darkTheme boolean
val themeMode by themePreferences.themeMode.collectAsState()
val darkTheme = when (themeMode) {
ThemeMode.SYSTEM -> isSystemInDarkTheme()
ThemeMode.LIGHT -> false
ThemeMode.DARK -> true
}
AppTheme(darkTheme = darkTheme) { /* content */ }
// 3. Tools/Settings screen — FilterChip row for selection
ThemeMode.entries.forEach { mode ->
FilterChip(
selected = selected == mode,
viewModel.setThemeMode(mode) },
label = { Text(mode.label) },
leadingIcon = if (selected == mode) { { Icon(Icons.Default.Check, null) } } else null
)
}
Phase 1 Bootstrap Pattern (SaaS Mobile Apps)
When building a native Android app for an existing SaaS backend, always implement Phase 1 first: Login + Dashboard + Empty Tabs. This is the mandatory starting point before any business features.
Phase 1 Delivers
- JWT Auth — Login/logout, token refresh with rotation, breach detection, encrypted storage
- Dashboard — Real KPI stats, offline-first Room caching, pull-to-refresh, shimmer loading
- 5-Tab Navigation — Bottom bar with max 5 tabs, placeholder screens for future features
- Full Infrastructure — Hilt DI, Retrofit interceptor chain, Room DB, Material 3 theme, network monitor
- 40+ Unit Tests — ViewModels, Use Cases, Repositories, Interceptors all tested
Why Phase 1 First
- Proves the entire vertical slice (Compose UI → ViewModel → UseCase → Repo → Retrofit → PHP → MySQL)
- Establishes all reusable infrastructure patterns
- Gives user a working installable app immediately
- Uncovers backend integration issues early
See android-saas-planning skill for the complete Phase 1 plan template.
KMP Projects
If this is a Kotlin Multiplatform project, this skill governs the
composeApp/ module (Android UI and platform integration). The shared/
module is governed by the kmp-development skill. Use Hilt for DI in
composeApp/ and Koin in shared/. Use the kmp-development skill for shared module test-driven development.
Anti-Patterns
- Putting business logic in Composables
- Using
mutableStateOf in ViewModels instead of StateFlow
- Hardcoding colors/dimensions instead of design tokens
- Skipping error states in UI
- Network calls on main thread
- Missing
key parameter in LazyColumn items
- God ViewModels (split by feature, not by screen)
- Ignoring lifecycle (use
collectAsStateWithLifecycle)
- Building phone-only UIs — all screens must adapt to tablets/foldables
- Using hardcoded
isTablet() checks instead of WindowSizeClass breakpoints
- Missing
enableEdgeToEdge() — causes immediate crash on Android 15 devices
- Setting
window.statusBarColor directly — deprecated, conflicts with edge-to-edge
- Testing only on one Android version — must verify on both old (minSdk) and new (latest) devices
Integration with Other Skills
feature-planning -> spec + implementation strategy
|
android-development -> Kotlin/Compose implementation
|
android-ui-ux-design -> premium Material 3 UX and screen quality
|
mobile-platform-operations -> Play policy and submission readiness
|
api-error-handling -> Backend API error patterns
|
mysql-best-practices -> Database schema (backend)
|
vibe-security-skill -> Security review
Always apply vibe-security-skill alongside this skill for web-connected Android apps.
Use mobile-platform-operations when preparing Play Console submissions.
Reference Implementations
Decision Rules
| Condition |
Choice |
| New user interface |
Compose; isolate an existing View system behind a stable boundary |
| Business rule shared across screens |
Pure Kotlin domain use case |
| Android framework dependency |
Keep it outside the domain layer |
| Release behaviour differs by environment |
Typed build flavour configuration; no runtime hard-coded URL |
Degraded Mode
When builds or devices are unavailable, provide a reviewable patch and list the exact Gradle, unit, instrumentation, accessibility, and min-SDK checks still requiring execution. Do not claim device compatibility from static inspection alone.
Google maintains three official reference repos. Use them as canonical examples:
Full production-quality app. Use for: multi-module architecture, convention plugins, offline-first (Room + network sync), Hilt across modules, version catalogs, Gradle KTS build config.
Layered architecture TODO app. Use for: MVVM pattern clarity, Repository pattern with dual data sources, single-activity navigation with Compose, product flavors (mock/prod), comprehensive test suite (unit + integration + E2E), clean separation of concerns.
Collection of focused Compose apps. Use for specific UI patterns:
| Sample |
Use For |
| JetNews |
Material app structure, theming, Compose testing |
| Jetchat |
Material 3, dynamic colors, navigation, state management |
| Jetsnack |
Custom design systems, layouts, animations |
| Jetcaster |
Redux-style architecture, dynamic theming, Room, coroutines |
| Reply |
Adaptive UI (phone/tablet/foldable), Material 3 |
| JetLagged |
Custom layouts, graphics, Canvas/Path drawing |
When in doubt about how to implement something, check these repos first.
Inputs
| Artefact |
Required? |
Purpose |
| Android requirements, supported API levels, architecture, UX, and backend contracts |
yes |
Bound implementation |
Outputs
- Produce Android code or design with lifecycle, accessibility, test, performance, and release evidence.
Capability contract
Read/search and local builds follow task scope; signing, store publication, backend mutation, and device-data destruction require explicit authority.
1---2name: android-development3description: Use when building or reviewing native Android applications with Kotlin, Compose, Hilt, and layered architecture; use android-data-persistence or android-tdd for focused data and test work.4metadata:5 portable: true6 compatible_with:7 - claude-code8 - codex9---1011## Platform Notes1213- Optional helper plugins may help in some environments, but they must not be treated as required for this skill.1415# Android Development Standards16Acknowledgement: Shared by Peter Bamuhigire, techguypeter.com, +256 784 464178.1718<!-- dual-compat-start -->19## Use When2021- Android development standards for AI agent implementation. Kotlin-first, Jetpack Compose UI, MVVM + Clean Architecture, Hilt DI, comprehensive security, testing, and performance patterns. Use when building or reviewing Android applications...2223## Evidence Produced2425| Category | Artifact | Format | Example |26|----------|----------|--------|---------|27| Correctness | Android feature test plan | Markdown doc covering unit, instrumentation, and Compose tests | `docs/android/feature-tests-checkout.md` |28| UX quality | Accessibility audit | Markdown doc covering TalkBack, semantics, and contrast | `docs/android/a11y-checkout.md` |2930## References3132- Use the `references/` directory for deep detail after reading the core workflow below.33- `references/android-ai-ml.md` for on-device Android AI/ML, ML Kit, LiteRT, MediaPipe, AICore, and Gemini Nano.34- `references/android-biometric-login.md` for AndroidX Biometric launch gates and CryptoObject-backed authentication.35- `references/android-pdf-export.md` for native `PdfDocument` export and Android report PDF generation.36<!-- dual-compat-end -->37## Load Order38391. Load `world-class-engineering` for shared production gates.402. Load `system-architecture-design` when the Android app is part of a larger backend or multi-module system.413. Load this skill for Android implementation details.424. Load `android-ui-ux-design` for every user-facing Android screen, especially premium, dashboard, onboarding, reporting, form, or revenue-critical flows.435. Load `vibe-security-skill` and feature-specific skills as needed.4445Production-grade Android development standards for AI-assisted implementation. Kotlin-first with Jetpack Compose, following modern Android best practices.4647**Core Stack:** Kotlin 100% | Jetpack Compose (default UI toolkit) | MVVM + Clean Architecture | Hilt DI48**Min SDK:** 29 (Android 10) | **Target SDK:** 35 (Android 15)49**Compatibility:** Must run flawlessly on BOTH the minSdk (oldest supported) AND the latest stable Android release50**Reference App:** [Now in Android](https://github.com/android/nowinandroid) - Google's official sample demonstrating these standards in a production-quality codebase5152## When to Use5354- Building new Android applications or features55- Reviewing Android code for quality and standards compliance56- Generating Kotlin/Compose code via AI agents57- Setting up Android project structure58- Implementing security, testing, or performance patterns59- Integrating with REST APIs from Android clients6061## Backend Environments6263Android apps connect to a PHP/MySQL backend deployed across three environments:6465| Environment | Base URL Pattern | Database | Notes |66|---|---|---|---|67| **Development** | `http://{LAN_IP}:{port}/DMS_web/api/` | MySQL 8.4.7 (Windows WAMP) | Use host machine's LAN IP, not `localhost` |68| **Staging** | `https://staging.{domain}/api/` | MySQL 8.x (Ubuntu VPS) | For QA and testing |69| **Production** | `https://{domain}/api/` | MySQL 8.x (Debian VPS) | Live users |7071Configure base URLs using build flavors (`dev`, `staging`, `prod`) so the app targets the correct backend per build variant. All backends use `utf8mb4_unicode_ci` collation and MySQL 8.x.7273## Quick Reference7475| Topic | Reference File | Covers |76| --------------------------- | ------------------------------------- | ----------------------------------------------- |77| **Project Structure** | `references/project-structure.md` | Directory layout, module organization |78| **Kotlin Conventions** | `references/kotlin-conventions.md` | Coding style, Compose patterns |79| **Architecture** | `references/architecture-patterns.md` | MVVM, Clean Architecture layers |80| **Dependency Injection** | `references/dependency-injection.md` | Hilt modules, scoping, ViewModel injection |81| **Security** | `references/security.md` | Encrypted storage, biometrics, network security |82| **UI Design System** | `references/ui-design-system.md` | Tokens, components, Material 3 |83| **Premium Android UX** | `../android-ui-ux-design/SKILL.md` | Material 3 polish, mobile ergonomics, premium gate |84| **Screen Patterns** | `references/screen-patterns.md` | Complete screen templates, state handling |85| **Testing** | `references/testing.md` | Unit, UI, instrumentation tests |86| **Build Configuration** | `references/build-configuration.md` | Gradle KTS, Android Studio setup, dependencies, build types, build-speed tuning |87| **API Integration** | `references/api-integration.md` | Retrofit, error handling, repository pattern |88| **Analytics & Performance** | `references/analytics-performance.md` | Firebase, monitoring, optimization |89| **AI Agent Guidelines** | `references/ai-agent-guidelines.md` | Prompt templates, quality checklists |9091## Architecture Overview9293```94Presentation Layer (Compose + ViewModels)95 |96 Domain Layer (Use Cases + Repository Interfaces)97 |98 Data Layer (Repository Impl + API + Room)99```100101### Layer Rules1021031. **Presentation** depends on Domain only1042. **Domain** has no Android dependencies (pure Kotlin)1053. **Data** implements Domain interfaces, handles API/DB106107### Package Structure108109```110com.company.app/111 core/ # Shared: DI, models, repositories, utils112 data/ # Room DB, API services, data sources113 presentation/ # Screens, ViewModels, components, navigation114 theme/ # Design system tokens115```116117## Key Standards Summary118119### Kotlin120121- 100% Kotlin, no Java for new code122- Coroutines + Flow for async (never callbacks)123- Sealed classes for UI state modeling124- Extension functions for utility code125126### Compose127128- Jetpack Compose is the default UI toolkit for all new screens129- Views are allowed only for legacy interop or third-party View-only SDKs130- Stateless composables preferred (state hoisted to ViewModel)131- `LaunchedEffect` for side effects, never in composition132- `collectAsStateWithLifecycle()` for Flow collection133- Stable keys for `LazyColumn`/`LazyRow` items134- **Adaptive layouts mandatory** — use `WindowSizeClass` for phone/tablet/foldable135- Material 3 adaptive library: `androidx.compose.material3.adaptive:adaptive`136137### Custom PNG Icons (Required)138139- Use custom PNG icons only; do not use icon libraries140- Use `painterResource(R.drawable.<name>)` or `@drawable/<name>`141- Maintain `PROJECT_ICONS.md` in the project root142143Follow the `mobile-platform-operations` skill (its `mobile-custom-icons` reference) for naming, directory rules, and tracking.144145### Charting (Vico Standard)146147- Use Vico for all charting needs (line, bar, column, candle, etc.)148- Prefer the Compose module for new screens; use Views only when required149- Always follow the official guide for setup and current versions150- Reference the Vico sample module for patterns and styling151152### Report Tables (25+ Rows)153154- Any report that can exceed 25 rows must render as a table, not cards155- Follow the `android-ui-ux-design` skill (business reports over 25 rows use table-first or dense list patterns) for table-first guidance, and the `professional-word-output` skill for exported report tables.156157### Three Build Variants (Mandatory)158159Every Android app MUST have exactly 3 build variants. This is non-negotiable.160161| Variant | Purpose | APK Name | Minified | Install Target |162|---------|---------|----------|----------|----------------|163| **debug** (dev) | Local development | `{AppName}-dev-{version}.apk` | No | Emulator (default) |164| **staging** | QA / pre-production | `{AppName}-staging-{version}.apk` | Yes (R8) | Emulator (on request) |165| **release** (prod) | Production / Play Store | `{AppName}-prod-{version}.apk` | Yes (R8) | Device (manual) |166167**Rules:**1681691. **User must provide** the staging and production API URLs for each project. Debug always points to the local dev server (`http://10.0.2.2/...` for emulator or the host LAN IP).1702. **During active development, build only the variant you need** — usually `debug`. Do not build `staging` and `release` on every iteration.1713. **Default local loop:** `./gradlew installDebug` (or `assembleDebug`) for normal coding, UI work, and device testing.1724. **Build all 3 APKs only for release verification, QA handoff, CI, or when the user explicitly asks for all artifacts**: `./gradlew assembleDebug assembleStaging assembleRelease`1735. If the user explicitly asks to test staging, install staging instead: `./gradlew installStaging`1746. **APK naming** uses a consistent prefix per app (e.g., `DMS-dev-1.0.0.apk`, `DMS-staging-1.0.0.apk`, `DMS-prod-1.0.0.apk`). Configure via the modern Android Components Variant API, not deprecated internal output classes.1757. **Staging** inherits from release (R8 enabled, resource shrinking) but uses the debug signing config so it can be installed alongside dev on the same device.1768. **ProGuard rules** must strip `Log.v`, `Log.d`, `Log.i`, and `println` from staging and release builds.1778. **Never hardcode API URLs** — always use `BuildConfig.API_BASE_URL` (or similar) set per build type.178179See `references/build-configuration.md` for the complete Gradle setup.180181Always set API endpoints through `BuildConfig.API_BASE_URL` (or a similar generated constant) per build type or flavor. Never hardcode server URLs in app code.182183### Android Studio + Build Speed Baseline184185Before doing deeper performance work, establish this baseline:1861871. **Keep tools current** — update Android Studio, SDK tools, Gradle, and AGP together when the project allows it.1882. **Use KSP instead of kapt** wherever the library supports it. `kapt` should be treated as legacy.1893. **Pin dependency and plugin versions** — never use dynamic versions like `2.+` or `latest.release`.1904. **Disable Jetifier** unless Build Analyzer proves the project still needs it.1915. **Enable configuration cache** once the project and plugins are compatible.1926. **Use configuration-avoidance and lazy APIs** in Gradle scripts; do not run expensive logic during configuration.1937. **Keep debug builds static** — no dynamic version names, manifest placeholders, or generated values that force full rebuilds.1948. **Prefer modularization** when the app is large enough that feature or core modules can compile independently.1959. **Use Build Analyzer and Gradle profiling before guessing**. Measure first, then optimize the real bottleneck.19610. **Develop on API 24+ devices/emulators whenever possible** for faster deployment loops.197198### Device & Android Version Compatibility (CRITICAL)199200Our apps MUST work for the few people still holding older devices, but MUST ALSO WORK for those with newer/latest devices. Never test only on one Android version.201202**Mandatory rules:**2032041. **`enableEdgeToEdge()` is REQUIRED** — Call it in `MainActivity.onCreate()` before `super.onCreate()`. Android 15 (API 35) enforces edge-to-edge for apps targeting SDK 35. Without it, the app **crashes immediately** on Android 15 devices. This is non-negotiable.2052. **Do NOT set `window.statusBarColor` directly** — It is deprecated and conflicts with edge-to-edge. Let `enableEdgeToEdge()` handle system bar colors. Only control light/dark icon appearance via `WindowCompat.getInsetsController().isAppearanceLightStatusBars`.2063. **Test on at least two Android versions** — Always verify on both the minSdk emulator (Android 10) AND a recent Android (14/15) emulator or device before shipping.2074. **Guard version-specific APIs** — When using APIs added after minSdk, wrap them in `if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.X)` checks.2085. **Keep targetSdk current** — Target the latest stable SDK (currently 35). Do not lag behind — Google Play requires recent targetSdk and newer Android versions enforce stricter behavior for apps that target them.2096. **Use `AppCompatActivity`** when locale switching is needed (`AppCompatDelegate.setApplicationLocales()`). Otherwise prefer `ComponentActivity` for pure Compose apps.210211**Correct MainActivity pattern:**212213```kotlin214class MainActivity : AppCompatActivity() {215 override fun onCreate(savedInstanceState: Bundle?) {216 installSplashScreen() // Before super217 enableEdgeToEdge() // Before super — MANDATORY for targetSdk 35218 super.onCreate(savedInstanceState)219 setContent { ... }220 }221}222```223224### Security225226- `EncryptedSharedPreferences` for sensitive data227- Certificate pinning for API calls — **NEVER use placeholder pins** (they cause `SSLPeerUnverifiedException`). Extract real SHA-256 pins from servers using `openssl` before enabling. See `references/security.md` for the extraction command.228- For **Let's Encrypt** servers: always pin the **intermediate CA** (stable) alongside the leaf pin. Leaf pins rotate every 90 days on auto-renewal; intermediate CA pins survive renewals.229- Use `ENABLE_CERT_PINNING` BuildConfig flag: `false` for dev, `true` for staging/prod230- Pin **ALL** server domains the app connects to (both staging AND production)231- Biometric authentication for sensitive operations232- No hardcoded secrets, use `BuildConfig` fields233- ProGuard/R8 for release builds234235### Testing236237- Unit tests for ViewModels and Use Cases (MockK)238- Compose UI tests for screens (ComposeTestRule)239- Turbine for Flow testing240- Hilt test rules for DI in tests241242### Performance243244- StrictMode in debug builds245- Stable keys in lazy lists246- `derivedStateOf` for expensive calculations247- Image loading via Coil with caching248- ProGuard + resource shrinking in release249- Build with `debug` only during normal development; reserve full multi-variant builds for QA or release checks250- Use Build Analyzer before changing Gradle memory, GC, or plugin settings251- Prefer KSP-backed processors and remove `kapt` unless there is no supported migration path252- Keep `android.enableJetifier=false` unless a dependency audit proves otherwise253- Enable configuration cache only after checking plugin compatibility and fixing violations254255### Release Gate256257Before calling an Android feature production-ready:258259- Verify the main user journey on minSdk and latest Android.260- Verify offline, slow-network, and denied-permission behavior.261- Verify startup, scrolling, and list interactions against performance expectations.262- Verify crash reporting, analytics, and audit-sensitive actions are instrumented.263- Verify sensitive data never lands in logs, screenshots, or unsecured storage.264- Verify `android-ui-ux-design` premium UX checks for navigation, touch targets, text scaling, TalkBack, state completeness, and platform-native polish.265266### Local Development Networking (WAMP)267268- When developing on a local machine (Windows WAMP or Ubuntu), the Android emulator must reach the backend via the host machine's static LAN IP, not `localhost`.269- Always document the static IP in dev setup notes and use it for `BASE_URL` in the Android dev build.270- Verify firewall rules allow inbound connections to the WAMP HTTP port.271272### Google Play Review Readiness273274- Use the `mobile-platform-operations` skill (its `google-play-store-review` reference) before Play Console submission.275- Keep targetSdk current and background work compliant.276- Ensure Data Safety form matches SDKs and permissions.277- Provide a public privacy policy and link it in-app.278- Validate ads and IAP flows for transparency and user control.279280### Mandatory Theme Appearance Setting281282Every Android app MUST include a theme appearance selector in its Tools/Settings section. This is a **non-negotiable standard** — users must be able to control the app's visual theme.283284**Requirements:**2851. **Three options:** System default (follows device setting), Light, Dark2862. **Default:** System default — always respect the user's device-wide preference2873. **Location:** Tools or Settings hub screen, under an "Appearance" section2884. **Persistence:** Store in SharedPreferences (not encrypted — non-sensitive)2895. **Reactivity:** Theme changes apply instantly without app restart (use StateFlow)290291**Implementation pattern:**292293```kotlin294// 1. ThemePreferences.kt (data/local/prefs/)295enum class ThemeMode(val key: String, val label: String) {296 SYSTEM("system", "System default"),297 LIGHT("light", "Light"),298 DARK("dark", "Dark");299 companion object {300 fun fromKey(key: String): ThemeMode =301 entries.firstOrNull { it.key == key } ?: SYSTEM302 }303}304305@Singleton306class ThemePreferences @Inject constructor(307 @ApplicationContext context: Context308) {309 private val prefs = context.getSharedPreferences("theme_prefs", Context.MODE_PRIVATE)310 private val _themeMode = MutableStateFlow(loadThemeMode())311 val themeMode: StateFlow<ThemeMode> = _themeMode.asStateFlow()312313 private fun loadThemeMode(): ThemeMode =314 ThemeMode.fromKey(prefs.getString("theme_mode", "system") ?: "system")315316 fun setThemeMode(mode: ThemeMode) {317 prefs.edit().putString("theme_mode", mode.key).apply()318 _themeMode.value = mode319 }320}321322// 2. MainActivity.kt — resolve ThemeMode to darkTheme boolean323val themeMode by themePreferences.themeMode.collectAsState()324val darkTheme = when (themeMode) {325 ThemeMode.SYSTEM -> isSystemInDarkTheme()326 ThemeMode.LIGHT -> false327 ThemeMode.DARK -> true328}329AppTheme(darkTheme = darkTheme) { /* content */ }330331// 3. Tools/Settings screen — FilterChip row for selection332ThemeMode.entries.forEach { mode ->333 FilterChip(334 selected = selected == mode,335 onClick = { viewModel.setThemeMode(mode) },336 label = { Text(mode.label) },337 leadingIcon = if (selected == mode) { { Icon(Icons.Default.Check, null) } } else null338 )339}340```341342## Phase 1 Bootstrap Pattern (SaaS Mobile Apps)343344When building a native Android app for an existing SaaS backend, **always implement Phase 1 first**: Login + Dashboard + Empty Tabs. This is the mandatory starting point before any business features.345346### Phase 1 Delivers3473481. **JWT Auth** — Login/logout, token refresh with rotation, breach detection, encrypted storage3492. **Dashboard** — Real KPI stats, offline-first Room caching, pull-to-refresh, shimmer loading3503. **5-Tab Navigation** — Bottom bar with max 5 tabs, placeholder screens for future features3514. **Full Infrastructure** — Hilt DI, Retrofit interceptor chain, Room DB, Material 3 theme, network monitor3525. **40+ Unit Tests** — ViewModels, Use Cases, Repositories, Interceptors all tested353354### Why Phase 1 First355356- Proves the entire vertical slice (Compose UI → ViewModel → UseCase → Repo → Retrofit → PHP → MySQL)357- Establishes all reusable infrastructure patterns358- Gives user a working installable app immediately359- Uncovers backend integration issues early360361See `android-saas-planning` skill for the complete Phase 1 plan template.362363## KMP Projects364365If this is a **Kotlin Multiplatform** project, this skill governs the366`composeApp/` module (Android UI and platform integration). The `shared/`367module is governed by the `kmp-development` skill. Use Hilt for DI in368`composeApp/` and Koin in `shared/`. Use the `kmp-development` skill for shared module test-driven development.369370## Anti-Patterns371372- Putting business logic in Composables373- Using `mutableStateOf` in ViewModels instead of `StateFlow`374- Hardcoding colors/dimensions instead of design tokens375- Skipping error states in UI376- Network calls on main thread377- Missing `key` parameter in `LazyColumn` items378- God ViewModels (split by feature, not by screen)379- Ignoring lifecycle (use `collectAsStateWithLifecycle`)380- Building phone-only UIs — all screens must adapt to tablets/foldables381- Using hardcoded `isTablet()` checks instead of `WindowSizeClass` breakpoints382- **Missing `enableEdgeToEdge()`** — causes immediate crash on Android 15 devices383- Setting `window.statusBarColor` directly — deprecated, conflicts with edge-to-edge384- Testing only on one Android version — must verify on both old (minSdk) and new (latest) devices385386## Integration with Other Skills387388```389feature-planning -> spec + implementation strategy390 |391android-development -> Kotlin/Compose implementation392 |393android-ui-ux-design -> premium Material 3 UX and screen quality394 |395mobile-platform-operations -> Play policy and submission readiness396 |397api-error-handling -> Backend API error patterns398 |399mysql-best-practices -> Database schema (backend)400 |401vibe-security-skill -> Security review402```403404**Always apply `vibe-security-skill`** alongside this skill for web-connected Android apps.405Use `mobile-platform-operations` when preparing Play Console submissions.406407## Reference Implementations408409## Decision Rules410411| Condition | Choice |412|---|---|413| New user interface | Compose; isolate an existing View system behind a stable boundary |414| Business rule shared across screens | Pure Kotlin domain use case |415| Android framework dependency | Keep it outside the domain layer |416| Release behaviour differs by environment | Typed build flavour configuration; no runtime hard-coded URL |417418## Degraded Mode419420When builds or devices are unavailable, provide a reviewable patch and list the exact Gradle, unit, instrumentation, accessibility, and min-SDK checks still requiring execution. Do not claim device compatibility from static inspection alone.421422Google maintains three official reference repos. Use them as canonical examples:423424### Now in Android ([github.com/android/nowinandroid](https://github.com/android/nowinandroid))425426Full production-quality app. **Use for:** multi-module architecture, convention plugins, offline-first (Room + network sync), Hilt across modules, version catalogs, Gradle KTS build config.427428### Architecture Samples ([github.com/android/architecture-samples](https://github.com/android/architecture-samples))429430Layered architecture TODO app. **Use for:** MVVM pattern clarity, Repository pattern with dual data sources, single-activity navigation with Compose, product flavors (mock/prod), comprehensive test suite (unit + integration + E2E), clean separation of concerns.431432### Compose Samples ([github.com/android/compose-samples](https://github.com/android/compose-samples))433434Collection of focused Compose apps. **Use for specific UI patterns:**435436| Sample | Use For |437| ------------- | ----------------------------------------------------------- |438| **JetNews** | Material app structure, theming, Compose testing |439| **Jetchat** | Material 3, dynamic colors, navigation, state management |440| **Jetsnack** | Custom design systems, layouts, animations |441| **Jetcaster** | Redux-style architecture, dynamic theming, Room, coroutines |442| **Reply** | Adaptive UI (phone/tablet/foldable), Material 3 |443| **JetLagged** | Custom layouts, graphics, Canvas/Path drawing |444445When in doubt about how to implement something, check these repos first.446## Inputs447| Artefact | Required? | Purpose |448|---|---|---|449| Android requirements, supported API levels, architecture, UX, and backend contracts | yes | Bound implementation |450## Outputs451- Produce Android code or design with lifecycle, accessibility, test, performance, and release evidence.452## Capability contract453Read/search and local builds follow task scope; signing, store publication, backend mutation, and device-data destruction require explicit authority.