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.
Files changed (176) hide show
  1. package/dist/index.js +143 -0
  2. package/package.json +27 -0
  3. package/skills/Android Ecosystem/Baseline Profile Generator/SKILL.md +277 -0
  4. package/skills/Android Ecosystem/Glance/SKILL.md +315 -0
  5. package/skills/Android Platform/Configuration/SKILL.md +201 -0
  6. package/skills/Android Platform/Filesystem/SKILL.md +216 -0
  7. package/skills/Android Platform/Lifecycle/SKILL.md +233 -0
  8. package/skills/Android Platform/Manifest/SKILL.md +226 -0
  9. package/skills/Android Platform/Process Death Recovery/SKILL.md +214 -0
  10. package/skills/Android Platform/Resources/SKILL.md +234 -0
  11. package/skills/Android Platform/SavedStateHandle/SKILL.md +217 -0
  12. package/skills/Android Platform/State Restoration/SKILL.md +210 -0
  13. package/skills/Architecture/Bounded Context/SKILL.md +207 -0
  14. package/skills/Architecture/Clean Architecture/SKILL.md +229 -0
  15. package/skills/Architecture/Domain Modeling/SKILL.md +236 -0
  16. package/skills/Architecture/Entity Design/SKILL.md +243 -0
  17. package/skills/Architecture/Feature Isolation/SKILL.md +216 -0
  18. package/skills/Architecture/MVI/SKILL.md +224 -0
  19. package/skills/Architecture/MVVM/SKILL.md +198 -0
  20. package/skills/Architecture/Modularization/SKILL.md +194 -0
  21. package/skills/Architecture/Offline First/SKILL.md +249 -0
  22. package/skills/Architecture/Repository Pattern/SKILL.md +216 -0
  23. package/skills/Architecture/Side Effect Management/SKILL.md +278 -0
  24. package/skills/Architecture/State Management/SKILL.md +229 -0
  25. package/skills/Architecture/Unidirectional Data Flow/SKILL.md +196 -0
  26. package/skills/Architecture/Use Case Design/SKILL.md +244 -0
  27. package/skills/Architecture/Value Object/SKILL.md +226 -0
  28. package/skills/Build Infrastructure/Build Orchestration/SKILL.md +257 -0
  29. package/skills/Build Infrastructure/Dependency Compatibility Resolver/SKILL.md +259 -0
  30. package/skills/Build Infrastructure/Environment Validator/SKILL.md +311 -0
  31. package/skills/Build System/Build Cache/SKILL.md +233 -0
  32. package/skills/Build System/Build Flavor Strategy/SKILL.md +171 -0
  33. package/skills/Build System/Build Variant/SKILL.md +215 -0
  34. package/skills/Build System/Convention Plugin/SKILL.md +288 -0
  35. package/skills/Build System/Dependency Management/SKILL.md +261 -0
  36. package/skills/Build System/Gradle/SKILL.md +284 -0
  37. package/skills/Build System/Incremental Build/SKILL.md +199 -0
  38. package/skills/Build System/KAPT/SKILL.md +198 -0
  39. package/skills/Build System/KSP/SKILL.md +263 -0
  40. package/skills/Build System/Module Dependency Graph Validation/SKILL.md +223 -0
  41. package/skills/Build System/Specialized/C++/SKILL.md +308 -0
  42. package/skills/Build System/Specialized/JNI/SKILL.md +306 -0
  43. package/skills/Build System/Specialized/NDK/SKILL.md +264 -0
  44. package/skills/Build System/Version Catalog/SKILL.md +304 -0
  45. package/skills/Concurrency/Background Processing/SKILL.md +185 -0
  46. package/skills/Concurrency/Channel/SKILL.md +207 -0
  47. package/skills/Concurrency/Coroutine/SKILL.md +200 -0
  48. package/skills/Concurrency/Flow/SKILL.md +179 -0
  49. package/skills/Concurrency/Mutex Strategy/SKILL.md +185 -0
  50. package/skills/Concurrency/SharedFlow/SKILL.md +171 -0
  51. package/skills/Concurrency/StateFlow/SKILL.md +175 -0
  52. package/skills/Concurrency/Structured Concurrency/SKILL.md +197 -0
  53. package/skills/Concurrency/Synchronization Policy/SKILL.md +192 -0
  54. package/skills/Core Language/Annotation Processing/SKILL.md +224 -0
  55. package/skills/Core Language/DSL/SKILL.md +186 -0
  56. package/skills/Core Language/Extension Functions Design/SKILL.md +191 -0
  57. package/skills/Core Language/Immutability/SKILL.md +156 -0
  58. package/skills/Core Language/KMP/SKILL.md +182 -0
  59. package/skills/Core Language/Kotlin/SKILL.md +187 -0
  60. package/skills/Core Language/Reactive State Management/SKILL.md +228 -0
  61. package/skills/Core Language/Reactive Streams/SKILL.md +235 -0
  62. package/skills/Core Language/Serialization/SKILL.md +191 -0
  63. package/skills/Data Layer/Cache Strategy/SKILL.md +261 -0
  64. package/skills/Data Layer/Conflict Resolution/SKILL.md +248 -0
  65. package/skills/Data Layer/DAO/SKILL.md +225 -0
  66. package/skills/Data Layer/DTO Mapping/SKILL.md +269 -0
  67. package/skills/Data Layer/DataStore/SKILL.md +264 -0
  68. package/skills/Data Layer/Database Versioning Strategy/SKILL.md +215 -0
  69. package/skills/Data Layer/Encrypted Database/SKILL.md +212 -0
  70. package/skills/Data Layer/File Storage/SKILL.md +247 -0
  71. package/skills/Data Layer/Indexing/SKILL.md +184 -0
  72. package/skills/Data Layer/Key-Value Store Strategy/SKILL.md +185 -0
  73. package/skills/Data Layer/Merge Strategy/SKILL.md +240 -0
  74. package/skills/Data Layer/Migration/SKILL.md +243 -0
  75. package/skills/Data Layer/Paging/SKILL.md +264 -0
  76. package/skills/Data Layer/Proto DataStore/SKILL.md +250 -0
  77. package/skills/Data Layer/Room/SKILL.md +244 -0
  78. package/skills/Data Layer/SQLite/SKILL.md +255 -0
  79. package/skills/Data Layer/Sync Engine/SKILL.md +268 -0
  80. package/skills/Dependency Injection/Dagger/SKILL.md +283 -0
  81. package/skills/Dependency Injection/Hilt/SKILL.md +345 -0
  82. package/skills/Dependency Injection/Koin/SKILL.md +282 -0
  83. package/skills/Developer Experience/Detekt/SKILL.md +272 -0
  84. package/skills/Developer Experience/Lint Rule/SKILL.md +281 -0
  85. package/skills/Google Ecosystem/Analytics/SKILL.md +281 -0
  86. package/skills/Google Ecosystem/Crashlytics/SKILL.md +234 -0
  87. package/skills/Google Ecosystem/Firebase/SKILL.md +200 -0
  88. package/skills/Google Ecosystem/Firebase Messaging/SKILL.md +266 -0
  89. package/skills/Media/Audio/SKILL.md +257 -0
  90. package/skills/Media/Camera/SKILL.md +229 -0
  91. package/skills/Media/CameraX/SKILL.md +295 -0
  92. package/skills/Media/ExoPlayer/SKILL.md +258 -0
  93. package/skills/Media/Video/SKILL.md +228 -0
  94. package/skills/Meta Skills/Domain Error Model/SKILL.md +238 -0
  95. package/skills/Meta Skills/Error Handling/SKILL.md +255 -0
  96. package/skills/Meta Skills/Error Mapping/SKILL.md +232 -0
  97. package/skills/Meta Skills/Failure Strategy/SKILL.md +294 -0
  98. package/skills/Meta Skills/Migration Strategy/SKILL.md +305 -0
  99. package/skills/Meta Skills/User Friendly Errors/SKILL.md +334 -0
  100. package/skills/Navigation/Deep Navigation/SKILL.md +209 -0
  101. package/skills/Navigation/Navigation/SKILL.md +215 -0
  102. package/skills/Navigation/Nested Navigation/SKILL.md +214 -0
  103. package/skills/Networking/API Contract/SKILL.md +220 -0
  104. package/skills/Networking/Authentication/SKILL.md +210 -0
  105. package/skills/Networking/Certificate Pinning/SKILL.md +167 -0
  106. package/skills/Networking/Fallback Strategy/SKILL.md +182 -0
  107. package/skills/Networking/Ktor/SKILL.md +219 -0
  108. package/skills/Networking/Multipart Upload/SKILL.md +213 -0
  109. package/skills/Networking/OkHttp/SKILL.md +193 -0
  110. package/skills/Networking/REST/SKILL.md +178 -0
  111. package/skills/Networking/Rate Limiting/SKILL.md +170 -0
  112. package/skills/Networking/Retrofit/SKILL.md +241 -0
  113. package/skills/Networking/Retry-Backoff/SKILL.md +181 -0
  114. package/skills/Networking/Server-Sent Events (SSE)/SKILL.md +196 -0
  115. package/skills/Networking/WebSocket/SKILL.md +224 -0
  116. package/skills/Observability/Crash Reporting/SKILL.md +219 -0
  117. package/skills/Observability/Logging/SKILL.md +168 -0
  118. package/skills/Observability/Metrics/SKILL.md +227 -0
  119. package/skills/Observability/Structured Logging/SKILL.md +234 -0
  120. package/skills/Performance/ANR Prevention/SKILL.md +192 -0
  121. package/skills/Performance/Allocation Optimization/SKILL.md +179 -0
  122. package/skills/Performance/App Startup/SKILL.md +183 -0
  123. package/skills/Performance/Baseline Profile/SKILL.md +205 -0
  124. package/skills/Performance/Battery Optimization/SKILL.md +192 -0
  125. package/skills/Performance/Benchmark/SKILL.md +182 -0
  126. package/skills/Performance/Bitmap Optimization/SKILL.md +178 -0
  127. package/skills/Performance/Compose Optimization/SKILL.md +187 -0
  128. package/skills/Performance/Heap Management/SKILL.md +184 -0
  129. package/skills/Performance/Macrobenchmark/SKILL.md +214 -0
  130. package/skills/Performance/Memory Leak Prevention/SKILL.md +218 -0
  131. package/skills/Performance/Rendering Performance/SKILL.md +205 -0
  132. package/skills/Performance/Startup Optimization/SKILL.md +219 -0
  133. package/skills/Security/Biometric/SKILL.md +224 -0
  134. package/skills/Security/Certificate Transparency/SKILL.md +158 -0
  135. package/skills/Security/Cryptography/SKILL.md +244 -0
  136. package/skills/Security/Encrypted Storage/SKILL.md +273 -0
  137. package/skills/Security/Frida Detection/SKILL.md +230 -0
  138. package/skills/Security/Hook Detection/SKILL.md +197 -0
  139. package/skills/Security/Keystore/SKILL.md +272 -0
  140. package/skills/Security/Network Security Config/SKILL.md +186 -0
  141. package/skills/Security/Obfuscation/SKILL.md +226 -0
  142. package/skills/Security/Proguard/SKILL.md +202 -0
  143. package/skills/Security/R8/SKILL.md +234 -0
  144. package/skills/Security/Reverse Engineering Resistance/SKILL.md +267 -0
  145. package/skills/Security/Root Detection/SKILL.md +220 -0
  146. package/skills/Security/Secure Networking/SKILL.md +220 -0
  147. package/skills/System Integration/AlarmManager/SKILL.md +182 -0
  148. package/skills/System Integration/App Widget/SKILL.md +182 -0
  149. package/skills/System Integration/Deep Link/SKILL.md +187 -0
  150. package/skills/System Integration/Foreground Service/SKILL.md +212 -0
  151. package/skills/System Integration/Notification/SKILL.md +237 -0
  152. package/skills/System Integration/WorkManager/SKILL.md +256 -0
  153. package/skills/System Integration/clipboard/SKILL.md +155 -0
  154. package/skills/System Integration/share-intent/SKILL.md +182 -0
  155. package/skills/Testing/Compose Testing/SKILL.md +296 -0
  156. package/skills/Testing/Espresso/SKILL.md +292 -0
  157. package/skills/Testing/Fake Data/SKILL.md +245 -0
  158. package/skills/Testing/Integration Testing/SKILL.md +288 -0
  159. package/skills/Testing/Mocking/SKILL.md +229 -0
  160. package/skills/Testing/Snapshot Testing/SKILL.md +259 -0
  161. package/skills/Testing/UI Testing/SKILL.md +293 -0
  162. package/skills/Testing/Unit Testing/SKILL.md +309 -0
  163. package/skills/UI System/Bottom Sheet Patterns/SKILL.md +279 -0
  164. package/skills/UI System/Compose/SKILL.md +296 -0
  165. package/skills/UI System/Compose Animation/SKILL.md +281 -0
  166. package/skills/UI System/Compose Multiplatform/SKILL.md +261 -0
  167. package/skills/UI System/Compose Navigation/SKILL.md +255 -0
  168. package/skills/UI System/Compose Performance/SKILL.md +274 -0
  169. package/skills/UI System/Design System/SKILL.md +217 -0
  170. package/skills/UI System/Empty State Strategy/SKILL.md +208 -0
  171. package/skills/UI System/Keyboard Navigation/SKILL.md +214 -0
  172. package/skills/UI System/Loading Strategy/SKILL.md +254 -0
  173. package/skills/UI System/Material 3/SKILL.md +279 -0
  174. package/skills/UI System/RTL/SKILL.md +179 -0
  175. package/src/index.ts +182 -0
  176. package/tsconfig.json +19 -0
