android-native-dev

安装量: 1.2K
排名: #3650

安装

npx skills add https://github.com/minimax-ai/skills --skill android-native-dev
  1. Project Scenario Assessment Before starting development, assess the current project state: Scenario Characteristics Approach Empty Directory No files present Full initialization required, including Gradle Wrapper Has Gradle Wrapper gradlew and gradle/wrapper/ exist Use ./gradlew directly for builds Android Studio Project Complete project structure, may lack wrapper Check wrapper, run gradle wrapper if needed Incomplete Project Partial files present Check missing files, complete configuration Key Principles : Before writing business logic, ensure ./gradlew assembleDebug succeeds If gradle.properties is missing, create it first and configure AndroidX 1.1 Required Files Checklist MyApp/ ├── gradle.properties # Configure AndroidX and other settings ├── settings.gradle.kts ├── build.gradle.kts # Root level ├── gradle/wrapper/ │ └── gradle-wrapper.properties ├── app/ │ ├── build.gradle.kts # Module level │ └── src/main/ │ ├── AndroidManifest.xml │ ├── java/com/example/myapp/ │ │ └── MainActivity.kt │ └── res/ │ ├── values/ │ │ ├── strings.xml │ │ ├── colors.xml │ │ └── themes.xml │ └── mipmap-*/ # App icons
  2. Project Configuration 2.1 gradle.properties

Required configuration

android.useAndroidX

true android.enableJetifier = true

Build optimization

org.gradle.parallel

true kotlin.code.style = official

JVM memory settings (adjust based on project size)

Small projects: 2048m, Medium: 4096m, Large: 8192m+

org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8

