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,216 @@
1
+ ---
2
+ name: filesystem
3
+ description: >
4
+ Android filesystem — internal storage, external storage, cache, and file sharing.
5
+ Load this skill when reading or writing files, sharing files between apps,
6
+ choosing the right storage location, or handling storage permissions.
7
+ ---
8
+
9
+ # Filesystem
10
+
11
+ ## Overview
12
+
13
+ Android provides several storage locations with different visibility, persistence, and permission requirements. Choosing the right location depends on whether files are private to the app, shareable with other apps, or user-visible. Scoped Storage (API 29+) significantly restricts direct filesystem access.
14
+
15
+ ---
16
+
17
+ ## Core Principles
18
+
19
+ - Default to **internal storage** — private, no permissions needed
20
+ - Use **external storage** only for files the user should access via file manager
21
+ - Never use `Environment.getExternalStorageDirectory()` — deprecated, requires dangerous permission
22
+ - Use `FileProvider` for sharing files with other apps — never expose raw file paths
23
+ - Cache files can be deleted by the system at any time — don't rely on them for critical data
24
+
25
+ ---
26
+
27
+ ## Storage Locations
28
+
29
+ | Location | API | Permission | Cleared on Uninstall | Visible to User |
30
+ | ------------------ | ------------------------------- | ------------------------ | -------------------- | --------------- |
31
+ | `filesDir` | `context.filesDir` | None | ✅ Yes | ❌ No |
32
+ | `cacheDir` | `context.cacheDir` | None | ✅ Yes | ❌ No |
33
+ | `externalFilesDir` | `context.getExternalFilesDir()` | None (API 19+) | ✅ Yes | ✅ Yes |
34
+ | `externalCacheDir` | `context.externalCacheDir` | None | ✅ Yes | ✅ Yes |
35
+ | MediaStore | Via ContentResolver | `READ_MEDIA_*` (API 33+) | ❌ No | ✅ Yes |
36
+
37
+ ---
38
+
39
+ ## Internal Storage
40
+
41
+ ```kotlin
42
+ // ✅ Write to internal storage
43
+ fun writeFile(context: Context, fileName: String, content: String) {
44
+ val file = File(context.filesDir, fileName)
45
+ file.writeText(content)
46
+ }
47
+
48
+ // ✅ Read from internal storage
49
+ fun readFile(context: Context, fileName: String): String? {
50
+ val file = File(context.filesDir, fileName)
51
+ return if (file.exists()) file.readText() else null
52
+ }
53
+
54
+ // ✅ Subdirectory in internal storage
55
+ fun getAppDirectory(context: Context, dirName: String): File {
56
+ return File(context.filesDir, dirName).also { it.mkdirs() }
57
+ }
58
+
59
+ // ✅ Write binary data
60
+ fun writeBinaryFile(context: Context, fileName: String, bytes: ByteArray) {
61
+ File(context.filesDir, fileName).writeBytes(bytes)
62
+ }
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Cache Storage
68
+
69
+ ```kotlin
70
+ // ✅ Use cache for temporary/reproducible data
71
+ fun cacheImage(context: Context, name: String, bitmap: Bitmap) {
72
+ val file = File(context.cacheDir, name)
73
+ file.outputStream().use { out ->
74
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)
75
+ }
76
+ }
77
+
78
+ // ✅ Check cache before downloading
79
+ fun getCachedFile(context: Context, name: String): File? {
80
+ val file = File(context.cacheDir, name)
81
+ return if (file.exists()) file else null
82
+ }
83
+
84
+ // ✅ Limit cache size manually if needed
85
+ fun trimCache(context: Context, maxSizeBytes: Long) {
86
+ val cacheDir = context.cacheDir
87
+ val files = cacheDir.listFiles()?.sortedBy { it.lastModified() } ?: return
88
+ var totalSize = files.sumOf { it.length() }
89
+ for (file in files) {
90
+ if (totalSize <= maxSizeBytes) break
91
+ totalSize -= file.length()
92
+ file.delete()
93
+ }
94
+ }
95
+ ```
96
+
97
+ ---
98
+
99
+ ## External App-Specific Storage
100
+
101
+ ```kotlin
102
+ // ✅ Write to app-specific external directory (no permission needed)
103
+ fun writeToExternalFiles(context: Context, fileName: String, content: String) {
104
+ val dir = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)
105
+ ?: return // external storage may not be available
106
+ File(dir, fileName).writeText(content)
107
+ }
108
+
109
+ // ✅ Check external storage availability
110
+ fun isExternalStorageWritable(): Boolean =
111
+ Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
112
+ ```
113
+
114
+ ---
115
+
116
+ ## File Sharing with FileProvider
117
+
118
+ ```xml
119
+ <!-- AndroidManifest.xml -->
120
+ <provider
121
+ android:name="androidx.core.content.FileProvider"
122
+ android:authorities="${applicationId}.fileprovider"
123
+ android:exported="false"
124
+ android:grantUriPermissions="true">
125
+ <meta-data
126
+ android:name="android.support.FILE_PROVIDER_PATHS"
127
+ android:resource="@xml/file_paths" />
128
+ </provider>
129
+ ```
130
+
131
+ ```xml
132
+ <!-- res/xml/file_paths.xml -->
133
+ <paths>
134
+ <files-path name="internal_files" path="." />
135
+ <cache-path name="cache" path="." />
136
+ <external-files-path name="external_files" path="." />
137
+ </paths>
138
+ ```
139
+
140
+ ```kotlin
141
+ // ✅ Share a file via FileProvider
142
+ fun shareFile(context: Context, file: File) {
143
+ val uri = FileProvider.getUriForFile(
144
+ context,
145
+ "${context.packageName}.fileprovider",
146
+ file
147
+ )
148
+
149
+ val intent = Intent(Intent.ACTION_SEND).apply {
150
+ type = "application/pdf"
151
+ putExtra(Intent.EXTRA_STREAM, uri)
152
+ addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
153
+ }
154
+
155
+ context.startActivity(Intent.createChooser(intent, "Share File"))
156
+ }
157
+ ```
158
+
159
+ ---
160
+
161
+ ## Reading Files from Assets
162
+
163
+ ```kotlin
164
+ // ✅ Read from assets/
165
+ fun readAsset(context: Context, fileName: String): String {
166
+ return context.assets.open(fileName).bufferedReader().use { it.readText() }
167
+ }
168
+
169
+ // ✅ Read JSON config from assets
170
+ fun readJsonAsset(context: Context, fileName: String): JsonObject {
171
+ val content = readAsset(context, fileName)
172
+ return Json.parseToJsonElement(content).jsonObject
173
+ }
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Coroutine-Safe File I/O
179
+
180
+ ```kotlin
181
+ // ✅ Always perform file I/O on Dispatchers.IO
182
+ suspend fun writeFileSafely(context: Context, fileName: String, content: String) {
183
+ withContext(Dispatchers.IO) {
184
+ File(context.filesDir, fileName).writeText(content)
185
+ }
186
+ }
187
+
188
+ suspend fun readFileSafely(context: Context, fileName: String): String? {
189
+ return withContext(Dispatchers.IO) {
190
+ val file = File(context.filesDir, fileName)
191
+ if (file.exists()) file.readText() else null
192
+ }
193
+ }
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Anti-Patterns
199
+
200
+ - Using `Environment.getExternalStorageDirectory()` — deprecated since API 29
201
+ - File I/O on the main thread — causes ANR
202
+ - Exposing raw `file://` URIs to other apps — crashes on API 24+, use FileProvider
203
+ - Storing sensitive data in external storage — accessible by other apps
204
+ - Relying on cache files for critical data — system can delete them anytime
205
+ - Not checking external storage availability before writing
206
+ - Hardcoding absolute paths — they differ across devices and API levels
207
+
208
+ ---
209
+
210
+ ## Related Skills
211
+
212
+ - `file-storage` — higher-level file storage patterns
213
+ - `binary-storage` — storing binary/media files
214
+ - `encrypted-database` — encrypting sensitive stored data
215
+ - `workmanager` — background file operations
216
+ - `datastore` — structured key-value persistence
@@ -0,0 +1,233 @@
1
+ ---
2
+ name: lifecycle
3
+ description: >
4
+ Android Lifecycle management for Activities, Fragments, and Compose.
5
+ Load this skill when working with lifecycle-aware components, collecting
6
+ flows with lifecycle awareness, managing resources tied to lifecycle,
7
+ or avoiding memory leaks caused by lifecycle misuse.
8
+ ---
9
+
10
+ # Lifecycle
11
+
12
+ ## Overview
13
+
14
+ The Android Lifecycle represents the states an Activity, Fragment, or other component goes through from creation to destruction. Lifecycle-awareness ensures that operations start and stop at the right time, preventing memory leaks, crashes, and wasted resources.
15
+
16
+ ---
17
+
18
+ ## Core Principles
19
+
20
+ - Never hold references to Activity or Fragment in long-lived objects
21
+ - Always use lifecycle-aware collection for Flows — never raw `launch {}`
22
+ - Release resources in the **symmetric opposite** of where they were acquired
23
+ - Prefer `ViewModel` to survive configuration changes — never store UI state in Activity
24
+ - Use `repeatOnLifecycle` over `launchWhenStarted` — it properly cancels on stop
25
+
26
+ ---
27
+
28
+ ## Lifecycle States
29
+
30
+ ```
31
+ INITIALIZED → CREATED → STARTED → RESUMED
32
+ ↑ ↓
33
+ DESTROYED ← STOPPED
34
+ ```
35
+
36
+ | State | Activity callback | Fragment callback |
37
+ | --------- | ----------------- | ----------------- |
38
+ | CREATED | `onCreate()` | `onViewCreated()` |
39
+ | STARTED | `onStart()` | `onStart()` |
40
+ | RESUMED | `onResume()` | `onResume()` |
41
+ | STOPPED | `onStop()` | `onStop()` |
42
+ | DESTROYED | `onDestroy()` | `onDestroyView()` |
43
+
44
+ ---
45
+
46
+ ## Flow Collection — The Right Way
47
+
48
+ ```kotlin
49
+ // ✅ repeatOnLifecycle — cancels collection when below target state
50
+ viewLifecycleOwner.lifecycleScope.launch {
51
+ repeatOnLifecycle(Lifecycle.State.STARTED) {
52
+ viewModel.state.collect { state ->
53
+ renderState(state)
54
+ }
55
+ }
56
+ }
57
+
58
+ // ✅ Multiple flows — launch inside repeatOnLifecycle
59
+ viewLifecycleOwner.lifecycleScope.launch {
60
+ repeatOnLifecycle(Lifecycle.State.STARTED) {
61
+ launch { viewModel.state.collect { renderState(it) } }
62
+ launch { viewModel.events.collect { handleEvent(it) } }
63
+ }
64
+ }
65
+
66
+ // ✅ Compose — collectAsStateWithLifecycle (preferred over collectAsState)
67
+ @Composable
68
+ fun MyScreen(viewModel: MyViewModel = hiltViewModel()) {
69
+ val state by viewModel.state.collectAsStateWithLifecycle()
70
+ }
71
+
72
+ // ❌ Wrong — doesn't cancel when app goes to background
73
+ lifecycleScope.launch {
74
+ viewModel.state.collect { renderState(it) }
75
+ }
76
+
77
+ // ❌ Wrong — deprecated, doesn't resume collection after stop
78
+ lifecycleScope.launchWhenStarted {
79
+ viewModel.state.collect { renderState(it) }
80
+ }
81
+ ```
82
+
83
+ ---
84
+
85
+ ## ViewModel and Lifecycle
86
+
87
+ ```kotlin
88
+ // ✅ ViewModel survives configuration changes
89
+ class UserViewModel : ViewModel() {
90
+ // State here survives rotation
91
+ private val _state = MutableStateFlow(UserUiState())
92
+ val state: StateFlow<UserUiState> = _state.asStateFlow()
93
+
94
+ // ✅ viewModelScope is cancelled when ViewModel is cleared
95
+ fun loadUsers() {
96
+ viewModelScope.launch {
97
+ // safe — auto-cancelled on ViewModel destruction
98
+ }
99
+ }
100
+
101
+ // ✅ onCleared — clean up resources
102
+ override fun onCleared() {
103
+ super.onCleared()
104
+ // cancel non-coroutine resources if needed
105
+ }
106
+ }
107
+
108
+ // ✅ Get ViewModel in Fragment
109
+ class UserFragment : Fragment() {
110
+ private val viewModel: UserViewModel by viewModels()
111
+ // shared ViewModel across fragments in same Activity
112
+ private val sharedViewModel: SharedViewModel by activityViewModels()
113
+ }
114
+ ```
115
+
116
+ ---
117
+
118
+ ## Lifecycle-Aware Resource Management
119
+
120
+ ```kotlin
121
+ // ✅ Register/unregister in symmetric callbacks
122
+ class LocationFragment : Fragment() {
123
+
124
+ private lateinit var locationManager: LocationManager
125
+
126
+ override fun onStart() {
127
+ super.onStart()
128
+ locationManager.startUpdates() // start in onStart
129
+ }
130
+
131
+ override fun onStop() {
132
+ locationManager.stopUpdates() // stop in onStop
133
+ super.onStop()
134
+ }
135
+ }
136
+
137
+ // ✅ ViewBinding — avoid leaks
138
+ class UserFragment : Fragment(R.layout.fragment_user) {
139
+
140
+ private var _binding: FragmentUserBinding? = null
141
+ private val binding get() = _binding!!
142
+
143
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
144
+ super.onViewCreated(view, savedInstanceState)
145
+ _binding = FragmentUserBinding.bind(view)
146
+ }
147
+
148
+ override fun onDestroyView() {
149
+ _binding = null // ✅ clear binding reference
150
+ super.onDestroyView()
151
+ }
152
+ }
153
+ ```
154
+
155
+ ---
156
+
157
+ ## DefaultLifecycleObserver
158
+
159
+ ```kotlin
160
+ // ✅ Use DefaultLifecycleObserver for custom lifecycle-aware components
161
+ class AnalyticsTracker(private val analytics: Analytics) : DefaultLifecycleObserver {
162
+
163
+ override fun onStart(owner: LifecycleOwner) {
164
+ analytics.startSession()
165
+ }
166
+
167
+ override fun onStop(owner: LifecycleOwner) {
168
+ analytics.endSession()
169
+ }
170
+ }
171
+
172
+ // Register in Activity or Fragment
173
+ lifecycle.addObserver(AnalyticsTracker(analytics))
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Compose Lifecycle
179
+
180
+ ```kotlin
181
+ // ✅ LaunchedEffect — scoped to composition, cancelled on leave
182
+ @Composable
183
+ fun UserScreen(userId: String) {
184
+ LaunchedEffect(userId) {
185
+ // runs when userId changes, cancelled when composable leaves
186
+ viewModel.loadUser(userId)
187
+ }
188
+ }
189
+
190
+ // ✅ DisposableEffect — for non-coroutine cleanup
191
+ @Composable
192
+ fun MapScreen() {
193
+ DisposableEffect(Unit) {
194
+ val listener = registerMapListener()
195
+ onDispose {
196
+ listener.unregister()
197
+ }
198
+ }
199
+ }
200
+
201
+ // ✅ rememberUpdatedState — keep latest value in long-running effect
202
+ @Composable
203
+ fun Timer(onTick: () -> Unit) {
204
+ val currentOnTick by rememberUpdatedState(onTick)
205
+ LaunchedEffect(Unit) {
206
+ while (true) {
207
+ delay(1_000)
208
+ currentOnTick()
209
+ }
210
+ }
211
+ }
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Anti-Patterns
217
+
218
+ - Storing Activity/Fragment reference in ViewModel or Repository — causes memory leaks
219
+ - Using `lifecycleScope.launch {}` without `repeatOnLifecycle` for Flow collection
220
+ - Using `launchWhenStarted` — deprecated, doesn't cancel on stop
221
+ - Starting work in `onCreate` that should be in `onStart` — runs even when not visible
222
+ - Forgetting to clear ViewBinding in `onDestroyView` — memory leak
223
+ - Using `GlobalScope` for any lifecycle-bound work
224
+
225
+ ---
226
+
227
+ ## Related Skills
228
+
229
+ - `savedstatehandle` — persisting state across process death
230
+ - `process-death-recovery` — surviving process kill
231
+ - `viewmodel` — state management with ViewModel
232
+ - `compose` — Compose-specific lifecycle patterns
233
+ - `reactive-streams` — lifecycle-aware Flow collection
@@ -0,0 +1,226 @@
1
+ ---
2
+ name: manifest
3
+ description: >
4
+ Android Manifest configuration and best practices.
5
+ Load this skill when editing AndroidManifest.xml, declaring components,
6
+ configuring permissions, intent filters, or app-level attributes.
7
+ ---
8
+
9
+ # Manifest
10
+
11
+ ## Overview
12
+
13
+ The AndroidManifest.xml is the entry point configuration of every Android app. It declares all components, permissions, hardware requirements, and app-level behavior. Incorrect manifest configuration causes runtime crashes, security vulnerabilities, and Play Store rejections.
14
+
15
+ ---
16
+
17
+ ## Core Principles
18
+
19
+ - Declare only what the app **actually needs** — minimal permissions
20
+ - Never declare a component that isn't used — increases attack surface
21
+ - Always declare `android:exported` explicitly on components with intent filters
22
+ - Keep sensitive config (API keys, secrets) out of the manifest — use BuildConfig or encrypted storage
23
+ - Use `tools:` namespace for merge directives — never duplicate entries
24
+
25
+ ---
26
+
27
+ ## Application Block
28
+
29
+ ```xml
30
+ <application
31
+ android:name=".MyApplication"
32
+ android:icon="@mipmap/ic_launcher"
33
+ android:roundIcon="@mipmap/ic_launcher_round"
34
+ android:label="@string/app_name"
35
+ android:theme="@style/Theme.App"
36
+ android:supportsRtl="true"
37
+ android:allowBackup="false"
38
+ android:fullBackupContent="false"
39
+ android:dataExtractionRules="@xml/data_extraction_rules"
40
+ android:networkSecurityConfig="@xml/network_security_config">
41
+
42
+ <!-- components go here -->
43
+
44
+ </application>
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Activity Declaration
50
+
51
+ ```xml
52
+ <!-- ✅ Main launcher activity -->
53
+ <activity
54
+ android:name=".MainActivity"
55
+ android:exported="true"
56
+ android:windowSoftInputMode="adjustResize"
57
+ android:configChanges="orientation|screenSize|keyboardHidden">
58
+ <intent-filter>
59
+ <action android:name="android.intent.action.MAIN" />
60
+ <category android:name="android.intent.category.LAUNCHER" />
61
+ </intent-filter>
62
+ </activity>
63
+
64
+ <!-- ✅ Internal activity — not exported -->
65
+ <activity
66
+ android:name=".feature.detail.DetailActivity"
67
+ android:exported="false" />
68
+
69
+ <!-- ✅ Deep link support -->
70
+ <activity
71
+ android:name=".MainActivity"
72
+ android:exported="true">
73
+ <intent-filter android:autoVerify="true">
74
+ <action android:name="android.intent.action.VIEW" />
75
+ <category android:name="android.intent.category.DEFAULT" />
76
+ <category android:name="android.intent.category.BROWSABLE" />
77
+ <data android:scheme="https" android:host="example.com" />
78
+ </intent-filter>
79
+ </activity>
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Permissions
85
+
86
+ ```xml
87
+ <!-- ✅ Declare only what's needed -->
88
+ <uses-permission android:name="android.permission.INTERNET" />
89
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
90
+
91
+ <!-- ✅ Runtime permissions — still declare in manifest -->
92
+ <uses-permission android:name="android.permission.CAMERA" />
93
+ <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
94
+
95
+ <!-- ✅ Restrict to specific OS version if not needed on older -->
96
+ <uses-permission
97
+ android:name="android.permission.POST_NOTIFICATIONS"
98
+ android:minSdkVersion="33" />
99
+
100
+ <!-- ✅ Remove permission added by a library -->
101
+ <uses-permission
102
+ android:name="android.permission.READ_PHONE_STATE"
103
+ tools:node="remove" />
104
+ ```
105
+
106
+ ### Permission Groups by Category
107
+
108
+ | Category | Permissions |
109
+ | ------------- | ------------------------------------------------------------------------------ |
110
+ | Network | `INTERNET`, `ACCESS_NETWORK_STATE`, `CHANGE_NETWORK_STATE` |
111
+ | Location | `ACCESS_FINE_LOCATION`, `ACCESS_COARSE_LOCATION`, `ACCESS_BACKGROUND_LOCATION` |
112
+ | Camera | `CAMERA` |
113
+ | Storage | `READ_MEDIA_IMAGES`, `READ_MEDIA_VIDEO`, `READ_MEDIA_AUDIO` |
114
+ | Notifications | `POST_NOTIFICATIONS` (API 33+) |
115
+ | Bluetooth | `BLUETOOTH_SCAN`, `BLUETOOTH_CONNECT` (API 31+) |
116
+
117
+ ---
118
+
119
+ ## Services
120
+
121
+ ```xml
122
+ <!-- ✅ Foreground service -->
123
+ <service
124
+ android:name=".service.DownloadService"
125
+ android:exported="false"
126
+ android:foregroundServiceType="dataSync" />
127
+
128
+ <!-- ✅ WorkManager worker — no declaration needed -->
129
+ <!-- Workers are not components and don't need manifest entries -->
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Receivers
135
+
136
+ ```xml
137
+ <!-- ✅ Boot receiver -->
138
+ <receiver
139
+ android:name=".receiver.BootReceiver"
140
+ android:exported="true">
141
+ <intent-filter>
142
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
143
+ </intent-filter>
144
+ </receiver>
145
+
146
+ <!-- ✅ Internal receiver — not exported -->
147
+ <receiver
148
+ android:name=".receiver.DownloadReceiver"
149
+ android:exported="false" />
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Providers
155
+
156
+ ```xml
157
+ <!-- ✅ FileProvider for sharing files -->
158
+ <provider
159
+ android:name="androidx.core.content.FileProvider"
160
+ android:authorities="${applicationId}.fileprovider"
161
+ android:exported="false"
162
+ android:grantUriPermissions="true">
163
+ <meta-data
164
+ android:name="android.support.FILE_PROVIDER_PATHS"
165
+ android:resource="@xml/file_paths" />
166
+ </provider>
167
+ ```
168
+
169
+ ---
170
+
171
+ ## Manifest Merge (Multi-Module)
172
+
173
+ ```xml
174
+ <!-- ✅ Override a library's manifest entry -->
175
+ <activity
176
+ android:name="com.library.SomeActivity"
177
+ android:exported="false"
178
+ tools:node="merge" />
179
+
180
+ <!-- ✅ Remove a component added by a library -->
181
+ <activity
182
+ android:name="com.library.UnwantedActivity"
183
+ tools:node="remove" />
184
+
185
+ <!-- ✅ Replace an attribute from a library -->
186
+ <application
187
+ android:allowBackup="false"
188
+ tools:replace="android:allowBackup" />
189
+ ```
190
+
191
+ ---
192
+
193
+ ## Hardware Features
194
+
195
+ ```xml
196
+ <!-- ✅ Declare required hardware -->
197
+ <uses-feature
198
+ android:name="android.hardware.camera"
199
+ android:required="true" />
200
+
201
+ <!-- ✅ Declare optional hardware — don't block install -->
202
+ <uses-feature
203
+ android:name="android.hardware.camera.autofocus"
204
+ android:required="false" />
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Anti-Patterns
210
+
211
+ - `android:exported` not set on components with intent-filters — security risk, required API 31+
212
+ - Storing API keys or secrets in `<meta-data>` — visible in decompiled APK
213
+ - Declaring `READ_EXTERNAL_STORAGE` on API 33+ — use `READ_MEDIA_*` instead
214
+ - Requesting `ACCESS_BACKGROUND_LOCATION` without foreground location first
215
+ - Declaring unused permissions — increases permissions dialog burden and audit surface
216
+ - Missing `android:supportsRtl="true"` — breaks RTL layouts
217
+ - `android:allowBackup="true"` without configuring backup rules — leaks sensitive data
218
+
219
+ ---
220
+
221
+ ## Related Skills
222
+
223
+ - `deep-link` — intent filter setup for deep links
224
+ - `foreground-service` — foreground service declaration
225
+ - `network-security-config` — network security configuration
226
+ - `resources` — resource references in manifest