android-ai-skills 1.2.0 → 1.3.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/CHANGELOG.md +7 -0
- package/README.md +214 -9
- package/android-accessibility-best-practices/SKILL.md +36 -0
- package/android-accessibility-best-practices/references/color_contrast.md +30 -0
- package/android-accessibility-best-practices/references/compose_semantics.md +48 -0
- package/android-accessibility-best-practices/references/content_descriptions.md +32 -0
- package/android-accessibility-best-practices/references/talkback_navigation.md +38 -0
- package/android-accessibility-best-practices/references/touch_targets.md +28 -0
- package/android-background-work/SKILL.md +33 -0
- package/android-background-work/references/foreground_services.md +30 -0
- package/android-background-work/references/notifications.md +34 -0
- package/android-background-work/references/scheduling.md +31 -0
- package/android-background-work/references/workmanager.md +41 -0
- package/android-build-infra/SKILL.md +34 -0
- package/android-build-infra/references/build_variants.md +30 -0
- package/android-build-infra/references/convention_plugins.md +29 -0
- package/android-build-infra/references/dependency_management.md +30 -0
- package/android-build-infra/references/modularization.md +33 -0
- package/android-build-infra/references/version_catalogs.md +24 -0
- package/android-navigation-best-practices/SKILL.md +32 -0
- package/android-navigation-best-practices/references/app_links.md +45 -0
- package/android-navigation-best-practices/references/deep_links.md +34 -0
- package/android-navigation-best-practices/references/navigation_patterns.md +41 -0
- package/android-navigation-best-practices/references/navigation_testing.md +35 -0
- package/android-performance-best-practices/SKILL.md +37 -0
- package/android-performance-best-practices/references/app_size.md +31 -0
- package/android-performance-best-practices/references/app_startup.md +26 -0
- package/android-performance-best-practices/references/baseline_profiles.md +26 -0
- package/android-performance-best-practices/references/battery_optimization.md +31 -0
- package/android-performance-best-practices/references/memory_management.md +27 -0
- package/android-performance-best-practices/references/strict_mode.md +43 -0
- package/android-security-best-practices/SKILL.md +37 -0
- package/android-security-best-practices/references/intent_component_security.md +33 -0
- package/android-security-best-practices/references/network_security.md +26 -0
- package/android-security-best-practices/references/r8_proguard.md +24 -0
- package/android-security-best-practices/references/secrets_management.md +25 -0
- package/android-security-best-practices/references/secure_storage.md +25 -0
- package/android-security-best-practices/references/webview_security.md +24 -0
- package/android-testing-best-practices/SKILL.md +37 -0
- package/android-testing-best-practices/references/ci_testing.md +32 -0
- package/android-testing-best-practices/references/compose_ui_testing.md +34 -0
- package/android-testing-best-practices/references/instrumented_testing.md +30 -0
- package/android-testing-best-practices/references/room_migration_testing.md +31 -0
- package/android-testing-best-practices/references/screenshot_testing.md +32 -0
- package/android-testing-best-practices/references/test_architecture.md +30 -0
- package/bin/android-ai-skills.js +32 -1
- package/package.json +9 -1
- package/play-store-readiness/SKILL.md +36 -0
- package/play-store-readiness/references/app_signing.md +24 -0
- package/play-store-readiness/references/data_safety.md +25 -0
- package/play-store-readiness/references/release_checklist.md +40 -0
- package/play-store-readiness/references/runtime_permissions.md +26 -0
- package/play-store-readiness/references/target_sdk_compliance.md +29 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [1.3.0](https://github.com/noloman/Android-AI-skills/compare/v1.2.0...v1.3.0) (2026-02-12)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* add 8 cross-cutting Android platform skills ([821a0d3](https://github.com/noloman/Android-AI-skills/commit/821a0d34bb2f193ea395a990411f2ef0d9c2c23a))
|
|
7
|
+
|
|
1
8
|
# [1.2.0](https://github.com/noloman/Android-AI-skills/compare/v1.1.0...v1.2.0) (2026-02-12)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -47,6 +47,14 @@ These AI skills:
|
|
|
47
47
|
- Prevent architecture drift
|
|
48
48
|
- Protect performance budgets
|
|
49
49
|
- Keep KMP boundaries clean
|
|
50
|
+
- Harden **security** (secrets, storage, network, components)
|
|
51
|
+
- Ensure **Play Store compliance** (Data Safety, permissions, target SDK)
|
|
52
|
+
- Enforce **accessibility** (WCAG AA contrast, touch targets, TalkBack)
|
|
53
|
+
- Optimize **performance** (startup, memory, battery, app size)
|
|
54
|
+
- Maintain **test quality** (test pyramid, Compose testing, screenshot tests)
|
|
55
|
+
- Standardize **build infrastructure** (version catalogs, convention plugins, modularization)
|
|
56
|
+
- Govern **background work** (WorkManager, foreground services, notifications)
|
|
57
|
+
- Guide **navigation** (type-safe routes, deep links, App Links)
|
|
50
58
|
- Scale from indie to enterprise
|
|
51
59
|
- Adapt automatically (Enterprise Mode auto-detection)
|
|
52
60
|
|
|
@@ -76,6 +84,46 @@ flowchart LR
|
|
|
76
84
|
D --- L
|
|
77
85
|
E --- L
|
|
78
86
|
L --> M[Structured Concurrency & Flow]
|
|
87
|
+
|
|
88
|
+
N[android-security-best-practices]
|
|
89
|
+
C --- N
|
|
90
|
+
D --- N
|
|
91
|
+
E --- N
|
|
92
|
+
|
|
93
|
+
O[android-performance-best-practices]
|
|
94
|
+
C --- O
|
|
95
|
+
D --- O
|
|
96
|
+
E --- O
|
|
97
|
+
|
|
98
|
+
P[play-store-readiness]
|
|
99
|
+
C --- P
|
|
100
|
+
D --- P
|
|
101
|
+
E --- P
|
|
102
|
+
|
|
103
|
+
Q[android-testing-best-practices]
|
|
104
|
+
C --- Q
|
|
105
|
+
D --- Q
|
|
106
|
+
E --- Q
|
|
107
|
+
|
|
108
|
+
R[android-accessibility-best-practices]
|
|
109
|
+
C --- R
|
|
110
|
+
D --- R
|
|
111
|
+
E --- R
|
|
112
|
+
|
|
113
|
+
S[android-build-infra]
|
|
114
|
+
C --- S
|
|
115
|
+
D --- S
|
|
116
|
+
E --- S
|
|
117
|
+
|
|
118
|
+
T[android-background-work]
|
|
119
|
+
C --- T
|
|
120
|
+
D --- T
|
|
121
|
+
E --- T
|
|
122
|
+
|
|
123
|
+
U[android-navigation-best-practices]
|
|
124
|
+
C --- U
|
|
125
|
+
D --- U
|
|
126
|
+
E --- U
|
|
79
127
|
```
|
|
80
128
|
|
|
81
129
|
---
|
|
@@ -139,6 +187,123 @@ Cross-cutting skill that always activates alongside the project-type-specific sk
|
|
|
139
187
|
|
|
140
188
|
---
|
|
141
189
|
|
|
190
|
+
### 5. android-security-best-practices
|
|
191
|
+
|
|
192
|
+
Cross-cutting skill — secrets management, secure storage, network security, component hardening.
|
|
193
|
+
|
|
194
|
+
**Enforces:**
|
|
195
|
+
- No hardcoded secrets in source code
|
|
196
|
+
- EncryptedSharedPreferences / Android Keystore for sensitive data
|
|
197
|
+
- HTTPS enforcement with Network Security Config
|
|
198
|
+
- exported="false" by default on all components
|
|
199
|
+
- PendingIntent.FLAG_IMMUTABLE, WebView file access disabled
|
|
200
|
+
- R8 enabled for release builds
|
|
201
|
+
- No sensitive data in logs
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
### 6. android-performance-best-practices
|
|
206
|
+
|
|
207
|
+
Cross-cutting skill — startup optimization, memory management, battery, app size.
|
|
208
|
+
|
|
209
|
+
**Enforces:**
|
|
210
|
+
- TTID < 2s, TTFD < 4s
|
|
211
|
+
- No heavy init on main thread during onCreate()
|
|
212
|
+
- App Startup library, Baseline Profiles
|
|
213
|
+
- No static Activity/Context references
|
|
214
|
+
- StrictMode in debug builds
|
|
215
|
+
- R8 + resource shrinking for release
|
|
216
|
+
- WebP assets, Doze-aware networking
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
### 7. play-store-readiness
|
|
221
|
+
|
|
222
|
+
Cross-cutting skill — Data Safety, permissions, target SDK, signing, release process.
|
|
223
|
+
|
|
224
|
+
**Enforces:**
|
|
225
|
+
- Data Safety section matches actual SDK behavior
|
|
226
|
+
- Runtime permissions at point of use with rationale
|
|
227
|
+
- Annual target SDK compliance
|
|
228
|
+
- Play App Signing with separate upload key
|
|
229
|
+
- AAB format, staged rollout (5-10%)
|
|
230
|
+
- Crash-free rate target >= 99%
|
|
231
|
+
- No debuggable release builds
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
### 8. android-testing-best-practices
|
|
236
|
+
|
|
237
|
+
Cross-cutting skill — Compose UI testing, screenshot tests, Room migrations, CI strategy.
|
|
238
|
+
|
|
239
|
+
**Enforces:**
|
|
240
|
+
- Test pyramid (unit > integration > E2E)
|
|
241
|
+
- Compose testing APIs for Compose UI (not Espresso)
|
|
242
|
+
- Fakes over mocks
|
|
243
|
+
- Room schema export + migration tests
|
|
244
|
+
- Descriptive test names, no Thread.sleep()
|
|
245
|
+
- Deterministic tests, flaky test quarantine
|
|
246
|
+
- TestDispatcher + runTest for coroutines
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
### 9. android-accessibility-best-practices
|
|
251
|
+
|
|
252
|
+
Cross-cutting skill — content descriptions, TalkBack, touch targets, contrast, semantics.
|
|
253
|
+
|
|
254
|
+
**Enforces:**
|
|
255
|
+
- contentDescription on all interactive non-text elements
|
|
256
|
+
- 48dp minimum touch targets
|
|
257
|
+
- WCAG AA contrast (4.5:1 normal, 3:1 large text)
|
|
258
|
+
- No color-only information
|
|
259
|
+
- Logical TalkBack reading order
|
|
260
|
+
- Correct semantics on custom composables
|
|
261
|
+
- sp (not dp) for text sizes
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### 10. android-build-infra
|
|
266
|
+
|
|
267
|
+
Cross-cutting skill — version catalogs, convention plugins, modularization, build variants.
|
|
268
|
+
|
|
269
|
+
**Enforces:**
|
|
270
|
+
- Gradle version catalogs (libs.versions.toml) for all dependencies
|
|
271
|
+
- Convention plugins for shared build config
|
|
272
|
+
- Feature modularization (feature-api/feature-impl)
|
|
273
|
+
- Dependencies flow inward, no feature-to-feature deps
|
|
274
|
+
- implementation scope by default
|
|
275
|
+
- Build variants for debug/release/staging
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
### 11. android-background-work
|
|
280
|
+
|
|
281
|
+
Cross-cutting skill — WorkManager, foreground services, notifications, scheduling.
|
|
282
|
+
|
|
283
|
+
**Enforces:**
|
|
284
|
+
- WorkManager for deferrable persistent work
|
|
285
|
+
- Foreground service types declared (API 34+)
|
|
286
|
+
- Notification channels (API 26+)
|
|
287
|
+
- Never hold WakeLocks indefinitely
|
|
288
|
+
- Exact alarms only for user-visible scheduling
|
|
289
|
+
- POST_NOTIFICATIONS permission (API 33+)
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
### 12. android-navigation-best-practices
|
|
294
|
+
|
|
295
|
+
Cross-cutting skill — type-safe routes, deep links, App Links, navigation patterns.
|
|
296
|
+
|
|
297
|
+
**Enforces:**
|
|
298
|
+
- Type-safe navigation (data class/object routes)
|
|
299
|
+
- App Links verified with Digital Asset Links
|
|
300
|
+
- Deep link fallbacks for non-installed users
|
|
301
|
+
- No heavy logic in navigation callbacks
|
|
302
|
+
- Standard launch mode with Navigation
|
|
303
|
+
- Deep link parameter validation
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
142
307
|
## Enterprise Mode (Auto-Detection)
|
|
143
308
|
|
|
144
309
|
Enterprise Mode activates automatically if the repository contains:
|
|
@@ -249,27 +414,59 @@ npx android-ai-skills@latest init --force
|
|
|
249
414
|
Running `init` with defaults creates:
|
|
250
415
|
|
|
251
416
|
```
|
|
252
|
-
AGENTS.md
|
|
253
|
-
CLAUDE.md
|
|
254
|
-
.github/copilot-instructions.md
|
|
255
|
-
.cursor/rules/compose-best-practices.mdc
|
|
417
|
+
AGENTS.md # Codex
|
|
418
|
+
CLAUDE.md # Claude Code
|
|
419
|
+
.github/copilot-instructions.md # GitHub Copilot
|
|
420
|
+
.cursor/rules/compose-best-practices.mdc # Cursor (per skill)
|
|
256
421
|
.cursor/rules/kmp-architecture-best-practices.mdc
|
|
257
422
|
.cursor/rules/compose-multiplatform-best-practices.mdc
|
|
258
423
|
.cursor/rules/kotlin-coroutines-best-practices.mdc
|
|
259
|
-
.
|
|
260
|
-
.
|
|
424
|
+
.cursor/rules/android-security-best-practices.mdc
|
|
425
|
+
.cursor/rules/android-performance-best-practices.mdc
|
|
426
|
+
.cursor/rules/play-store-readiness.mdc
|
|
427
|
+
.cursor/rules/android-testing-best-practices.mdc
|
|
428
|
+
.cursor/rules/android-accessibility-best-practices.mdc
|
|
429
|
+
.cursor/rules/android-build-infra.mdc
|
|
430
|
+
.cursor/rules/android-background-work.mdc
|
|
431
|
+
.cursor/rules/android-navigation-best-practices.mdc
|
|
432
|
+
.windsurfrules # Windsurf
|
|
433
|
+
.clinerules/compose-best-practices.md # Cline (per skill)
|
|
261
434
|
.clinerules/kmp-architecture-best-practices.md
|
|
262
435
|
.clinerules/compose-multiplatform-best-practices.md
|
|
263
436
|
.clinerules/kotlin-coroutines-best-practices.md
|
|
264
|
-
.
|
|
437
|
+
.clinerules/android-security-best-practices.md
|
|
438
|
+
.clinerules/android-performance-best-practices.md
|
|
439
|
+
.clinerules/play-store-readiness.md
|
|
440
|
+
.clinerules/android-testing-best-practices.md
|
|
441
|
+
.clinerules/android-accessibility-best-practices.md
|
|
442
|
+
.clinerules/android-build-infra.md
|
|
443
|
+
.clinerules/android-background-work.md
|
|
444
|
+
.clinerules/android-navigation-best-practices.md
|
|
445
|
+
.aiassistant/rules/compose-best-practices.md # JetBrains AI (per skill)
|
|
265
446
|
.aiassistant/rules/kmp-architecture-best-practices.md
|
|
266
447
|
.aiassistant/rules/compose-multiplatform-best-practices.md
|
|
267
448
|
.aiassistant/rules/kotlin-coroutines-best-practices.md
|
|
268
|
-
.
|
|
449
|
+
.aiassistant/rules/android-security-best-practices.md
|
|
450
|
+
.aiassistant/rules/android-performance-best-practices.md
|
|
451
|
+
.aiassistant/rules/play-store-readiness.md
|
|
452
|
+
.aiassistant/rules/android-testing-best-practices.md
|
|
453
|
+
.aiassistant/rules/android-accessibility-best-practices.md
|
|
454
|
+
.aiassistant/rules/android-build-infra.md
|
|
455
|
+
.aiassistant/rules/android-background-work.md
|
|
456
|
+
.aiassistant/rules/android-navigation-best-practices.md
|
|
457
|
+
.amazonq/rules/compose-best-practices.md # Amazon Q (per skill)
|
|
269
458
|
.amazonq/rules/kmp-architecture-best-practices.md
|
|
270
459
|
.amazonq/rules/compose-multiplatform-best-practices.md
|
|
271
460
|
.amazonq/rules/kotlin-coroutines-best-practices.md
|
|
272
|
-
|
|
461
|
+
.amazonq/rules/android-security-best-practices.md
|
|
462
|
+
.amazonq/rules/android-performance-best-practices.md
|
|
463
|
+
.amazonq/rules/play-store-readiness.md
|
|
464
|
+
.amazonq/rules/android-testing-best-practices.md
|
|
465
|
+
.amazonq/rules/android-accessibility-best-practices.md
|
|
466
|
+
.amazonq/rules/android-build-infra.md
|
|
467
|
+
.amazonq/rules/android-background-work.md
|
|
468
|
+
.amazonq/rules/android-navigation-best-practices.md
|
|
469
|
+
CONVENTIONS.md # Aider
|
|
273
470
|
.aider.conf.yml
|
|
274
471
|
```
|
|
275
472
|
|
|
@@ -342,6 +539,14 @@ compose-best-practices/
|
|
|
342
539
|
kmp-architecture-best-practices/
|
|
343
540
|
compose-multiplatform-best-practices/
|
|
344
541
|
kotlin-coroutines-best-practices/
|
|
542
|
+
android-security-best-practices/
|
|
543
|
+
android-performance-best-practices/
|
|
544
|
+
play-store-readiness/
|
|
545
|
+
android-testing-best-practices/
|
|
546
|
+
android-accessibility-best-practices/
|
|
547
|
+
android-build-infra/
|
|
548
|
+
android-background-work/
|
|
549
|
+
android-navigation-best-practices/
|
|
345
550
|
README.md
|
|
346
551
|
```
|
|
347
552
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
---
|
|
3
|
+
name: android-accessibility-best-practices
|
|
4
|
+
description: Android accessibility — content descriptions, TalkBack, touch targets, contrast, Compose semantics.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Android Accessibility Best Practices
|
|
8
|
+
|
|
9
|
+
Cross-cutting skill — always activates alongside the project-type-specific skill.
|
|
10
|
+
|
|
11
|
+
## Hard Rules
|
|
12
|
+
- Provide contentDescription on all interactive non-text elements.
|
|
13
|
+
- Set contentDescription = null on purely decorative images.
|
|
14
|
+
- Minimum touch target size: 48dp × 48dp.
|
|
15
|
+
- Meet WCAG AA contrast ratios: 4.5:1 for normal text, 3:1 for large text.
|
|
16
|
+
- Never convey information by color alone — add icons, patterns, or labels.
|
|
17
|
+
- Ensure logical TalkBack reading order matches visual layout.
|
|
18
|
+
- Apply correct semantics (Role, stateDescription) on custom composables.
|
|
19
|
+
- Time-based content must be pausable or extendable.
|
|
20
|
+
- All form fields must have associated labels.
|
|
21
|
+
- Use sp (not dp) for text sizes to respect user font scaling.
|
|
22
|
+
|
|
23
|
+
## Core Patterns
|
|
24
|
+
- Use Modifier.semantics {} to expose custom component meaning.
|
|
25
|
+
- Use mergeDescendants to group related elements for TalkBack.
|
|
26
|
+
- Test with TalkBack enabled on a real device.
|
|
27
|
+
- Run Accessibility Scanner for automated checks.
|
|
28
|
+
- Support dynamic font sizes — test at maximum font scale.
|
|
29
|
+
- Verify dark theme meets contrast requirements separately.
|
|
30
|
+
|
|
31
|
+
## References
|
|
32
|
+
- references/content_descriptions.md
|
|
33
|
+
- references/talkback_navigation.md
|
|
34
|
+
- references/touch_targets.md
|
|
35
|
+
- references/color_contrast.md
|
|
36
|
+
- references/compose_semantics.md
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Color & Contrast
|
|
2
|
+
|
|
3
|
+
## WCAG AA Requirements
|
|
4
|
+
- Normal text (< 18sp or < 14sp bold): contrast ratio ≥ 4.5:1.
|
|
5
|
+
- Large text (≥ 18sp or ≥ 14sp bold): contrast ratio ≥ 3:1.
|
|
6
|
+
- Non-text elements (icons, borders, form fields): contrast ratio ≥ 3:1.
|
|
7
|
+
- WCAG AAA (optional, stricter): 7:1 for normal text, 4.5:1 for large text.
|
|
8
|
+
|
|
9
|
+
## Exceptions
|
|
10
|
+
- Disabled/inactive elements: no contrast requirement (but consider usability).
|
|
11
|
+
- Logos and decorative elements: no contrast requirement.
|
|
12
|
+
- Text within images: same contrast requirements as regular text.
|
|
13
|
+
|
|
14
|
+
## Color Independence
|
|
15
|
+
- Never use color alone to convey information (e.g., red=error, green=success).
|
|
16
|
+
- Add icons, patterns, underlines, or labels alongside color indicators.
|
|
17
|
+
- Error states: use error icon + red color + descriptive text.
|
|
18
|
+
- Charts/graphs: use patterns, labels, or shapes in addition to color.
|
|
19
|
+
|
|
20
|
+
## Dark Theme
|
|
21
|
+
- Verify contrast ratios for both light and dark themes separately.
|
|
22
|
+
- Dark theme surfaces use lighter text — ensure sufficient contrast.
|
|
23
|
+
- Surface color hierarchy matters: surface, surfaceVariant, surfaceContainer.
|
|
24
|
+
- Test dynamic theming (Material You) — user-generated colors may fail contrast.
|
|
25
|
+
|
|
26
|
+
## Tools
|
|
27
|
+
- Accessibility Scanner (Android): scans visible UI for contrast issues.
|
|
28
|
+
- WebAIM Contrast Checker: manual ratio calculation.
|
|
29
|
+
- Colour Contrast Analyser (desktop): eyedropper-based tool.
|
|
30
|
+
- Android Studio Layout Inspector: check rendered colors.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Compose Semantics
|
|
2
|
+
|
|
3
|
+
## Modifier.semantics
|
|
4
|
+
- Use Modifier.semantics { } to add accessibility information to composables.
|
|
5
|
+
- mergeDescendants = true: combines child semantics into a single TalkBack announcement.
|
|
6
|
+
- clearAndSetSemantics { }: removes all child semantics and sets custom ones.
|
|
7
|
+
|
|
8
|
+
## Roles
|
|
9
|
+
- Role.Button: announces as "button" (double-tap to activate).
|
|
10
|
+
- Role.Checkbox, Role.Switch, Role.RadioButton: announces toggle state.
|
|
11
|
+
- Role.Tab: announces as "tab" with position.
|
|
12
|
+
- Role.Image: announces as "image".
|
|
13
|
+
- Set via: Modifier.semantics { role = Role.Button }.
|
|
14
|
+
|
|
15
|
+
## State Description
|
|
16
|
+
- stateDescription: announces the current state (e.g., "Selected", "Expanded", "50%").
|
|
17
|
+
- toggleableState: ToggleableState.On, Off, Indeterminate.
|
|
18
|
+
- selected: Boolean for selectable items.
|
|
19
|
+
- Use for custom components that have states TalkBack should announce.
|
|
20
|
+
|
|
21
|
+
## Headings & Structure
|
|
22
|
+
- heading(): marks element as a heading for navigation.
|
|
23
|
+
- Modifier.semantics { heading() } — TalkBack users can jump between headings.
|
|
24
|
+
- Use for screen titles, section headers, group labels.
|
|
25
|
+
|
|
26
|
+
## Content & Actions
|
|
27
|
+
- contentDescription: text read by TalkBack.
|
|
28
|
+
- customActions: list of CustomAccessibilityAction for contextual actions.
|
|
29
|
+
- onClick(label = "action description") { }: labeled click action.
|
|
30
|
+
- disabled(): marks element as non-interactive.
|
|
31
|
+
- error("message"): announces error state.
|
|
32
|
+
|
|
33
|
+
## Password & Input
|
|
34
|
+
- password(): hides text from TalkBack, announces "password".
|
|
35
|
+
- editableText: programmatic text for text fields.
|
|
36
|
+
- textSelectionRange: cursor position information.
|
|
37
|
+
- imeAction: announces expected keyboard action.
|
|
38
|
+
|
|
39
|
+
## Live Regions
|
|
40
|
+
- liveRegion = LiveRegionMode.Polite: announce changes when idle.
|
|
41
|
+
- liveRegion = LiveRegionMode.Assertive: announce changes immediately.
|
|
42
|
+
- Use for: toast messages, loading states, live counters, error banners.
|
|
43
|
+
|
|
44
|
+
## Testing Semantics
|
|
45
|
+
- Use ComposeTestRule.onNodeWithText().assertHasClickAction().
|
|
46
|
+
- assert(SemanticsMatcher.keyIsDefined(SemanticsProperties.Heading)).
|
|
47
|
+
- printToLog() to dump the semantic tree for debugging.
|
|
48
|
+
- Verify role, state, and content description in tests.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Content Descriptions
|
|
2
|
+
|
|
3
|
+
## Required Elements
|
|
4
|
+
- All interactive non-text elements: IconButton, Image (clickable), FAB, custom icons.
|
|
5
|
+
- Compose: Image(contentDescription = "description") or Icon(contentDescription = "description").
|
|
6
|
+
- View system: android:contentDescription or setContentDescription().
|
|
7
|
+
|
|
8
|
+
## Decorative Elements
|
|
9
|
+
- Set contentDescription = null on decorative images (Compose).
|
|
10
|
+
- View system: android:importantForAccessibility="no".
|
|
11
|
+
- Decorative = adds no information beyond what's already visible as text.
|
|
12
|
+
|
|
13
|
+
## Writing Descriptions
|
|
14
|
+
- Describe the action, not the appearance: "Delete item" not "Red trash can icon".
|
|
15
|
+
- Keep it concise: 2–5 words is ideal.
|
|
16
|
+
- Avoid "button" or "image" — TalkBack announces the role automatically.
|
|
17
|
+
- Match the language of the UI locale.
|
|
18
|
+
|
|
19
|
+
## Dynamic Descriptions
|
|
20
|
+
- Update contentDescription when state changes (e.g., "Play" → "Pause").
|
|
21
|
+
- Use stateDescription for toggle states (e.g., "Selected", "Expanded").
|
|
22
|
+
- Compose: Modifier.semantics { stateDescription = "Expanded" }.
|
|
23
|
+
|
|
24
|
+
## Icon + Text Combinations
|
|
25
|
+
- If an icon is next to text that describes it, set icon contentDescription = null.
|
|
26
|
+
- TalkBack reads both — redundant descriptions cause confusion.
|
|
27
|
+
- Use mergeDescendants to group icon and text into one TalkBack announcement.
|
|
28
|
+
|
|
29
|
+
## Live Regions
|
|
30
|
+
- Use Modifier.semantics { liveRegion = LiveRegionMode.Polite } for dynamic updates.
|
|
31
|
+
- Polite: announces when TalkBack is idle. Assertive: interrupts immediately.
|
|
32
|
+
- Use for: snackbars, loading indicators, real-time counters.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# TalkBack Navigation
|
|
2
|
+
|
|
3
|
+
## Default Traversal Order
|
|
4
|
+
- TalkBack reads nodes top-to-bottom, start-to-end (LTR/RTL aware).
|
|
5
|
+
- Order follows the semantic tree, which mirrors the composable tree by default.
|
|
6
|
+
- Ensure visual order matches semantic order — mismatches confuse users.
|
|
7
|
+
|
|
8
|
+
## Custom Ordering
|
|
9
|
+
- Compose: Modifier.semantics { traversalIndex = 1f } to reorder.
|
|
10
|
+
- Lower traversalIndex = announced earlier.
|
|
11
|
+
- Use sparingly — prefer restructuring the composable tree over overriding traversal.
|
|
12
|
+
- View system: android:accessibilityTraversalBefore / accessibilityTraversalAfter.
|
|
13
|
+
|
|
14
|
+
## Focus Management
|
|
15
|
+
- Use FocusRequester to programmatically move focus (e.g., after navigation).
|
|
16
|
+
- Announce screen changes to TalkBack — user needs context after navigation.
|
|
17
|
+
- Compose: LaunchedEffect to request focus on the first meaningful element.
|
|
18
|
+
|
|
19
|
+
## Headings
|
|
20
|
+
- Mark section headings: Modifier.semantics { heading() }.
|
|
21
|
+
- TalkBack users can navigate by headings (swipe up/down gesture).
|
|
22
|
+
- Use headings for screen titles, section dividers, list group headers.
|
|
23
|
+
|
|
24
|
+
## Dialogs and Modals
|
|
25
|
+
- Focus must be trapped inside dialogs — TalkBack should not escape to background.
|
|
26
|
+
- Compose Dialog and BottomSheet handle this automatically.
|
|
27
|
+
- On dismiss, return focus to the element that opened the dialog.
|
|
28
|
+
|
|
29
|
+
## Custom Actions
|
|
30
|
+
- Use Modifier.semantics { customActions = listOf(CustomAccessibilityAction("Delete") { ... }) }.
|
|
31
|
+
- Provides additional actions without visible UI controls.
|
|
32
|
+
- TalkBack users access via the actions menu.
|
|
33
|
+
|
|
34
|
+
## Testing
|
|
35
|
+
- Enable TalkBack (Settings > Accessibility > TalkBack) and navigate your app.
|
|
36
|
+
- Verify: every element is reachable, descriptions are meaningful, order is logical.
|
|
37
|
+
- Test with the screen off (TalkBack Braille mode) for additional confidence.
|
|
38
|
+
- Use Accessibility Scanner app for automated checks.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Touch Targets
|
|
2
|
+
|
|
3
|
+
## Minimum Size
|
|
4
|
+
- 48dp × 48dp minimum for all interactive elements (Material Design guideline).
|
|
5
|
+
- WCAG 2.5.8 requires at least 24×24 CSS px — Android's 48dp exceeds this.
|
|
6
|
+
- Applies to: buttons, icons, checkboxes, switches, list items, links.
|
|
7
|
+
|
|
8
|
+
## Compose
|
|
9
|
+
- Use Modifier.sizeIn(minWidth = 48.dp, minHeight = 48.dp) on interactive elements.
|
|
10
|
+
- Material components set minimumInteractiveComponentSize automatically.
|
|
11
|
+
- For custom composables, ensure the clickable area includes padding.
|
|
12
|
+
- Use Modifier.clickable with indication and correct hit area.
|
|
13
|
+
|
|
14
|
+
## Expanding Touch Area
|
|
15
|
+
- Add padding around small visual elements to expand the touch target.
|
|
16
|
+
- Compose: Modifier.padding() outside Modifier.clickable() expands the touch area.
|
|
17
|
+
- View system: use TouchDelegate to extend touch area beyond the view bounds.
|
|
18
|
+
- ViewCompat.setMinimumTouchTargetSize for backward-compatible touch targets.
|
|
19
|
+
|
|
20
|
+
## Spacing
|
|
21
|
+
- Maintain at least 8dp spacing between adjacent touch targets.
|
|
22
|
+
- Prevents accidental taps on the wrong element.
|
|
23
|
+
- Especially important for dense layouts: toolbars, bottom navigation, list actions.
|
|
24
|
+
|
|
25
|
+
## Verification
|
|
26
|
+
- Use Accessibility Scanner to detect targets smaller than 48dp.
|
|
27
|
+
- Enable "Show layout bounds" in Developer Options for visual verification.
|
|
28
|
+
- Test on actual devices — touch accuracy varies by device and user.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
|
|
2
|
+
---
|
|
3
|
+
name: android-background-work
|
|
4
|
+
description: Android background work — WorkManager, foreground services, notifications, scheduling.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Android Background Work
|
|
8
|
+
|
|
9
|
+
Cross-cutting skill — always activates alongside the project-type-specific skill.
|
|
10
|
+
|
|
11
|
+
## Hard Rules
|
|
12
|
+
- Use WorkManager for all deferrable, persistent background work.
|
|
13
|
+
- Declare foreground service types explicitly (API 34+ requirement).
|
|
14
|
+
- Use notification channels (API 26+) for all notifications.
|
|
15
|
+
- Never hold WakeLocks indefinitely — always release in a finally block.
|
|
16
|
+
- Use exact alarms only for user-visible scheduling (alarms, reminders).
|
|
17
|
+
- FCM high-priority messages only for user-visible notifications.
|
|
18
|
+
- Stop foreground services when work completes — do not leave them running.
|
|
19
|
+
- Request POST_NOTIFICATIONS permission (API 33+) before posting notifications.
|
|
20
|
+
|
|
21
|
+
## Core Patterns
|
|
22
|
+
- WorkManager with constraints (network, charging, storage) for intelligent scheduling.
|
|
23
|
+
- Use ExistingWorkPolicy.KEEP or REPLACE to avoid duplicate work.
|
|
24
|
+
- Chain work requests with then() for sequential dependencies.
|
|
25
|
+
- Use expedited work for urgent tasks that must run immediately.
|
|
26
|
+
- Prefer inexact alarms (setInexactRepeating) to save battery.
|
|
27
|
+
- Use Hilt @AssistedInject for WorkManager Worker injection.
|
|
28
|
+
|
|
29
|
+
## References
|
|
30
|
+
- references/workmanager.md
|
|
31
|
+
- references/foreground_services.md
|
|
32
|
+
- references/notifications.md
|
|
33
|
+
- references/scheduling.md
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Foreground Services
|
|
2
|
+
|
|
3
|
+
## Service Types (API 34+)
|
|
4
|
+
- Must declare foreground service type in AndroidManifest.xml.
|
|
5
|
+
- Types: dataSync, camera, connectedDevice, health, location, mediaPlayback, mediaProjection, microphone, phoneCall, remoteMessaging, shortService, specialUse, systemExempted.
|
|
6
|
+
- Declare in manifest: android:foregroundServiceType="location|dataSync".
|
|
7
|
+
- Pass type when starting: ServiceCompat.startForeground(service, id, notification, FOREGROUND_SERVICE_TYPE_LOCATION).
|
|
8
|
+
|
|
9
|
+
## Permissions
|
|
10
|
+
- Declare <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />.
|
|
11
|
+
- API 34+: also declare <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" /> (per type).
|
|
12
|
+
- Some types require runtime permissions (location, camera, microphone).
|
|
13
|
+
|
|
14
|
+
## Notification Requirement
|
|
15
|
+
- Foreground services must display a persistent notification.
|
|
16
|
+
- Call startForeground(notificationId, notification) within 5 seconds of service start.
|
|
17
|
+
- Notification cannot be dismissed by the user while service is running.
|
|
18
|
+
- Use a meaningful notification — explain what the service is doing.
|
|
19
|
+
|
|
20
|
+
## Lifecycle
|
|
21
|
+
- Start with Context.startForegroundService() (API 26+).
|
|
22
|
+
- Call startForeground() immediately in onCreate() or onStartCommand().
|
|
23
|
+
- Stop when work completes: stopForeground(STOP_FOREGROUND_REMOVE) + stopSelf().
|
|
24
|
+
- Do not leave foreground services running indefinitely — system may restrict.
|
|
25
|
+
|
|
26
|
+
## Short-Lived Services
|
|
27
|
+
- shortService type: for tasks that complete in under ~3 minutes.
|
|
28
|
+
- System may stop shortService after the timeout.
|
|
29
|
+
- Use for: quick uploads, brief processing, transient operations.
|
|
30
|
+
- Prefer WorkManager expedited work over short foreground services when possible.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Notifications
|
|
2
|
+
|
|
3
|
+
## Notification Channels (API 26+)
|
|
4
|
+
- Create channels in Application.onCreate() — must exist before posting notifications.
|
|
5
|
+
- Each channel has: id, name, importance level, optional description.
|
|
6
|
+
- Importance levels: IMPORTANCE_HIGH (sound + popup), IMPORTANCE_DEFAULT (sound), IMPORTANCE_LOW (no sound), IMPORTANCE_MIN (no sound or visual).
|
|
7
|
+
- Users can customize per channel — respect their settings.
|
|
8
|
+
- Don't create too many channels — group by user-facing feature.
|
|
9
|
+
|
|
10
|
+
## POST_NOTIFICATIONS Permission (API 33+)
|
|
11
|
+
- Request android.permission.POST_NOTIFICATIONS before posting.
|
|
12
|
+
- Without permission, notifications are silently dropped.
|
|
13
|
+
- Time the request: after user understands value, not at app startup.
|
|
14
|
+
- Handle denial gracefully — app should still function.
|
|
15
|
+
|
|
16
|
+
## Building Notifications
|
|
17
|
+
- Use NotificationCompat.Builder for backward compatibility.
|
|
18
|
+
- Required: setSmallIcon(), setContentTitle(), setContentText().
|
|
19
|
+
- Set PendingIntent with FLAG_IMMUTABLE for tap action.
|
|
20
|
+
- Use setAutoCancel(true) to dismiss on tap.
|
|
21
|
+
|
|
22
|
+
## Styles
|
|
23
|
+
- BigTextStyle: expandable text content.
|
|
24
|
+
- BigPictureStyle: large image preview.
|
|
25
|
+
- InboxStyle: multi-line list format.
|
|
26
|
+
- MessagingStyle: chat conversation format (required for messaging apps).
|
|
27
|
+
- Use appropriate style — improves user experience and system ranking.
|
|
28
|
+
|
|
29
|
+
## Actions & Grouping
|
|
30
|
+
- Add up to 3 notification actions with addAction().
|
|
31
|
+
- Use PendingIntent with FLAG_IMMUTABLE for each action.
|
|
32
|
+
- Group related notifications: setGroup("group_key").
|
|
33
|
+
- Provide a group summary notification for the bundle.
|
|
34
|
+
- Use direct reply action for messaging-style notifications.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Scheduling
|
|
2
|
+
|
|
3
|
+
## AlarmManager
|
|
4
|
+
- Use setInexactRepeating() for periodic tasks — allows system batching.
|
|
5
|
+
- Use setExactAndAllowWhileIdle() only for user-visible alarms (alarm clock, reminders).
|
|
6
|
+
- Use setExact() when exact timing matters but Doze exemption isn't needed.
|
|
7
|
+
- SCHEDULE_EXACT_ALARM permission required (API 31+) for exact alarms.
|
|
8
|
+
- User can revoke exact alarm permission — check with canScheduleExactAlarms().
|
|
9
|
+
|
|
10
|
+
## Alarm Delivery
|
|
11
|
+
- Use BroadcastReceiver as the alarm target.
|
|
12
|
+
- PendingIntent with FLAG_IMMUTABLE for the alarm PendingIntent.
|
|
13
|
+
- Alarms are lost on reboot — re-schedule in BOOT_COMPLETED receiver.
|
|
14
|
+
- Use AlarmManager.AlarmClockInfo for user-visible alarm clock features.
|
|
15
|
+
|
|
16
|
+
## Doze & Standby Implications
|
|
17
|
+
- Doze defers alarms, network, and jobs when device is idle.
|
|
18
|
+
- setAndAllowWhileIdle(): fires during Doze but with rate limiting (~1 per 9 min).
|
|
19
|
+
- setExactAndAllowWhileIdle(): exact timing during Doze, also rate-limited.
|
|
20
|
+
- App Standby buckets throttle alarms for infrequently-used apps.
|
|
21
|
+
|
|
22
|
+
## Network Scheduling
|
|
23
|
+
- Add jitter to periodic network requests — avoid thundering herd on server.
|
|
24
|
+
- Use WorkManager with network constraint instead of AlarmManager for network tasks.
|
|
25
|
+
- Batch multiple network operations into a single work request.
|
|
26
|
+
|
|
27
|
+
## Migration from JobScheduler
|
|
28
|
+
- JobScheduler is lower-level — use WorkManager as the recommended wrapper.
|
|
29
|
+
- WorkManager handles backward compatibility, constraints, and chaining.
|
|
30
|
+
- Migrate JobService implementations to Worker/CoroutineWorker.
|
|
31
|
+
- WorkManager supports all JobScheduler constraints plus more.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# WorkManager
|
|
2
|
+
|
|
3
|
+
## Request Types
|
|
4
|
+
- OneTimeWorkRequest: single execution, optionally expedited.
|
|
5
|
+
- PeriodicWorkRequest: repeating work with minimum interval of 15 minutes.
|
|
6
|
+
- Periodic work has a flex window — work runs within [interval - flex, interval].
|
|
7
|
+
|
|
8
|
+
## Constraints
|
|
9
|
+
- NetworkType: CONNECTED, UNMETERED, METERED, NOT_ROAMING.
|
|
10
|
+
- requiresCharging(): run only when device is charging.
|
|
11
|
+
- requiresStorageNotLow(): run only when storage is sufficient.
|
|
12
|
+
- requiresBatteryNotLow(): run only when battery is adequate.
|
|
13
|
+
- Combine constraints: Constraints.Builder().setRequiredNetworkType(CONNECTED).setRequiresCharging(true).
|
|
14
|
+
|
|
15
|
+
## Work Policies
|
|
16
|
+
- ExistingWorkPolicy.KEEP: skip if existing work with same unique name is running.
|
|
17
|
+
- ExistingWorkPolicy.REPLACE: cancel existing work and start new.
|
|
18
|
+
- ExistingWorkPolicy.APPEND: chain after existing work completes.
|
|
19
|
+
- Use enqueueUniqueWork() with a descriptive unique name.
|
|
20
|
+
|
|
21
|
+
## Chaining
|
|
22
|
+
- then(): sequential execution — output of one feeds into next.
|
|
23
|
+
- WorkManager.getInstance().beginWith(a, b).then(c): a and b run in parallel, then c.
|
|
24
|
+
- Pass data via Data objects (key-value, max 10KB).
|
|
25
|
+
- Use inputMerger for combining outputs from parallel work.
|
|
26
|
+
|
|
27
|
+
## Retry
|
|
28
|
+
- BackoffPolicy.LINEAR or BackoffPolicy.EXPONENTIAL.
|
|
29
|
+
- Minimum backoff delay: 10 seconds, maximum: 5 hours.
|
|
30
|
+
- Return Result.retry() from doWork() to trigger retry.
|
|
31
|
+
|
|
32
|
+
## Observation
|
|
33
|
+
- Observe WorkInfo via LiveData or Flow: getWorkInfoByIdFlow(workId).
|
|
34
|
+
- Check state: ENQUEUED, RUNNING, SUCCEEDED, FAILED, BLOCKED, CANCELLED.
|
|
35
|
+
- Use tags for querying groups of work: getWorkInfosByTagFlow("sync").
|
|
36
|
+
|
|
37
|
+
## Hilt Integration
|
|
38
|
+
- Use @HiltWorker annotation on Worker class.
|
|
39
|
+
- Inject dependencies via @AssistedInject constructor.
|
|
40
|
+
- @Assisted for workerParams: Context and WorkerParameters.
|
|
41
|
+
- Register HiltWorkerFactory in Application.
|