Note
If you encounter OutOfMemoryError during build, increase -Xmx value. Large projects with many dependencies may require 8GB or more. 2.2 Dependency Declaration Standards dependencies { // Use BOM to manage Compose versions implementation ( platform ( "androidx.compose:compose-bom:2024.02.00" ) ) implementation ( "androidx.compose.ui:ui" ) implementation ( "androidx.compose.material3:material3" ) // Activity & ViewModel implementation ( "androidx.activity:activity-compose:1.8.2" ) implementation ( "androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0" ) } 2.3 Build Variants & Product Flavors Product Flavors allow you to create different versions of your app (e.g., free/paid, dev/staging/prod). Configuration in app/build.gradle.kts : android { // Define flavor dimensions flavorDimensions += "environment" productFlavors { create ( "dev" ) { dimension = "environment" applicationIdSuffix = ".dev" versionNameSuffix = "-dev" // Different config values per flavor buildConfigField ( "String" , "API_BASE_URL" , "\"https://dev-api.example.com\"" ) buildConfigField ( "Boolean" , "ENABLE_LOGGING" , "true" ) // Different resources resValue ( "string" , "app_name" , "MyApp Dev" ) } create ( "staging" ) { dimension = "environment" applicationIdSuffix = ".staging" versionNameSuffix = "-staging" buildConfigField ( "String" , "API_BASE_URL" , "\"https://staging-api.example.com\"" ) buildConfigField ( "Boolean" , "ENABLE_LOGGING" , "true" ) resValue ( "string" , "app_name" , "MyApp Staging" ) } create ( "prod" ) { dimension = "environment" // No suffix for production buildConfigField ( "String" , "API_BASE_URL" , "\"https://api.example.com\"" ) buildConfigField ( "Boolean" , "ENABLE_LOGGING" , "false" ) resValue ( "string" , "app_name" , "MyApp" ) } } buildTypes { debug { isDebuggable = true isMinifyEnabled = false } release { isDebuggable = false isMinifyEnabled = true proguardFiles ( getDefaultProguardFile ( "proguard-android-optimize.txt" ) , "proguard-rules.pro" ) } } } Build Variant Naming : {flavor}{BuildType} → e.g., devDebug , prodRelease Gradle Build Commands :

List all available build variants

./gradlew tasks --group = "build"

Build specific variant (flavor + buildType)

./gradlew assembleDevDebug

Dev flavor, Debug build

./gradlew assembleStagingDebug

Staging flavor, Debug build

./gradlew assembleProdRelease

Prod flavor, Release build

Build all variants of a specific flavor

./gradlew assembleDev

All Dev variants (debug + release)

./gradlew assembleProd

All Prod variants

Build all variants of a specific build type

./gradlew assembleDebug

All flavors, Debug build

./gradlew assembleRelease

All flavors, Release build

Install specific variant to device

./gradlew installDevDebug ./gradlew installProdRelease

Build and install in one command

./gradlew installDevDebug
&&
adb shell am start
-n
com.example.myapp.dev/.MainActivity
Access BuildConfig in Code
:
Note
Starting from AGP 8.0, BuildConfig is no longer generated by default. You must explicitly enable it in your build.gradle.kts : android { buildFeatures { buildConfig = true } } // Use build config values in your code val apiUrl = BuildConfig . API_BASE_URL val isLoggingEnabled = BuildConfig . ENABLE_LOGGING if ( BuildConfig . DEBUG ) { // Debug-only code } Flavor-Specific Source Sets : app/src/ ├── main/ # Shared code for all flavors ├── dev/ # Dev-only code and resources │ ├── java/ │ └── res/ ├── staging/ # Staging-only code and resources ├── prod/ # Prod-only code and resources ├── debug/ # Debug build type code └── release/ # Release build type code Multiple Flavor Dimensions (e.g., environment + tier): android { flavorDimensions += listOf ( "environment" , "tier" ) productFlavors { create ( "dev" ) { dimension = "environment" } create ( "prod" ) { dimension = "environment" } create ( "free" ) { dimension = "tier" } create ( "paid" ) { dimension = "tier" } } } // Results in: devFreeDebug, devPaidDebug, prodFreeRelease, etc. 3. Kotlin Development Standards 3.1 Naming Conventions Type Convention Example Class/Interface PascalCase UserRepository , MainActivity Function/Variable camelCase getUserName() , isLoading Constant SCREAMING_SNAKE MAX_RETRY_COUNT Package lowercase com.example.myapp Composable PascalCase @Composable fun UserCard() 3.2 Code Standards (Important) Null Safety : // ❌ Avoid: Non-null assertion !! (may crash) val name = user !! . name // ✅ Recommended: Safe call + default value val name = user ? . name ?: "Unknown" // ✅ Recommended: let handling user ? . let { processUser ( it ) } Exception Handling : // ❌ Avoid: Random try-catch in business layer swallowing exceptions fun loadData ( ) { try { val data = api . fetch ( ) } catch ( e : Exception ) { // Swallowing exception, hard to debug } } // ✅ Recommended: Let exceptions propagate, handle at appropriate layer suspend fun loadData ( ) : Result < Data

{ return try { Result . success ( api . fetch ( ) ) } catch ( e : Exception ) { Result . failure ( e ) // Wrap and return, let caller decide handling } } // ✅ Recommended: Unified handling in ViewModel viewModelScope . launch { runCatching { repository . loadData ( ) } . onSuccess { _uiState . value = UiState . Success ( it ) } . onFailure { _uiState . value = UiState . Error ( it . message ) } } 3.3 Threading & Coroutines (Critical) Thread Selection Principles : Operation Type Thread Description UI Updates Dispatchers.Main Update View, State, LiveData Network Requests Dispatchers.IO HTTP calls, API requests File I/O Dispatchers.IO Local storage, database operations Compute Intensive Dispatchers.Default JSON parsing, sorting, encryption Correct Usage : // In ViewModel viewModelScope . launch { // Default Main thread, can update UI State _uiState . value = UiState . Loading // Switch to IO thread for network request val result = withContext ( Dispatchers . IO ) { repository . fetchData ( ) } // Automatically returns to Main thread, update UI _uiState . value = UiState . Success ( result ) } // In Repository (suspend functions should be main-safe) suspend fun fetchData ( ) : Data = withContext ( Dispatchers . IO ) { api . getData ( ) } Common Mistakes : // ❌ Wrong: Updating UI on IO thread viewModelScope . launch ( Dispatchers . IO ) { val data = api . fetch ( ) _uiState . value = data // Crash or warning! } // ❌ Wrong: Executing time-consuming operation on Main thread viewModelScope . launch { val data = api . fetch ( ) // Blocking main thread! ANR } // ✅ Correct: Fetch on IO, update on Main viewModelScope . launch { val data = withContext ( Dispatchers . IO ) { api . fetch ( ) } _uiState . value = data } 3.4 Visibility Rules // Default is public, declare explicitly when needed class UserRepository { // public private val cache = mutableMapOf < String , User

( ) // Visible only within class internal fun clearCache ( ) { } // Visible only within module } // data class properties are public by default, be careful when used across modules data class User ( val id : String , // public val name : String ) 3.5 Common Syntax Pitfalls // ❌ Wrong: Accessing uninitialized lateinit class MyViewModel : ViewModel ( ) { lateinit var data : String fun process ( ) = data . length // May crash } // ✅ Correct: Use nullable or default value class MyViewModel : ViewModel ( ) { var data : String ? = null fun process ( ) = data ? . length ?: 0 } // ❌ Wrong: Using return in lambda list . forEach { item -> if ( item . isEmpty ( ) ) return // Returns from outer function! } // ✅ Correct: Use return@forEach list . forEach { item -> if ( item . isEmpty ( ) ) return @forEach } 3.6 Server Response Data Class Fields Must Be Nullable // ❌ Wrong: Fields declared as non-null (server may not return them) data class UserResponse ( val id : String = "" , val name : String = "" , val avatar : String = "" ) // ✅ Correct: All fields declared as nullable data class UserResponse ( @SerializedName ( "id" ) val id : String ? = null , @SerializedName ( "name" ) val name : String ? = null , @SerializedName ( "avatar" ) val avatar : String ? = null ) 3.7 Lifecycle Resource Management // ❌ Wrong: Only adding Observer, not removing class MyView : View { override fun onAttachedToWindow ( ) { super . onAttachedToWindow ( ) activity ? . lifecycle ? . addObserver ( this ) } // Memory leak! } // ✅ Correct: Paired add and remove class MyView : View { override fun onAttachedToWindow ( ) { super . onAttachedToWindow ( ) activity ? . lifecycle ? . addObserver ( this ) } override fun onDetachedFromWindow ( ) { activity ? . lifecycle ? . removeObserver ( this ) super . onDetachedFromWindow ( ) } } 3.8 Logging Level Usage import android . util . Log // Info: Key checkpoints in normal flow Log . i ( TAG , "loadData: started, userId = $ userId " ) // Warning: Abnormal but recoverable situations Log . w ( TAG , "loadData: cache miss, fallback to network" ) // Error: Failure/error situations Log . e ( TAG , "loadData failed: ${ error . message } " ) Level Use Case i (Info) Normal flow, method entry, key parameters w (Warning) Recoverable exceptions, fallback handling, null returns e (Error) Request failures, caught exceptions, unrecoverable errors 4. Jetpack Compose Standards 4.1 @Composable Context Rules // ❌ Wrong: Calling Composable from non-Composable function fun showError ( message : String ) { Text ( message ) // Compile error! } // ✅ Correct: Mark as @Composable @Composable fun ErrorMessage ( message : String ) { Text ( message ) } // ❌ Wrong: Using suspend outside LaunchedEffect @Composable fun MyScreen ( ) { val data = fetchData ( ) // Error! } // ✅ Correct: Use LaunchedEffect @Composable fun MyScreen ( ) { var data by remember { mutableStateOf < Data ?

( null ) } LaunchedEffect ( Unit ) { data = fetchData ( ) } } 4.2 State Management // Basic State var count by remember { mutableStateOf ( 0 ) } // Derived State (avoid redundant computation) val isEven by remember { derivedStateOf { count % 2 == 0 } } // Persist across recomposition (e.g., scroll position) val scrollState = rememberScrollState ( ) // State in ViewModel class MyViewModel : ViewModel ( ) { private val _uiState = MutableStateFlow ( UiState ( ) ) val uiState : StateFlow < UiState

= _uiState . asStateFlow ( ) } 4.3 Common Compose Mistakes // ❌ Wrong: Creating objects in Composable (created on every recomposition) @Composable fun MyScreen ( ) { val viewModel = MyViewModel ( ) // Wrong! } // ✅ Correct: Use viewModel() or remember @Composable fun MyScreen ( viewModel : MyViewModel = viewModel ( ) ) { // ... } 5. Resources & Icons 5.1 App Icon Requirements Must provide multi-resolution icons: Directory Size Purpose mipmap-mdpi 48x48 Baseline mipmap-hdpi 72x72 1.5x mipmap-xhdpi 96x96 2x mipmap-xxhdpi 144x144 3x mipmap-xxxhdpi 192x192 4x Recommended: Use Adaptive Icon (Android 8+):

