android-development

Create production-quality Android applications following Google's official architecture guidance and NowInAndroid best practices. Use when building Android…

INSTALLATION
npx skills add https://github.com/dpconde/claude-android-skill --skill android-development
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$27

Adding a new feature?

→ Create feature module with api and impl submodules

→ Follow patterns in architecture.md

Building UI screens?

→ Read compose-patterns.md

→ Create Screen + ViewModel + UiState

Setting up data layer?

→ Read data layer section in architecture.md

→ Create Repository + DataSource + DAO

Core Principles

  • Offline-first: Local database is source of truth, sync with remote
  • Unidirectional data flow: Events flow down, data flows up
  • Reactive streams: Use Kotlin Flow for all data exposure
  • Modular by feature: Each feature is self-contained with clear boundaries
  • Testable by design: Use interfaces and test doubles, no mocking libraries

Architecture Layers

┌─────────────────────────────────────────┐

│              UI Layer                    │

│  (Compose Screens + ViewModels)          │

├─────────────────────────────────────────┤

│           Domain Layer                   │

│  (Use Cases - optional, for reuse)       │

├─────────────────────────────────────────┤

│            Data Layer                    │

│  (Repositories + DataSources)            │

└─────────────────────────────────────────┘

Module Types

app/                    # App module - navigation, scaffolding

feature/

  ├── featurename/

  │   ├── api/          # Navigation keys (public)

  │   └── impl/         # Screen, ViewModel, DI (internal)

core/

  ├── data/             # Repositories

  ├── database/         # Room DAOs, entities

  ├── network/          # Retrofit, API models

  ├── model/            # Domain models (pure Kotlin)

  ├── common/           # Shared utilities

  ├── ui/               # Reusable Compose components

  ├── designsystem/     # Theme, icons, base components

  ├── datastore/        # Preferences storage

  └── testing/          # Test utilities

Creating a New Feature

  • Create feature:myfeature:api module with navigation key
  • Create feature:myfeature:impl module with:
  • MyFeatureScreen.kt - Composable UI
  • MyFeatureViewModel.kt - State holder
  • MyFeatureUiState.kt - Sealed interface for states
  • MyFeatureNavigation.kt - Navigation setup
  • MyFeatureModule.kt - Hilt DI module

Standard File Patterns

ViewModel Pattern

@HiltViewModel

class MyFeatureViewModel @Inject constructor(

    private val myRepository: MyRepository,

) : ViewModel() {

    val uiState: StateFlow<MyFeatureUiState> = myRepository

        .getData()

        .map { data -> MyFeatureUiState.Success(data) }

        .stateIn(

            scope = viewModelScope,

            started = SharingStarted.WhileSubscribed(5_000),

            initialValue = MyFeatureUiState.Loading,

        )

    fun onAction(action: MyFeatureAction) {

        when (action) {

            is MyFeatureAction.ItemClicked -> handleItemClick(action.id)

        }

    }

}

UiState Pattern

sealed interface MyFeatureUiState {

    data object Loading : MyFeatureUiState

    data class Success(val items: List<Item>) : MyFeatureUiState

    data class Error(val message: String) : MyFeatureUiState

}

Screen Pattern

@Composable

internal fun MyFeatureRoute(

    onNavigateToDetail: (String) -> Unit,

    viewModel: MyFeatureViewModel = hiltViewModel(),

) {

    val uiState by viewModel.uiState.collectAsStateWithLifecycle()

    MyFeatureScreen(

        uiState = uiState,

        onAction = viewModel::onAction,

        onNavigateToDetail = onNavigateToDetail,

    )

}

@Composable

internal fun MyFeatureScreen(

    uiState: MyFeatureUiState,

    onAction: (MyFeatureAction) -> Unit,

    onNavigateToDetail: (String) -> Unit,

) {

    when (uiState) {

        is MyFeatureUiState.Loading -> LoadingIndicator()

        is MyFeatureUiState.Success -> ContentList(uiState.items, onAction)

        is MyFeatureUiState.Error -> ErrorMessage(uiState.message)

    }

}

Repository Pattern

interface MyRepository {

    fun getData(): Flow<List<MyModel>>

    suspend fun updateItem(id: String, data: MyModel)

}

internal class OfflineFirstMyRepository @Inject constructor(

    private val localDataSource: MyDao,

    private val networkDataSource: MyNetworkApi,

) : MyRepository {

    override fun getData(): Flow<List<MyModel>> =

        localDataSource.getAll().map { entities ->

            entities.map { it.toModel() }

        }

    override suspend fun updateItem(id: String, data: MyModel) {

        localDataSource.upsert(data.toEntity())

    }

}

Key Dependencies

// Gradle version catalog (libs.versions.toml)

[versions]

kotlin = "1.9.x"

compose-bom = "2024.x.x"

hilt = "2.48"

room = "2.6.x"

coroutines = "1.7.x"

[libraries]

androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }

hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }

room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }

Build Configuration

Use convention plugins in build-logic/ for consistent configuration:

  • AndroidApplicationConventionPlugin - App modules
  • AndroidLibraryConventionPlugin - Library modules
  • AndroidFeatureConventionPlugin - Feature modules
  • AndroidComposeConventionPlugin - Compose setup
  • AndroidHiltConventionPlugin - Hilt setup

See gradle-setup.md for complete build configuration.

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card