|
| 1 | +# TapLock |
| 2 | + |
| 3 | +Android screen-lock utility using accessibility services and widgets. Single-module Kotlin/Compose app. |
| 4 | + |
| 5 | +## Commands |
| 6 | + |
| 7 | +```bash |
| 8 | +./gradlew assembleDebug # Build debug APK |
| 9 | +./gradlew testDebugUnitTest # Unit tests (DoubleTapDetector) |
| 10 | +./gradlew connectedAndroidTest # Instrumented UI tests (requires device/emulator) |
| 11 | +./gradlew lintDebug # Lint checks |
| 12 | +``` |
| 13 | + |
| 14 | +## Architecture |
| 15 | + |
| 16 | +Single `:app` module. All source in `app/src/main/java/com/ah/taplock/`: |
| 17 | + |
| 18 | +- **MainActivity.kt** — Compose settings UI, onboarding flow, permission management |
| 19 | +- **TapLockAccessibilityService.kt** — Core service: overlay management, double-tap detection on status bar and lock screen |
| 20 | +- **TapLockWidgetProvider.kt** — RemoteViews-based 1x1 widget |
| 21 | +- **FloatingButtonService.kt** — Draggable overlay button (foreground service) |
| 22 | +- **TapLockTileService.kt** — Quick Settings tile |
| 23 | +- **DoubleTapDetector.kt** — Time-window tap detection with injectable clock |
| 24 | +- **VibrationHelper.kt** — API-level-aware vibration (Android 13+ vs older) |
| 25 | +- **Utils.kt** — Accessibility state check utility |
| 26 | + |
| 27 | +## Build Config |
| 28 | + |
| 29 | +- Min SDK 31 (Android 12), Target/Compile SDK 36 |
| 30 | +- Java 21, Kotlin 2.3.20, AGP 9.2.0 |
| 31 | +- Dependencies managed via `gradle/libs.versions.toml` |
| 32 | +- R8 minification enabled for release builds |
| 33 | + |
| 34 | +## Code Style |
| 35 | + |
| 36 | +Kotlin official style (`kotlin.code.style=official`). No detekt/ktlint — use `./gradlew lintDebug`. |
| 37 | + |
| 38 | +## Gotchas |
| 39 | + |
| 40 | +- `TapLockAccessibilityService.instance` is intentionally static (`@Suppress("StaticFieldLeak")`). Cleared in `onUnbind()`/`onDestroy()`. Don't add another static reference. |
| 41 | +- Overlay touch handling: must call `performClick()` after ACTION_UP. Overlay height changes reset the double-tap detector to prevent false positives. |
| 42 | +- Lock screen tap zone detection uses depth-first traversal to find clickable nodes — touches near interactive elements are forwarded, not counted. |
| 43 | +- Widget uses RemoteViews (no Compose). Custom icon requires manual cache invalidation via ACTION_APPWIDGET_UPDATE broadcast. |
| 44 | +- VibrationHelper branches on Build.VERSION for Android 13+. Both paths must be maintained. |
| 45 | +- SharedPreferences are synchronous throughout — changes immediately trigger recomposition via preference listener. |
0 commit comments