< adaptive-icon

background android: drawable = " @color/ic_launcher_background " / foreground android: drawable = " @mipmap/ic_launcher_foreground " / </ adaptive-icon

5.2 Resource Naming Conventions Type Prefix Example Layout layout_ layout_main.xml Image ic_, img_, bg_ ic_user.png Color color_ color_primary String - app_name , btn_submit 5.3 Avoid Android Reserved Names (Important) Variable names, resource IDs, colors, icons, and XML elements must not use Android reserved words or system resource names. Using reserved names causes build errors or resource conflicts. Common Reserved Names to Avoid : Category Reserved Names (Do NOT Use) Colors background , foreground , transparent , white , black Icons/Drawables icon , logo , image , drawable Views view , text , button , layout , container Attributes id , name , type , style , theme , color System app , android , content , data , action Examples :

< color name = " background "

FFFFFF

</ color

< color name = " icon "

000000

</ color

< color name = " app_background "

FFFFFF

</ color

< color name = " icon_primary "

000000

</ color

// ❌ Wrong: Variable names conflict with system val icon = R . drawable . my_icon val background = Color . White // ✅ Correct: Use descriptive names val appIcon = R . drawable . my_icon val screenBackground = Color . White

ImageView android: src = " @drawable/icon " /

<
ImageView
android:
src
=
"
@drawable/ic_home
"
/>
6. Build Error Diagnosis & Fixes
6.1 Common Error Quick Reference
Error Keyword
Cause
Fix
Unresolved reference
Missing import or undefined
Check imports, verify dependencies
Type mismatch
Type incompatibility
Check parameter types, add conversion
Cannot access
Visibility issue
Check public/private/internal
@Composable invocations
Composable context error
Ensure caller is also @Composable
Duplicate class
Dependency conflict
Use
./gradlew dependencies
to investigate
AAPT: error
Resource file error
Check XML syntax and resource references
6.2 Fix Best Practices
Read the complete error message first
Locate file and line number
Check recent changes
Problems usually in latest modifications
Clean Build
:
./gradlew clean assembleDebug
Check dependency versions
Version conflicts are common causes
Refresh dependencies if needed
Clear cache and rebuild 6.3 Debugging Commands