@@ -0,0 +1,304 @@
1
+ ---
2
+ name: version-catalog
3
+ description: >
4
+ Gradle Version Catalog setup and usage for Android projects.
5
+ Load this skill when managing dependency versions centrally,
6
+ adding new dependencies, or organizing libs.versions.toml.
7
+ ---
8
+
9
+ # Version Catalog
10
+
11
+ ## Overview
12
+ Gradle Version Catalog (`libs.versions.toml`) is the standard way to centralize all dependency versions in one file. It provides type-safe accessors in build scripts, prevents version conflicts, and makes upgrades visible in a single diff.
13
+
14
+ ---
15
+
16
+ ## Core Principles
17
+
18
+ - **All dependencies** go through Version Catalog — no inline versions anywhere
19
+ - Group related libraries under the same version alias when possible
20
+ - Use **bundles** for sets of dependencies that always go together
21
+ - Keep `libs.versions.toml` the **single source of truth** for all versions
22
+ - Separate **plugin versions** from library versions clearly
23
+
24
+ ---
25
+
26
+ ## File Structure
27
+
28
+ ```toml
29
+ # gradle/libs.versions.toml
30
+
31
+ [versions]
32
+ # SDK
33
+ android-compileSdk = "35"
34
+ android-minSdk = "24"
35
+ android-targetSdk = "35"
36
+
37
+ # Core
38
+ kotlin = "2.0.0"
39
+ ksp = "2.0.0-1.0.21"
40
+ agp = "8.7.0"
41
+
42
+ # AndroidX
43
+ androidx-core = "1.13.1"
44
+ androidx-lifecycle = "2.8.6"
45
+ androidx-navigation = "2.8.3"
46
+ androidx-room = "2.6.1"
47
+ androidx-datastore = "1.1.1"
48
+ androidx-paging = "3.3.2"
49
+ androidx-work = "2.9.1"
50
+
51
+ # Compose
52
+ compose-bom = "2024.10.01"
53
+ compose-compiler = "1.5.14"
54
+
55
+ # Network
56
+ retrofit = "2.11.0"
57
+ okhttp = "4.12.0"
58
+ ktor = "2.3.12"
59
+
60
+ # DI
61
+ hilt = "2.51.1"
62
+ hilt-navigation = "1.2.0"
63
+
64
+ # Firebase
65
+ firebase-bom = "33.5.1"
66
+ google-services = "4.4.2"
67
+ firebase-crashlytics-plugin = "3.0.2"
68
+
69
+ # Serialization
70
+ kotlinx-serialization = "1.7.3"
71
+ kotlinx-coroutines = "1.9.0"
72
+
73
+ # Media
74
+ media3 = "1.4.0"
75
+ camerax = "1.3.4"
76
+
77
+ # Testing
78
+ junit = "4.13.2"
79
+ junit5 = "5.10.2"
80
+ mockk = "1.13.12"
81
+ turbine = "1.1.0"
82
+ androidx-test-runner = "1.6.2"
83
+ espresso = "3.6.1"
84
+
85
+ # Quality
86
+ detekt = "1.23.7"
87
+ ktlint = "12.1.1"
88
+
89
+
90
+ [libraries]
91
+ # AndroidX Core
92
+ androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
93
+ androidx-appcompat = { module = "androidx.appcompat:appcompat", version = "1.7.0" }
94
+ androidx-activity-compose = { module = "androidx.activity:activity-compose", version = "1.9.2" }
95
+
96
+ # Lifecycle
97
+ androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle" }
98
+ androidx-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" }
99
+ androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" }
100
+
101
+ # Compose
102
+ compose-bom = { module = "androidx.compose:compose-bom", version.ref = "compose-bom" }
103
+ compose-ui = { module = "androidx.compose.ui:ui" }
104
+ compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
105
+ compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
106
+ compose-foundation = { module = "androidx.compose.foundation:foundation" }
107
+ compose-material3 = { module = "androidx.compose.material3:material3" }
108
+ compose-material-icons = { module = "androidx.compose.material:material-icons-extended" }
109
+ compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest" }
110
+ compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" }
111
+
112
+ # Navigation
113
+ androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" }
114
+
115
+ # Room
116
+ androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "androidx-room" }
117
+ androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "androidx-room" }
118
+ androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "androidx-room" }
119
+ androidx-room-paging = { module = "androidx.room:room-paging", version.ref = "androidx-room" }
120
+ androidx-room-testing = { module = "androidx.room:room-testing", version.ref = "androidx-room" }
121
+
122
+ # DataStore
123
+ androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "androidx-datastore" }
124
+ androidx-datastore-proto = { module = "androidx.datastore:datastore", version.ref = "androidx-datastore" }
125
+
126
+ # Paging
127
+ androidx-paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "androidx-paging" }
128
+ androidx-paging-compose = { module = "androidx.paging:paging-compose", version.ref = "androidx-paging" }
129
+
130
+ # WorkManager
131
+ androidx-work-runtime = { module = "androidx.work:work-runtime-ktx", version.ref = "androidx-work" }
132
+ androidx-work-hilt = { module = "androidx.hilt:hilt-work", version = "1.2.0" }
133
+ androidx-work-testing = { module = "androidx.work:work-testing", version.ref = "androidx-work" }
134
+
135
+ # Network
136
+ retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
137
+ retrofit-kotlinx-serialization = { module = "com.squareup.retrofit2:converter-kotlinx-serialization", version.ref = "retrofit" }
138
+ okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
139
+ okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
140
+ ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
141
+ ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
142
+ ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
143
+ ktor-serialization-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
144
+
145
+ # DI — Hilt
146
+ hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }
147
+ hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" }
148
+ hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hilt-navigation" }
149
+ hilt-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "hilt" }
150
+
151
+ # Serialization / Coroutines
152
+ kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
153
+ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
154
+ kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
155
+ kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
156
+
157
+ # Firebase
158
+ firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebase-bom" }
159
+ firebase-analytics = { module = "com.google.firebase:firebase-analytics-ktx" }
160
+ firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics-ktx" }
161
+ firebase-messaging = { module = "com.google.firebase:firebase-messaging-ktx" }
162
+ firebase-config = { module = "com.google.firebase:firebase-config-ktx" }
163
+ firebase-auth = { module = "com.google.firebase:firebase-auth-ktx" }
164
+
165
+ # Media
166
+ media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3" }
167
+ media3-exoplayer-hls = { module = "androidx.media3:media3-exoplayer-hls", version.ref = "media3" }
168
+ media3-ui = { module = "androidx.media3:media3-ui", version.ref = "media3" }
169
+ media3-session = { module = "androidx.media3:media3-session", version.ref = "media3" }
170
+ camerax-core = { module = "androidx.camera:camera-core", version.ref = "camerax" }
171
+ camerax-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "camerax" }
172
+ camerax-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "camerax" }
173
+ camerax-video = { module = "androidx.camera:camera-video", version.ref = "camerax" }
174
+ camerax-view = { module = "androidx.camera:camera-view", version.ref = "camerax" }
175
+
176
+ # Security
177
+ androidx-security-crypto = { module = "androidx.security:security-crypto", version = "1.1.0-alpha06" }
178
+
179
+ # Testing
180
+ junit = { module = "junit:junit", version.ref = "junit" }
181
+ mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
182
+ mockk-android = { module = "io.mockk:mockk-android", version.ref = "mockk" }
183
+ turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" }
184
+ androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidx-test-runner" }
185
+ espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso" }
186
+ androidx-junit = { module = "androidx.test.ext:junit", version = "1.2.1" }
187
+
188
+ # Quality
189
+ detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
190
+
191
+
192
+ [bundles]
193
+ # ✅ Bundles — groups of always-used-together dependencies
194
+ compose = [
195
+ "compose-ui",
196
+ "compose-foundation",
197
+ "compose-material3",
198
+ "compose-ui-tooling-preview",
199
+ "compose-material-icons"
200
+ ]
201
+
202
+ lifecycle = [
203
+ "androidx-lifecycle-viewmodel",
204
+ "androidx-lifecycle-runtime",
205
+ "androidx-lifecycle-runtime-compose"
206
+ ]
207
+
208
+ room = [
209
+ "androidx-room-runtime",
210
+ "androidx-room-ktx"
211
+ ]
212
+
213
+ network = [
214
+ "retrofit",
215
+ "retrofit-kotlinx-serialization",
216
+ "okhttp",
217
+ "okhttp-logging"
218
+ ]
219
+
220
+ coroutines = [
221
+ "kotlinx-coroutines-core",
222
+ "kotlinx-coroutines-android"
223
+ ]
224
+
225
+ testing-unit = [
226
+ "junit",
227
+ "mockk",
228
+ "kotlinx-coroutines-test",
229
+ "turbine"
230
+ ]
231
+
232
+ testing-android = [
233
+ "androidx-test-runner",
234
+ "androidx-junit",
235
+ "espresso-core"
236
+ ]
237
+
238
+
239
+ [plugins]
240
+ android-application = { id = "com.android.application", version.ref = "agp" }
241
+ android-library = { id = "com.android.library", version.ref = "agp" }
242
+ kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
243
+ kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
244
+ kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
245
+ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
246
+ ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
247
+ hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
248
+ google-services = { id = "com.google.gms.google-services", version.ref = "google-services" }
249
+ firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebase-crashlytics-plugin" }
250
+ detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
251
+ ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
252
+ ```
253
+
254
+ ---
255
+
256
+ ## Using in build.gradle.kts
257
+
258
+ ```kotlin
259
+ // ✅ Reference via type-safe accessors
260
+ dependencies {
261
+ // Single library
262
+ implementation(libs.androidx.core.ktx)
263
+ implementation(libs.hilt.android)
264
+ ksp(libs.hilt.compiler)
265
+
266
+ // Bundle
267
+ implementation(libs.bundles.compose)
268
+ implementation(libs.bundles.room)
269
+ ksp(libs.androidx.room.compiler)
270
+
271
+ // BOM
272
+ implementation(platform(libs.firebase.bom))
273
+ implementation(libs.firebase.analytics)
274
+
275
+ // Test
276
+ testImplementation(libs.bundles.testing.unit)
277
+ androidTestImplementation(libs.bundles.testing.android)
278
+ }
279
+
280
+ plugins {
281
+ alias(libs.plugins.android.application)
282
+ alias(libs.plugins.kotlin.android)
283
+ alias(libs.plugins.hilt)
284
+ alias(libs.plugins.ksp)
285
+ }
286
+ ```
287
+
288
+ ---
289
+
290
+ ## Anti-Patterns
291
+
292
+ - Inline versions in `build.gradle.kts` — `implementation("com.example:lib:1.0.0")`
293
+ - Duplicate version definitions across modules
294
+ - Not using bundles for frequently co-used dependencies
295
+ - Mixing BOM and explicit versions for same library group
296
+ - Not keeping catalog alphabetically sorted — hard to find entries
297
+
298
+ ---
299
+
300
+ ## Related Skills
301
+ - `gradle` — Gradle build configuration
302
+ - `convention-plugin` — using catalog in shared build logic
303
+ - `dependency-management` — resolving conflicts with catalog
304
+ - `build-variant` — applying different deps per variant
@@ -0,0 +1,185 @@
1
+ ---
2
+ name: background-processing
3
+ description: >
4
+ Background processing strategies in Android.
5
+ Load this skill when choosing between WorkManager, coroutines, and
6
+ foreground services for background work, scheduling deferred tasks,
7
+ handling doze mode, or running work that must survive app death.
8
+ ---
9
+
10
+ # Background Processing
11
+
12
+ ## Overview
13
+
14
+ Android restricts background processing to preserve battery and memory. The correct tool depends on whether the work must survive app death, needs to be scheduled, or must run immediately. WorkManager is the standard for deferrable, guaranteed work. Coroutines handle in-process background work. Foreground Services handle long-running user-visible work.
15
+
16
+ ---
17
+
18
+ ## Core Principles
19
+
20
+ - Use **WorkManager** for deferrable work that must survive app death or device restart
21
+ - Use **coroutines** (`Dispatchers.IO`) for in-process background work tied to app lifetime
22
+ - Use **ForegroundService** for long-running work that the user is aware of (music, upload)
23
+ - Never use `AsyncTask`, `HandlerThread`, or bare `Thread` — use coroutines
24
+ - Respect **Doze mode** — only WorkManager and ForegroundService work reliably in Doze
25
+
26
+ ---
27
+
28
+ ## Decision Matrix
29
+
30
+ | Work Type | Survives App Death | User Visible | Use |
31
+ | ------------------------- | ------------------ | ------------ | -------------------------- |
32
+ | Short async (network, DB) | ❌ | ❌ | Coroutine |
33
+ | Deferred, guaranteed | ✅ | ❌ | WorkManager |
34
+ | Periodic background sync | ✅ | ❌ | WorkManager |
35
+ | Long-running, user-aware | ✅ | ✅ | ForegroundService |
36
+ | Immediate, in-process | ❌ | ❌ | Coroutine + Dispatchers.IO |
37
+
38
+ ---
39
+
40
+ ## WorkManager — Deferrable Work
41
+
42
+ ```kotlin
43
+ // ✅ Define a Worker
44
+ class SyncWorker(
45
+ context: Context,
46
+ params: WorkerParameters
47
+ ) : CoroutineWorker(context, params) {
48
+
49
+ override suspend fun doWork(): Result {
50
+ return try {
51
+ val userId = inputData.getString("user_id") ?: return Result.failure()
52
+ syncRepository.syncUser(userId)
53
+ Result.success()
54
+ } catch (e: Exception) {
55
+ if (runAttemptCount < 3) Result.retry()
56
+ else Result.failure()
57
+ }
58
+ }
59
+ }
60
+
61
+ // ✅ Schedule one-time work
62
+ val request = OneTimeWorkRequestBuilder<SyncWorker>()
63
+ .setInputData(workDataOf("user_id" to userId))
64
+ .setConstraints(
65
+ Constraints.Builder()
66
+ .setRequiredNetworkType(NetworkType.CONNECTED)
67
+ .build()
68
+ )
69
+ .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 15, TimeUnit.MINUTES)
70
+ .build()
71
+
72
+ WorkManager.getInstance(context).enqueueUniqueWork(
73
+ "sync_user_$userId",
74
+ ExistingWorkPolicy.KEEP,
75
+ request
76
+ )
77
+
78
+ // ✅ Schedule periodic work
79
+ val periodicRequest = PeriodicWorkRequestBuilder<SyncWorker>(1, TimeUnit.HOURS)
80
+ .setConstraints(
81
+ Constraints.Builder()
82
+ .setRequiredNetworkType(NetworkType.CONNECTED)
83
+ .setRequiresBatteryNotLow(true)
84
+ .build()
85
+ )
86
+ .build()
87
+
88
+ WorkManager.getInstance(context).enqueueUniquePeriodicWork(
89
+ "periodic_sync",
90
+ ExistingPeriodicWorkPolicy.KEEP,
91
+ periodicRequest
92
+ )
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Coroutine Background Work
98
+
99
+ ```kotlin
100
+ // ✅ Short background work — in-process only
101
+ class DataRepository @Inject constructor(
102
+ private val api: DataApi,
103
+ private val dao: DataDao
104
+ ) {
105
+ suspend fun refreshData() = withContext(Dispatchers.IO) {
106
+ val data = api.getData()
107
+ dao.insertAll(data)
108
+ }
109
+ }
110
+
111
+ // ✅ Long-running in-process work with custom scope
112
+ @Singleton
113
+ class PollingManager @Inject constructor(
114
+ private val repository: DataRepository
115
+ ) {
116
+ private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
117
+
118
+ fun startPolling() {
119
+ scope.launch {
120
+ while (isActive) {
121
+ runCatching { repository.refreshData() }
122
+ delay(30_000)
123
+ }
124
+ }
125
+ }
126
+
127
+ fun stopPolling() = scope.cancel()
128
+ }
129
+ ```
130
+
131
+ ---
132
+
133
+ ## Observing WorkManager Progress
134
+
135
+ ```kotlin
136
+ // ✅ Observe work state in ViewModel
137
+ class SyncViewModel @Inject constructor(
138
+ private val workManager: WorkManager
139
+ ) : ViewModel() {
140
+
141
+ val syncState: LiveData<WorkInfo> = workManager
142
+ .getWorkInfosForUniqueWorkLiveData("periodic_sync")
143
+ .map { workInfos -> workInfos.firstOrNull() }
144
+ .filterNotNull()
145
+
146
+ // Or as Flow
147
+ val syncStateFlow: Flow<WorkInfo?> = workManager
148
+ .getWorkInfosForUniqueWorkFlow("periodic_sync")
149
+ .map { it.firstOrNull() }
150
+ }
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Chaining Work
156
+
157
+ ```kotlin
158
+ // ✅ Chain workers sequentially
159
+ WorkManager.getInstance(context)
160
+ .beginUniqueWork("upload_chain", ExistingWorkPolicy.REPLACE,
161
+ OneTimeWorkRequestBuilder<CompressWorker>().build()
162
+ )
163
+ .then(OneTimeWorkRequestBuilder<UploadWorker>().build())
164
+ .then(OneTimeWorkRequestBuilder<NotifyWorker>().build())
165
+ .enqueue()
166
+ ```
167
+
168
+ ---
169
+
170
+ ## Anti-Patterns
171
+
172
+ - Using `GlobalScope` for work that should survive — use WorkManager instead
173
+ - Running network calls in a bare `Thread` — use coroutines with Dispatchers.IO
174
+ - Using `AlarmManager` for periodic work — WorkManager handles this better
175
+ - Starting a ForegroundService for short work — use WorkManager
176
+ - Not setting constraints on WorkManager — work runs even on metered network or low battery
177
+
178
+ ---
179
+
180
+ ## Related Skills
181
+
182
+ - `workmanager` — detailed WorkManager patterns
183
+ - `foreground-service` — long-running user-visible work
184
+ - `coroutine` — coroutine fundamentals and dispatcher selection
185
+ - `structured-concurrency` — managing coroutine lifecycle
@@ -0,0 +1,207 @@
1
+ ---
2
+ name: channel
3
+ description: >
4
+ Kotlin Channel for guaranteed single-consumer message delivery in Android.
5
+ Load this skill when implementing one-time UI events with delivery guarantee,
6
+ building producer-consumer pipelines, handling work queues,
7
+ or choosing between Channel and SharedFlow for event delivery.
8
+ ---
9
+
10
+ # Channel
11
+
12
+ ## Overview
13
+
14
+ `Channel` is a coroutine primitive for communication between coroutines. Unlike `SharedFlow`, a `Channel` guarantees delivery to exactly one consumer and buffers messages when the consumer is not active. On Android, `Channel` is the preferred mechanism for one-time ViewModel events (navigation, toasts) where delivery must be guaranteed.
15
+
16
+ ---
17
+
18
+ ## Core Principles
19
+
20
+ - Use `Channel` when delivery must be **guaranteed** — events must not be dropped or missed
21
+ - Use `SharedFlow` when **broadcasting** to multiple collectors is needed
22
+ - Always expose `Channel` as `receiveAsFlow()` — never expose the raw `Channel`
23
+ - Use `Channel.BUFFERED` capacity — prevents suspension when collector is temporarily inactive
24
+ - One `Channel` per event type, or a sealed class `Channel` for all events from one ViewModel
25
+
26
+ ---
27
+
28
+ ## Basic Channel for UI Events
29
+
30
+ ```kotlin
31
+ // ✅ Standard ViewModel event channel
32
+ class UserViewModel : ViewModel() {
33
+
34
+ private val _events = Channel<UserEvent>(Channel.BUFFERED)
35
+ val events: Flow<UserEvent> = _events.receiveAsFlow()
36
+
37
+ fun onSaveSuccess() {
38
+ viewModelScope.launch {
39
+ _events.send(UserEvent.NavigateBack)
40
+ }
41
+ }
42
+
43
+ fun onError(message: String) {
44
+ viewModelScope.launch {
45
+ _events.send(UserEvent.ShowSnackbar(message))
46
+ }
47
+ }
48
+ }
49
+
50
+ sealed interface UserEvent {
51
+ data object NavigateBack : UserEvent
52
+ data class ShowSnackbar(val message: String) : UserEvent
53
+ data class NavigateToDetail(val userId: String) : UserEvent
54
+ }
55
+ ```
56
+
57
+ ---
58
+
59
+ ## Collecting in Compose
60
+
61
+ ```kotlin
62
+ // ✅ Collect channel events in LaunchedEffect
63
+ @Composable
64
+ fun UserScreen(
65
+ onNavigateBack: () -> Unit,
66
+ onNavigateToDetail: (String) -> Unit,
67
+ viewModel: UserViewModel = hiltViewModel()
68
+ ) {
69
+ val snackbarHostState = remember { SnackbarHostState() }
70
+
71
+ LaunchedEffect(Unit) {
72
+ viewModel.events.collect { event ->
73
+ when (event) {
74
+ is UserEvent.NavigateBack -> onNavigateBack()
75
+ is UserEvent.ShowSnackbar -> snackbarHostState.showSnackbar(event.message)
76
+ is UserEvent.NavigateToDetail -> onNavigateToDetail(event.userId)
77
+ }
78
+ }
79
+ }
80
+
81
+ Scaffold(snackbarHost = { SnackbarHost(snackbarHostState) }) { padding ->
82
+ // screen content
83
+ }
84
+ }
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Channel Capacity Options
90
+
91
+ ```kotlin
92
+ // ✅ BUFFERED — default buffer (64 elements), send never suspends unless full
93
+ Channel<Event>(Channel.BUFFERED)
94
+
95
+ // ✅ UNLIMITED — unbounded buffer, send never suspends
96
+ Channel<Event>(Channel.UNLIMITED)
97
+
98
+ // ✅ RENDEZVOUS — no buffer, send suspends until receive
99
+ Channel<Event>(Channel.RENDEZVOUS)
100
+
101
+ // ✅ CONFLATED — keeps only the latest, old values dropped
102
+ Channel<Event>(Channel.CONFLATED)
103
+
104
+ // ✅ Custom capacity
105
+ Channel<Event>(capacity = 32)
106
+ ```
107
+
108
+ ---
109
+
110
+ ## Producer-Consumer Pipeline
111
+
112
+ ```kotlin
113
+ // ✅ Work queue with Channel
114
+ class ImageProcessingQueue @Inject constructor() {
115
+ private val queue = Channel<ImageTask>(capacity = 32)
116
+
117
+ suspend fun enqueue(task: ImageTask) {
118
+ queue.send(task)
119
+ }
120
+
121
+ fun startProcessing(scope: CoroutineScope) {
122
+ scope.launch(Dispatchers.Default) {
123
+ for (task in queue) { // ✅ for loop — processes until channel is closed
124
+ processImage(task)
125
+ }
126
+ }
127
+ }
128
+
129
+ fun close() {
130
+ queue.close()
131
+ }
132
+ }
133
+ ```
134
+
135
+ ---
136
+
137
+ ## Channel vs SharedFlow
138
+
139
+ | | Channel | SharedFlow |
140
+ | ------------- | ----------------------- | ------------------------------ |
141
+ | Consumers | Single | Multiple |
142
+ | Delivery | Guaranteed (buffered) | Not guaranteed (can miss) |
143
+ | Replay | No | Configurable |
144
+ | Best for | UI events, work queues | Broadcast events, status |
145
+ | Missed events | Buffered until consumed | Dropped if no active collector |
146
+
147
+ ---
148
+
149
+ ## trySend vs send
150
+
151
+ ```kotlin
152
+ // ✅ send — suspends if buffer full (use inside coroutines)
153
+ viewModelScope.launch {
154
+ _events.send(UserEvent.NavigateBack)
155
+ }
156
+
157
+ // ✅ trySend — returns ChannelResult, non-suspending (use outside coroutines)
158
+ val result = _events.trySend(UserEvent.NavigateBack)
159
+ if (result.isFailure) Timber.w("Event could not be sent — channel full or closed")
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Closing a Channel
165
+
166
+ ```kotlin
167
+ // ✅ Close channel when done producing — consumer loop ends
168
+ class DataProducer {
169
+ private val channel = Channel<Data>(Channel.BUFFERED)
170
+
171
+ suspend fun produce() {
172
+ try {
173
+ dataList.forEach { channel.send(it) }
174
+ } finally {
175
+ channel.close() // ✅ always close in finally
176
+ }
177
+ }
178
+
179
+ fun consume(scope: CoroutineScope) {
180
+ scope.launch {
181
+ for (data in channel) { // ends when channel is closed
182
+ process(data)
183
+ }
184
+ }
185
+ }
186
+ }
187
+ ```
188
+
189
+ ---
190
+
191
+ ## Anti-Patterns
192
+
193
+ - Exposing raw `MutableSharedFlow` or `Channel` — external code can send/close
194
+ - Not using `receiveAsFlow()` — exposes Channel API to consumers
195
+ - Using `Channel.RENDEZVOUS` for UI events — send suspends if UI isn't collecting
196
+ - Using `SharedFlow` when you need guaranteed single delivery — events can be missed
197
+ - Forgetting to close the channel in producer — consumer loop hangs forever
198
+
199
+ ---
200
+
201
+ ## Related Skills
202
+
203
+ - `sharedflow` — broadcast to multiple collectors
204
+ - `stateflow` — persistent UI state
205
+ - `flow` — cold stream fundamentals
206
+ - `coroutine` — structured concurrency and scopes
207
+ - `mvvm` — event pattern in ViewModel