android-sdd 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +143 -0
- package/package.json +27 -0
- package/skills/Android Ecosystem/Baseline Profile Generator/SKILL.md +277 -0
- package/skills/Android Ecosystem/Glance/SKILL.md +315 -0
- package/skills/Android Platform/Configuration/SKILL.md +201 -0
- package/skills/Android Platform/Filesystem/SKILL.md +216 -0
- package/skills/Android Platform/Lifecycle/SKILL.md +233 -0
- package/skills/Android Platform/Manifest/SKILL.md +226 -0
- package/skills/Android Platform/Process Death Recovery/SKILL.md +214 -0
- package/skills/Android Platform/Resources/SKILL.md +234 -0
- package/skills/Android Platform/SavedStateHandle/SKILL.md +217 -0
- package/skills/Android Platform/State Restoration/SKILL.md +210 -0
- package/skills/Architecture/Bounded Context/SKILL.md +207 -0
- package/skills/Architecture/Clean Architecture/SKILL.md +229 -0
- package/skills/Architecture/Domain Modeling/SKILL.md +236 -0
- package/skills/Architecture/Entity Design/SKILL.md +243 -0
- package/skills/Architecture/Feature Isolation/SKILL.md +216 -0
- package/skills/Architecture/MVI/SKILL.md +224 -0
- package/skills/Architecture/MVVM/SKILL.md +198 -0
- package/skills/Architecture/Modularization/SKILL.md +194 -0
- package/skills/Architecture/Offline First/SKILL.md +249 -0
- package/skills/Architecture/Repository Pattern/SKILL.md +216 -0
- package/skills/Architecture/Side Effect Management/SKILL.md +278 -0
- package/skills/Architecture/State Management/SKILL.md +229 -0
- package/skills/Architecture/Unidirectional Data Flow/SKILL.md +196 -0
- package/skills/Architecture/Use Case Design/SKILL.md +244 -0
- package/skills/Architecture/Value Object/SKILL.md +226 -0
- package/skills/Build Infrastructure/Build Orchestration/SKILL.md +257 -0
- package/skills/Build Infrastructure/Dependency Compatibility Resolver/SKILL.md +259 -0
- package/skills/Build Infrastructure/Environment Validator/SKILL.md +311 -0
- package/skills/Build System/Build Cache/SKILL.md +233 -0
- package/skills/Build System/Build Flavor Strategy/SKILL.md +171 -0
- package/skills/Build System/Build Variant/SKILL.md +215 -0
- package/skills/Build System/Convention Plugin/SKILL.md +288 -0
- package/skills/Build System/Dependency Management/SKILL.md +261 -0
- package/skills/Build System/Gradle/SKILL.md +284 -0
- package/skills/Build System/Incremental Build/SKILL.md +199 -0
- package/skills/Build System/KAPT/SKILL.md +198 -0
- package/skills/Build System/KSP/SKILL.md +263 -0
- package/skills/Build System/Module Dependency Graph Validation/SKILL.md +223 -0
- package/skills/Build System/Specialized/C++/SKILL.md +308 -0
- package/skills/Build System/Specialized/JNI/SKILL.md +306 -0
- package/skills/Build System/Specialized/NDK/SKILL.md +264 -0
- package/skills/Build System/Version Catalog/SKILL.md +304 -0
- package/skills/Concurrency/Background Processing/SKILL.md +185 -0
- package/skills/Concurrency/Channel/SKILL.md +207 -0
- package/skills/Concurrency/Coroutine/SKILL.md +200 -0
- package/skills/Concurrency/Flow/SKILL.md +179 -0
- package/skills/Concurrency/Mutex Strategy/SKILL.md +185 -0
- package/skills/Concurrency/SharedFlow/SKILL.md +171 -0
- package/skills/Concurrency/StateFlow/SKILL.md +175 -0
- package/skills/Concurrency/Structured Concurrency/SKILL.md +197 -0
- package/skills/Concurrency/Synchronization Policy/SKILL.md +192 -0
- package/skills/Core Language/Annotation Processing/SKILL.md +224 -0
- package/skills/Core Language/DSL/SKILL.md +186 -0
- package/skills/Core Language/Extension Functions Design/SKILL.md +191 -0
- package/skills/Core Language/Immutability/SKILL.md +156 -0
- package/skills/Core Language/KMP/SKILL.md +182 -0
- package/skills/Core Language/Kotlin/SKILL.md +187 -0
- package/skills/Core Language/Reactive State Management/SKILL.md +228 -0
- package/skills/Core Language/Reactive Streams/SKILL.md +235 -0
- package/skills/Core Language/Serialization/SKILL.md +191 -0
- package/skills/Data Layer/Cache Strategy/SKILL.md +261 -0
- package/skills/Data Layer/Conflict Resolution/SKILL.md +248 -0
- package/skills/Data Layer/DAO/SKILL.md +225 -0
- package/skills/Data Layer/DTO Mapping/SKILL.md +269 -0
- package/skills/Data Layer/DataStore/SKILL.md +264 -0
- package/skills/Data Layer/Database Versioning Strategy/SKILL.md +215 -0
- package/skills/Data Layer/Encrypted Database/SKILL.md +212 -0
- package/skills/Data Layer/File Storage/SKILL.md +247 -0
- package/skills/Data Layer/Indexing/SKILL.md +184 -0
- package/skills/Data Layer/Key-Value Store Strategy/SKILL.md +185 -0
- package/skills/Data Layer/Merge Strategy/SKILL.md +240 -0
- package/skills/Data Layer/Migration/SKILL.md +243 -0
- package/skills/Data Layer/Paging/SKILL.md +264 -0
- package/skills/Data Layer/Proto DataStore/SKILL.md +250 -0
- package/skills/Data Layer/Room/SKILL.md +244 -0
- package/skills/Data Layer/SQLite/SKILL.md +255 -0
- package/skills/Data Layer/Sync Engine/SKILL.md +268 -0
- package/skills/Dependency Injection/Dagger/SKILL.md +283 -0
- package/skills/Dependency Injection/Hilt/SKILL.md +345 -0
- package/skills/Dependency Injection/Koin/SKILL.md +282 -0
- package/skills/Developer Experience/Detekt/SKILL.md +272 -0
- package/skills/Developer Experience/Lint Rule/SKILL.md +281 -0
- package/skills/Google Ecosystem/Analytics/SKILL.md +281 -0
- package/skills/Google Ecosystem/Crashlytics/SKILL.md +234 -0
- package/skills/Google Ecosystem/Firebase/SKILL.md +200 -0
- package/skills/Google Ecosystem/Firebase Messaging/SKILL.md +266 -0
- package/skills/Media/Audio/SKILL.md +257 -0
- package/skills/Media/Camera/SKILL.md +229 -0
- package/skills/Media/CameraX/SKILL.md +295 -0
- package/skills/Media/ExoPlayer/SKILL.md +258 -0
- package/skills/Media/Video/SKILL.md +228 -0
- package/skills/Meta Skills/Domain Error Model/SKILL.md +238 -0
- package/skills/Meta Skills/Error Handling/SKILL.md +255 -0
- package/skills/Meta Skills/Error Mapping/SKILL.md +232 -0
- package/skills/Meta Skills/Failure Strategy/SKILL.md +294 -0
- package/skills/Meta Skills/Migration Strategy/SKILL.md +305 -0
- package/skills/Meta Skills/User Friendly Errors/SKILL.md +334 -0
- package/skills/Navigation/Deep Navigation/SKILL.md +209 -0
- package/skills/Navigation/Navigation/SKILL.md +215 -0
- package/skills/Navigation/Nested Navigation/SKILL.md +214 -0
- package/skills/Networking/API Contract/SKILL.md +220 -0
- package/skills/Networking/Authentication/SKILL.md +210 -0
- package/skills/Networking/Certificate Pinning/SKILL.md +167 -0
- package/skills/Networking/Fallback Strategy/SKILL.md +182 -0
- package/skills/Networking/Ktor/SKILL.md +219 -0
- package/skills/Networking/Multipart Upload/SKILL.md +213 -0
- package/skills/Networking/OkHttp/SKILL.md +193 -0
- package/skills/Networking/REST/SKILL.md +178 -0
- package/skills/Networking/Rate Limiting/SKILL.md +170 -0
- package/skills/Networking/Retrofit/SKILL.md +241 -0
- package/skills/Networking/Retry-Backoff/SKILL.md +181 -0
- package/skills/Networking/Server-Sent Events (SSE)/SKILL.md +196 -0
- package/skills/Networking/WebSocket/SKILL.md +224 -0
- package/skills/Observability/Crash Reporting/SKILL.md +219 -0
- package/skills/Observability/Logging/SKILL.md +168 -0
- package/skills/Observability/Metrics/SKILL.md +227 -0
- package/skills/Observability/Structured Logging/SKILL.md +234 -0
- package/skills/Performance/ANR Prevention/SKILL.md +192 -0
- package/skills/Performance/Allocation Optimization/SKILL.md +179 -0
- package/skills/Performance/App Startup/SKILL.md +183 -0
- package/skills/Performance/Baseline Profile/SKILL.md +205 -0
- package/skills/Performance/Battery Optimization/SKILL.md +192 -0
- package/skills/Performance/Benchmark/SKILL.md +182 -0
- package/skills/Performance/Bitmap Optimization/SKILL.md +178 -0
- package/skills/Performance/Compose Optimization/SKILL.md +187 -0
- package/skills/Performance/Heap Management/SKILL.md +184 -0
- package/skills/Performance/Macrobenchmark/SKILL.md +214 -0
- package/skills/Performance/Memory Leak Prevention/SKILL.md +218 -0
- package/skills/Performance/Rendering Performance/SKILL.md +205 -0
- package/skills/Performance/Startup Optimization/SKILL.md +219 -0
- package/skills/Security/Biometric/SKILL.md +224 -0
- package/skills/Security/Certificate Transparency/SKILL.md +158 -0
- package/skills/Security/Cryptography/SKILL.md +244 -0
- package/skills/Security/Encrypted Storage/SKILL.md +273 -0
- package/skills/Security/Frida Detection/SKILL.md +230 -0
- package/skills/Security/Hook Detection/SKILL.md +197 -0
- package/skills/Security/Keystore/SKILL.md +272 -0
- package/skills/Security/Network Security Config/SKILL.md +186 -0
- package/skills/Security/Obfuscation/SKILL.md +226 -0
- package/skills/Security/Proguard/SKILL.md +202 -0
- package/skills/Security/R8/SKILL.md +234 -0
- package/skills/Security/Reverse Engineering Resistance/SKILL.md +267 -0
- package/skills/Security/Root Detection/SKILL.md +220 -0
- package/skills/Security/Secure Networking/SKILL.md +220 -0
- package/skills/System Integration/AlarmManager/SKILL.md +182 -0
- package/skills/System Integration/App Widget/SKILL.md +182 -0
- package/skills/System Integration/Deep Link/SKILL.md +187 -0
- package/skills/System Integration/Foreground Service/SKILL.md +212 -0
- package/skills/System Integration/Notification/SKILL.md +237 -0
- package/skills/System Integration/WorkManager/SKILL.md +256 -0
- package/skills/System Integration/clipboard/SKILL.md +155 -0
- package/skills/System Integration/share-intent/SKILL.md +182 -0
- package/skills/Testing/Compose Testing/SKILL.md +296 -0
- package/skills/Testing/Espresso/SKILL.md +292 -0
- package/skills/Testing/Fake Data/SKILL.md +245 -0
- package/skills/Testing/Integration Testing/SKILL.md +288 -0
- package/skills/Testing/Mocking/SKILL.md +229 -0
- package/skills/Testing/Snapshot Testing/SKILL.md +259 -0
- package/skills/Testing/UI Testing/SKILL.md +293 -0
- package/skills/Testing/Unit Testing/SKILL.md +309 -0
- package/skills/UI System/Bottom Sheet Patterns/SKILL.md +279 -0
- package/skills/UI System/Compose/SKILL.md +296 -0
- package/skills/UI System/Compose Animation/SKILL.md +281 -0
- package/skills/UI System/Compose Multiplatform/SKILL.md +261 -0
- package/skills/UI System/Compose Navigation/SKILL.md +255 -0
- package/skills/UI System/Compose Performance/SKILL.md +274 -0
- package/skills/UI System/Design System/SKILL.md +217 -0
- package/skills/UI System/Empty State Strategy/SKILL.md +208 -0
- package/skills/UI System/Keyboard Navigation/SKILL.md +214 -0
- package/skills/UI System/Loading Strategy/SKILL.md +254 -0
- package/skills/UI System/Material 3/SKILL.md +279 -0
- package/skills/UI System/RTL/SKILL.md +179 -0
- package/src/index.ts +182 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-variant
|
|
3
|
+
description: >
|
|
4
|
+
Android build types and product flavors for managing multiple build variants.
|
|
5
|
+
Load this skill when configuring debug/release builds, multiple environments
|
|
6
|
+
(dev/staging/prod), or feature-based flavors.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Build Variant
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
Build variants are the combination of build types and product flavors. Build types define how the app is built (debug vs release), product flavors define what is built (dev vs prod, free vs paid). Every combination produces a distinct variant — e.g., `devDebug`, `prodRelease`.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Core Principles
|
|
17
|
+
|
|
18
|
+
- **Build types** = how to build (debug, release, staging)
|
|
19
|
+
- **Product flavors** = what to build (dev, prod, free, paid)
|
|
20
|
+
- Use **BuildConfig fields** for environment-specific values — not hardcoded strings
|
|
21
|
+
- Each variant can have its own `google-services.json` and resources
|
|
22
|
+
- Minimize the number of variants — complexity grows exponentially
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Build Types
|
|
27
|
+
|
|
28
|
+
```kotlin
|
|
29
|
+
android {
|
|
30
|
+
buildTypes {
|
|
31
|
+
|
|
32
|
+
debug {
|
|
33
|
+
isDebuggable = true
|
|
34
|
+
isMinifyEnabled = false
|
|
35
|
+
applicationIdSuffix = ".debug"
|
|
36
|
+
versionNameSuffix = "-debug"
|
|
37
|
+
buildConfigField("String", "API_URL", "\"https://dev.api.example.com/\"")
|
|
38
|
+
buildConfigField("Boolean", "ENABLE_LOGGING", "true")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
release {
|
|
42
|
+
isDebuggable = false
|
|
43
|
+
isMinifyEnabled = true
|
|
44
|
+
isShrinkResources = true
|
|
45
|
+
proguardFiles(
|
|
46
|
+
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
47
|
+
"proguard-rules.pro"
|
|
48
|
+
)
|
|
49
|
+
buildConfigField("String", "API_URL", "\"https://api.example.com/\"")
|
|
50
|
+
buildConfigField("Boolean", "ENABLE_LOGGING", "false")
|
|
51
|
+
signingConfig = signingConfigs.getByName("release")
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ✅ Custom build type — staging
|
|
55
|
+
create("staging") {
|
|
56
|
+
initWith(getByName("release")) // inherit from release
|
|
57
|
+
isDebuggable = true
|
|
58
|
+
applicationIdSuffix = ".staging"
|
|
59
|
+
versionNameSuffix = "-staging"
|
|
60
|
+
buildConfigField("String", "API_URL", "\"https://staging.api.example.com/\"")
|
|
61
|
+
buildConfigField("Boolean", "ENABLE_LOGGING", "true")
|
|
62
|
+
matchingFallbacks += listOf("release") // fallback for dependencies
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Product Flavors
|
|
71
|
+
|
|
72
|
+
```kotlin
|
|
73
|
+
android {
|
|
74
|
+
flavorDimensions += listOf("environment", "tier")
|
|
75
|
+
|
|
76
|
+
productFlavors {
|
|
77
|
+
|
|
78
|
+
// Environment dimension
|
|
79
|
+
create("dev") {
|
|
80
|
+
dimension = "environment"
|
|
81
|
+
applicationIdSuffix = ".dev"
|
|
82
|
+
versionNameSuffix = "-dev"
|
|
83
|
+
buildConfigField("String", "ENVIRONMENT", "\"dev\"")
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
create("prod") {
|
|
87
|
+
dimension = "environment"
|
|
88
|
+
buildConfigField("String", "ENVIRONMENT", "\"prod\"")
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Tier dimension
|
|
92
|
+
create("free") {
|
|
93
|
+
dimension = "tier"
|
|
94
|
+
buildConfigField("Boolean", "IS_PREMIUM", "false")
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
create("premium") {
|
|
98
|
+
dimension = "tier"
|
|
99
|
+
buildConfigField("Boolean", "IS_PREMIUM", "true")
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Resulting variants:
|
|
105
|
+
// devFreeDebug, devFreeRelease
|
|
106
|
+
// devPremiumDebug, devPremiumRelease
|
|
107
|
+
// prodFreeDebug, prodFreeRelease
|
|
108
|
+
// prodPremiumDebug, prodPremiumRelease
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Flavor-Specific Source Sets
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
app/src/
|
|
117
|
+
├── main/ ← shared for all variants
|
|
118
|
+
├── debug/ ← debug build type only
|
|
119
|
+
│ └── google-services.json
|
|
120
|
+
├── release/ ← release build type only
|
|
121
|
+
│ └── google-services.json
|
|
122
|
+
├── dev/ ← dev flavor only
|
|
123
|
+
│ ├── java/
|
|
124
|
+
│ │ └── com/example/app/
|
|
125
|
+
│ │ └── DevTools.kt
|
|
126
|
+
│ └── res/
|
|
127
|
+
│ └── values/
|
|
128
|
+
│ └── strings.xml ← override app_name for dev
|
|
129
|
+
├── prod/ ← prod flavor only
|
|
130
|
+
│ └── res/
|
|
131
|
+
│ └── values/
|
|
132
|
+
│ └── strings.xml
|
|
133
|
+
└── devDebug/ ← specific variant only
|
|
134
|
+
└── java/
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Variant-Specific Dependencies
|
|
140
|
+
|
|
141
|
+
```kotlin
|
|
142
|
+
dependencies {
|
|
143
|
+
// ✅ Debug-only dependencies
|
|
144
|
+
debugImplementation(libs.leakcanary)
|
|
145
|
+
debugImplementation(libs.compose.ui.tooling)
|
|
146
|
+
|
|
147
|
+
// ✅ Flavor-specific
|
|
148
|
+
"devImplementation"(libs.debug.drawer)
|
|
149
|
+
|
|
150
|
+
// ✅ Test
|
|
151
|
+
testImplementation(libs.junit)
|
|
152
|
+
androidTestImplementation(libs.espresso.core)
|
|
153
|
+
|
|
154
|
+
// ✅ Staging matches release dependencies
|
|
155
|
+
// (handled by matchingFallbacks)
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## BuildConfig Usage
|
|
162
|
+
|
|
163
|
+
```kotlin
|
|
164
|
+
// ✅ Access in code
|
|
165
|
+
class ApiConfig {
|
|
166
|
+
val baseUrl: String = BuildConfig.API_URL
|
|
167
|
+
val isLoggingEnabled: Boolean = BuildConfig.ENABLE_LOGGING
|
|
168
|
+
val environment: String = BuildConfig.ENVIRONMENT
|
|
169
|
+
val isPremium: Boolean = BuildConfig.IS_PREMIUM
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ✅ Conditional behavior
|
|
173
|
+
if (BuildConfig.DEBUG) {
|
|
174
|
+
Timber.plant(Timber.DebugTree())
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (BuildConfig.ENABLE_LOGGING) {
|
|
178
|
+
OkHttpClient.Builder().addInterceptor(HttpLoggingInterceptor())
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Variant Filtering
|
|
185
|
+
|
|
186
|
+
```kotlin
|
|
187
|
+
// ✅ Exclude unused variants to speed up build
|
|
188
|
+
android {
|
|
189
|
+
variantFilter {
|
|
190
|
+
// Ignore staging + free combination — doesn't make sense
|
|
191
|
+
if (flavors.any { it.name == "free" } && buildType.name == "staging") {
|
|
192
|
+
ignore = true
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Anti-Patterns
|
|
201
|
+
|
|
202
|
+
- Hardcoding API URLs — use `buildConfigField` per build type/flavor
|
|
203
|
+
- Too many dimensions — variants multiply, CI time explodes
|
|
204
|
+
- Not using `matchingFallbacks` for custom build types — dependency resolution fails
|
|
205
|
+
- Different logic in code for dev/prod via `if (BuildConfig.FLAVOR == "dev")` — use polymorphism or source sets
|
|
206
|
+
- Committing production `google-services.json` to version control unprotected
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Related Skills
|
|
211
|
+
- `gradle` — build system fundamentals
|
|
212
|
+
- `version-catalog` — dependency management per variant
|
|
213
|
+
- `convention-plugin` — shared build type configuration
|
|
214
|
+
- `build-flavor-strategy` — deciding on flavor structure
|
|
215
|
+
- `ci-cd` — building specific variants in CI
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: convention-plugin
|
|
3
|
+
description: >
|
|
4
|
+
Gradle convention plugins for sharing build logic across modules.
|
|
5
|
+
Load this skill when creating reusable build configuration,
|
|
6
|
+
eliminating duplication across module build files, or setting up
|
|
7
|
+
a build-logic module.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Convention Plugin
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
Convention plugins are Gradle plugins written in `build-logic/` that encapsulate shared build configuration. Instead of duplicating Android, Kotlin, and Hilt setup in every module's `build.gradle.kts`, each module applies a single convention plugin that contains all the shared logic.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Core Principles
|
|
18
|
+
|
|
19
|
+
- Convention plugins live in `build-logic/` — a separate included build
|
|
20
|
+
- Each plugin covers **one concern** — Android app, Android library, Compose, Hilt, etc.
|
|
21
|
+
- Modules apply **multiple small plugins** rather than one large plugin
|
|
22
|
+
- Convention plugins use the **Version Catalog** for all dependency/version references
|
|
23
|
+
- Changes to a convention plugin propagate to **all modules** that apply it
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Project Structure
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
build-logic/
|
|
31
|
+
├── settings.gradle.kts
|
|
32
|
+
└── convention/
|
|
33
|
+
├── build.gradle.kts
|
|
34
|
+
└── src/main/kotlin/
|
|
35
|
+
├── AndroidApplicationConventionPlugin.kt
|
|
36
|
+
├── AndroidLibraryConventionPlugin.kt
|
|
37
|
+
├── AndroidComposeConventionPlugin.kt
|
|
38
|
+
├── AndroidHiltConventionPlugin.kt
|
|
39
|
+
├── AndroidRoomConventionPlugin.kt
|
|
40
|
+
└── KotlinSerializationConventionPlugin.kt
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## build-logic Setup
|
|
46
|
+
|
|
47
|
+
```kotlin
|
|
48
|
+
// build-logic/settings.gradle.kts
|
|
49
|
+
dependencyResolutionManagement {
|
|
50
|
+
repositories {
|
|
51
|
+
google()
|
|
52
|
+
mavenCentral()
|
|
53
|
+
}
|
|
54
|
+
versionCatalogs {
|
|
55
|
+
create("libs") {
|
|
56
|
+
from(files("../gradle/libs.versions.toml"))
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
rootProject.name = "build-logic"
|
|
61
|
+
include(":convention")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```kotlin
|
|
65
|
+
// build-logic/convention/build.gradle.kts
|
|
66
|
+
plugins {
|
|
67
|
+
`kotlin-dsl`
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
dependencies {
|
|
71
|
+
compileOnly(libs.android.gradlePlugin)
|
|
72
|
+
compileOnly(libs.kotlin.gradlePlugin)
|
|
73
|
+
compileOnly(libs.ksp.gradlePlugin)
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```toml
|
|
78
|
+
# Add to libs.versions.toml for use in build-logic
|
|
79
|
+
[libraries]
|
|
80
|
+
android-gradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "agp" }
|
|
81
|
+
kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
|
82
|
+
ksp-gradlePlugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" }
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Android Application Plugin
|
|
88
|
+
|
|
89
|
+
```kotlin
|
|
90
|
+
// AndroidApplicationConventionPlugin.kt
|
|
91
|
+
class AndroidApplicationConventionPlugin : Plugin<Project> {
|
|
92
|
+
override fun apply(target: Project) {
|
|
93
|
+
with(target) {
|
|
94
|
+
with(pluginManager) {
|
|
95
|
+
apply("com.android.application")
|
|
96
|
+
apply("org.jetbrains.kotlin.android")
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
extensions.configure<ApplicationExtension> {
|
|
100
|
+
compileSdk = libs.findVersion("android-compileSdk").get().toString().toInt()
|
|
101
|
+
|
|
102
|
+
defaultConfig {
|
|
103
|
+
minSdk = libs.findVersion("android-minSdk").get().toString().toInt()
|
|
104
|
+
targetSdk = libs.findVersion("android-targetSdk").get().toString().toInt()
|
|
105
|
+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
compileOptions {
|
|
109
|
+
sourceCompatibility = JavaVersion.VERSION_17
|
|
110
|
+
targetCompatibility = JavaVersion.VERSION_17
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
kotlinOptions { jvmTarget = "17" }
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private val Project.libs
|
|
120
|
+
get(): VersionCatalog = extensions.getByType<VersionCatalogsExtension>().named("libs")
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Android Library Plugin
|
|
126
|
+
|
|
127
|
+
```kotlin
|
|
128
|
+
// AndroidLibraryConventionPlugin.kt
|
|
129
|
+
class AndroidLibraryConventionPlugin : Plugin<Project> {
|
|
130
|
+
override fun apply(target: Project) {
|
|
131
|
+
with(target) {
|
|
132
|
+
with(pluginManager) {
|
|
133
|
+
apply("com.android.library")
|
|
134
|
+
apply("org.jetbrains.kotlin.android")
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
extensions.configure<LibraryExtension> {
|
|
138
|
+
compileSdk = libs.findVersion("android-compileSdk").get().toString().toInt()
|
|
139
|
+
|
|
140
|
+
defaultConfig {
|
|
141
|
+
minSdk = libs.findVersion("android-minSdk").get().toString().toInt()
|
|
142
|
+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
143
|
+
consumerProguardFiles("consumer-rules.pro")
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
compileOptions {
|
|
147
|
+
sourceCompatibility = JavaVersion.VERSION_17
|
|
148
|
+
targetCompatibility = JavaVersion.VERSION_17
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
kotlinOptions { jvmTarget = "17" }
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Compose Plugin
|
|
161
|
+
|
|
162
|
+
```kotlin
|
|
163
|
+
// AndroidComposeConventionPlugin.kt
|
|
164
|
+
class AndroidComposeConventionPlugin : Plugin<Project> {
|
|
165
|
+
override fun apply(target: Project) {
|
|
166
|
+
with(target) {
|
|
167
|
+
pluginManager.apply("org.jetbrains.kotlin.plugin.compose")
|
|
168
|
+
|
|
169
|
+
val extension = extensions.findByType<CommonExtension<*, *, *, *, *, *>>()
|
|
170
|
+
?: error("Android plugin must be applied first")
|
|
171
|
+
|
|
172
|
+
extension.apply {
|
|
173
|
+
buildFeatures { compose = true }
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
dependencies {
|
|
177
|
+
val bom = libs.findLibrary("compose-bom").get()
|
|
178
|
+
add("implementation", platform(bom))
|
|
179
|
+
add("implementation", libs.findLibrary("compose-ui").get())
|
|
180
|
+
add("implementation", libs.findLibrary("compose-material3").get())
|
|
181
|
+
add("implementation", libs.findLibrary("compose-ui-tooling-preview").get())
|
|
182
|
+
add("debugImplementation", libs.findLibrary("compose-ui-tooling").get())
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Hilt Plugin
|
|
192
|
+
|
|
193
|
+
```kotlin
|
|
194
|
+
// AndroidHiltConventionPlugin.kt
|
|
195
|
+
class AndroidHiltConventionPlugin : Plugin<Project> {
|
|
196
|
+
override fun apply(target: Project) {
|
|
197
|
+
with(target) {
|
|
198
|
+
with(pluginManager) {
|
|
199
|
+
apply("com.google.dagger.hilt.android")
|
|
200
|
+
apply("com.google.devtools.ksp")
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
dependencies {
|
|
204
|
+
add("implementation", libs.findLibrary("hilt-android").get())
|
|
205
|
+
add("ksp", libs.findLibrary("hilt-compiler").get())
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Registering Plugins
|
|
215
|
+
|
|
216
|
+
```kotlin
|
|
217
|
+
// build-logic/convention/build.gradle.kts
|
|
218
|
+
gradlePlugin {
|
|
219
|
+
plugins {
|
|
220
|
+
register("androidApplication") {
|
|
221
|
+
id = "myapp.android.application"
|
|
222
|
+
implementationClass = "AndroidApplicationConventionPlugin"
|
|
223
|
+
}
|
|
224
|
+
register("androidLibrary") {
|
|
225
|
+
id = "myapp.android.library"
|
|
226
|
+
implementationClass = "AndroidLibraryConventionPlugin"
|
|
227
|
+
}
|
|
228
|
+
register("androidCompose") {
|
|
229
|
+
id = "myapp.android.compose"
|
|
230
|
+
implementationClass = "AndroidComposeConventionPlugin"
|
|
231
|
+
}
|
|
232
|
+
register("androidHilt") {
|
|
233
|
+
id = "myapp.android.hilt"
|
|
234
|
+
implementationClass = "AndroidHiltConventionPlugin"
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Usage in Modules
|
|
243
|
+
|
|
244
|
+
```kotlin
|
|
245
|
+
// app/build.gradle.kts
|
|
246
|
+
plugins {
|
|
247
|
+
id("myapp.android.application")
|
|
248
|
+
id("myapp.android.compose")
|
|
249
|
+
id("myapp.android.hilt")
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
android {
|
|
253
|
+
namespace = "com.example.app"
|
|
254
|
+
defaultConfig { applicationId = "com.example.app" }
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
dependencies {
|
|
258
|
+
implementation(projects.feature.home)
|
|
259
|
+
implementation(projects.core.network)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// feature/home/build.gradle.kts
|
|
263
|
+
plugins {
|
|
264
|
+
id("myapp.android.library")
|
|
265
|
+
id("myapp.android.compose")
|
|
266
|
+
id("myapp.android.hilt")
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
android { namespace = "com.example.feature.home" }
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Anti-Patterns
|
|
275
|
+
|
|
276
|
+
- One giant convention plugin for everything — hard to apply selectively
|
|
277
|
+
- Duplicating Android config across module build files — defeats the purpose
|
|
278
|
+
- Not using Version Catalog inside convention plugins — version drift
|
|
279
|
+
- Business logic in convention plugins — they configure, not implement
|
|
280
|
+
- Not including `build-logic` in `settings.gradle.kts` — plugins not found
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Related Skills
|
|
285
|
+
- `gradle` — Gradle fundamentals
|
|
286
|
+
- `version-catalog` — used inside convention plugins
|
|
287
|
+
- `build-variant` — build type config in convention plugins
|
|
288
|
+
- `modularization` — convention plugins enable consistent multi-module setup
|