Clean and build

./gradlew clean assembleDebug

View dependency tree (investigate conflicts)

./gradlew :app:dependencies

View detailed errors

./gradlew assembleDebug --stacktrace

Refresh dependencies

./gradlew --refresh-dependencies
7. Material Design 3 Guidelines
Review Android UI files for compliance with Material Design 3 Guidelines and Android best practices.
Design Philosophy
M3 Core Principles
Principle
Description
Personal
Dynamic color based on user preferences and wallpaper
Adaptive
Responsive across all screen sizes and form factors
Expressive
Bold colors and typography with personality
Accessible
Inclusive design for all users
M3 Expressive (Latest)
The latest evolution adds emotion-driven UX through:
Vibrant, dynamic colors
Intuitive motion physics
Adaptive components
Flexible typography
Contrasting shapes (35 new shape options)
App Style Selection
Critical Decision
Match visual style to app category and target audience.
App Category
Visual Style
Key Characteristics
Utility/Tool
Minimalist
Clean, efficient, neutral colors
Finance/Banking
Professional Trust
Conservative colors, security-focused
Health/Wellness
Calm & Natural
Soft colors, organic shapes
Kids (3-5)
Playful Simple
Bright colors, large targets (56dp+)
Kids (6-12)
Fun & Engaging
Vibrant, gamified feedback
Social/Entertainment
Expressive
Brand-driven, gesture-rich
Productivity
Clean & Focused
Minimal, high contrast
E-commerce
Conversion-focused
Clear CTAs, scannable
See
Design Style Guide
for detailed style profiles.
Quick Reference: Key Specifications
Color Contrast Requirements
Element
Minimum Ratio
Body text
4.5:1
Large text (18sp+)
3:1
UI components
3:1
Touch Targets
Type
Size
Minimum
48 × 48dp
Recommended (primary actions)
56 × 56dp
Kids apps
56dp+
Spacing between targets
8dp minimum
8dp Grid System
Token
Value
Usage
xs
4dp
Icon padding
sm
8dp
Tight spacing
md
16dp
Default padding
lg
24dp
Section spacing
xl
32dp
Large gaps
xxl
48dp
Screen margins
Typography Scale (Summary)
Category
Sizes
Display
57sp, 45sp, 36sp
Headline
32sp, 28sp, 24sp
Title
22sp, 16sp, 14sp
Body
16sp, 14sp, 12sp
Label
14sp, 12sp, 11sp
Animation Duration
Type
Duration
Micro (ripples)
50-100ms
Short (simple)
100-200ms
Medium (expand/collapse)
200-300ms
Long (complex)
300-500ms
Component Dimensions
Component
Height
Min Width
Button
40dp
64dp
FAB
56dp
56dp
Text Field
56dp
280dp
App Bar
64dp
-
Bottom Nav
80dp
-
Anti-Patterns (Must Avoid)
UI Anti-Patterns
More than 5 bottom navigation items
Multiple FABs on same screen
Touch targets smaller than 48dp
Inconsistent spacing (non-8dp multiples)
Missing dark theme support
Text on colored backgrounds without contrast check
Performance Anti-Patterns
Startup time > 2 seconds without progress indicator
Frame rate < 60 FPS (> 16ms per frame)
Crash rate > 1.09% (Google Play threshold)
ANR rate > 0.47% (Google Play threshold)
Accessibility Anti-Patterns
Missing contentDescription on interactive elements
Element type in labels (e.g., "Save button" instead of "Save")
Complex gestures in kids apps
Text-only buttons for non-readers
Review Checklist
8dp spacing grid compliance
48dp minimum touch targets
Proper typography scale usage
Color contrast compliance (4.5:1+ for text)
Dark theme support
contentDescription on all interactive elements
Startup < 2 seconds or shows progress
Visual style matches app category
Design References
Topic
Reference
Colors, Typography, Spacing, Shapes
Visual Design
Animation & Transitions
Motion System
Accessibility Guidelines
Accessibility
Large Screens & Foldables
Adaptive Screens
Android Vitals & Performance
Performance & Stability
Privacy & Security
Privacy & Security
Audio, Video, Notifications
Functional Requirements
App Style by Category
Design Style Guide
8. Testing
Note
Only add test dependencies when the user explicitly asks for testing.
A well-tested Android app uses layered testing: fast local unit tests for logic, instrumentation tests for UI and integration, and Gradle Managed Devices to run emulators reproducibly on any machine — including CI.
8.1 Test Dependencies
Before adding test dependencies, inspect the project's existing versions to avoid conflicts:
Check
gradle/libs.versions.toml
— if present, add test deps using the project's version catalog style
Check existing
build.gradle.kts
for already-pinned dependency versions
Match version families using the table below
Version Alignment Rules
:
Test Dependency
Must Align With
How to Check
kotlinx-coroutines-test
Project's
kotlinx-coroutines-core
version
Search for
kotlinx-coroutines
in build files or version catalog
compose-ui-test-junit4
Project's Compose BOM or
compose-compiler
Search for
compose-bom
or
compose.compiler
in build files
espresso-*
All Espresso artifacts must use the same version
Search for
espresso
in build files
androidx.test:runner
,
rules
,
ext:junit
Should use compatible AndroidX Test versions
Search for
androidx.test
in build files
mockk
Must support the project's Kotlin version
Check
kotlin
version in root
build.gradle.kts
or version catalog
Dependencies Reference
— add only the groups you need:
dependencies
{
// --- Local unit tests (src/test/) ---
testImplementation
(
"junit:junit:"
)
// 4.13.2+
testImplementation
(
"org.robolectric:robolectric:"
)
// 4.16.1+
testImplementation
(
"io.mockk:mockk:"
)
// match Kotlin version
testImplementation
(
"org.jetbrains.kotlinx:kotlinx-coroutines-test:"
)
// match coroutines-core
testImplementation
(
"androidx.arch.core:core-testing:"
)
// InstantTaskExecutorRule for LiveData
testImplementation
(
"app.cash.turbine:turbine:"
)
// Flow/StateFlow testing
// --- Instrumentation tests (src/androidTest/) ---
androidTestImplementation
(
"androidx.test.ext:junit:"
)
androidTestImplementation
(
"androidx.test:runner:"
)
androidTestImplementation
(
"androidx.test:rules:"
)
androidTestImplementation
(
"androidx.test.espresso:espresso-core:"
)
androidTestImplementation
(
"androidx.test.espresso:espresso-contrib:"
)
// RecyclerView, Drawer
androidTestImplementation
(
"androidx.test.espresso:espresso-intents:"
)
// Intent verification
androidTestImplementation
(
"androidx.test.espresso:espresso-idling-resource:"
)
androidTestImplementation
(
"androidx.test.uiautomator:uiautomator:"
)
// --- Compose UI tests (only if project uses Compose) ---
androidTestImplementation
(
"androidx.compose.ui:ui-test-junit4"
)
// version from Compose BOM
debugImplementation
(
"androidx.compose.ui:ui-test-manifest"
)
// required for createComposeRule
}
Note
If the project uses a Compose BOM, ui-test-junit4 and ui-test-manifest don't need explicit versions — the BOM manages them. Enable Robolectric resource support in the android block: android { testOptions { unitTests . isIncludeAndroidResources = true // required for Robolectric } } 8.2 Testing by Layer Layer Location Runs On Speed Use For Unit (JUnit) src/test/ JVM ~ms ViewModels, repos, mappers, validators Unit + Robolectric src/test/ JVM + simulated Android ~100ms Code needing Context, resources, SharedPrefs Compose UI (local) src/test/ JVM + Robolectric ~100ms Composable rendering & interaction Espresso src/androidTest/ Device/Emulator ~seconds View-based UI flows, Intents, DB integration Compose UI (device) src/androidTest/ Device/Emulator ~seconds Full Compose UI flows with real rendering UI Automator src/androidTest/ Device/Emulator ~seconds System dialogs, notifications, multi-app Managed Device src/androidTest/ Gradle-managed AVD ~minutes (first run) CI, matrix testing across API levels See Testing for detailed examples, code patterns, and Gradle Managed Device configuration. 8.3 Testing Commands

Local unit tests (fast, no emulator)

./gradlew test

all modules

./gradlew :app:testDebugUnitTest

app module, debug variant

Single test class

./gradlew :app:testDebugUnitTest --tests "com.example.myapp.CounterViewModelTest"

Instrumentation tests (requires device or managed device)

./gradlew connectedDebugAndroidTest

on connected device

./gradlew pixel6Api34DebugAndroidTest

on managed device

Both together

./gradlew test connectedDebugAndroidTest

Test with coverage report (JaCoCo)

./gradlew testDebugUnitTest jacocoTestReport

返回排行榜