Android: return-to-start stop prompt (epic #997) #999

Closed
opened 2026-08-07 03:51:27 +00:00 by spikerj · 1 comment
Owner

Part of epic #997.

  • core/tracking/ReturnToStartDetector.kt — mirror of iOS spec, TrackStats.haversineKm.
  • core/tracking/ReturnPromptController.kt — plain class owned by RecordingService; reads recording.state.value (paused, points.firstOrNull() start), invokes onFire when the setting allows.
  • core/audio/ReturnPromptSound.kt — res/raw/return_prompt.ogg (transcoded from iOS gap-ahead.caf) via MediaPlayer USAGE_ASSISTANCE_SONIFICATION + transient-may-duck focus; one-shot vibration. Self-played by the service so it works with POST_NOTIFICATIONS denied.
  • RecordingService.kt: feed returnPrompt.onRawFix(...) in onLocationResult before/independent of offerFix; new tracking_alerts IMPORTANCE_HIGH channel (sound null — service self-plays; existing activity_tracking is LOW + immutable); notification id 921 auto-cancel with Stop & save (ACTION_STOP_AND_SAVE) + Keep recording (ACTION_DISMISS_RETURN_PROMPT) service PendingIntents; STOP_AND_SAVE handler completes routes.saveCompleted("Untitled activity", RUN, points) before stopSelf(); ACTION_STOP/onDestroy cancel 921 + reset detector.
  • Settings IconButton in TrackerScreen → dialog Switch, SharedPreferences("tracker_prefs") return_prompt_enabled default true.
  • ReturnToStartDetectorTest.kt — matrix identical to iOS. No manifest changes.
Part of epic #997. - `core/tracking/ReturnToStartDetector.kt` — mirror of iOS spec, `TrackStats.haversineKm`. - `core/tracking/ReturnPromptController.kt` — plain class owned by `RecordingService`; reads `recording.state.value` (paused, `points.firstOrNull()` start), invokes onFire when the setting allows. - `core/audio/ReturnPromptSound.kt` — `res/raw/return_prompt.ogg` (transcoded from iOS gap-ahead.caf) via MediaPlayer USAGE_ASSISTANCE_SONIFICATION + transient-may-duck focus; one-shot vibration. Self-played by the service so it works with POST_NOTIFICATIONS denied. - `RecordingService.kt`: feed `returnPrompt.onRawFix(...)` in `onLocationResult` before/independent of `offerFix`; new `tracking_alerts` IMPORTANCE_HIGH channel (sound null — service self-plays; existing `activity_tracking` is LOW + immutable); notification id 921 auto-cancel with Stop & save (`ACTION_STOP_AND_SAVE`) + Keep recording (`ACTION_DISMISS_RETURN_PROMPT`) service PendingIntents; STOP_AND_SAVE handler completes `routes.saveCompleted("Untitled activity", RUN, points)` before `stopSelf()`; ACTION_STOP/onDestroy cancel 921 + reset detector. - Settings IconButton in `TrackerScreen` → dialog Switch, `SharedPreferences("tracker_prefs")` `return_prompt_enabled` default true. - `ReturnToStartDetectorTest.kt` — matrix identical to iOS. No manifest changes.
Author
Owner

Verified complete 2026-08-07 — closing.

  • Code: spikersoft-android@04d9c7b (PR #11, feat/return-to-start-999) — every bullet in the body is present on main:
    • core/tracking/ReturnToStartDetector.kt + core/tracking/ReturnToStartDetectorTest.kt (the iOS-identical matrix)
    • core/tracking/ReturnPromptController.kt
    • core/audio/ReturnPromptSound.kt with the transcoded asset committed at app/src/main/res/raw/return_prompt.ogg (the only file in res/raw/)
    • core/tracking/RecordingService.kt — ALERT_CHANNEL_ID = "tracking_alerts" (:313), ACTION_STOP_AND_SAVE (:323) with its handler at :119 and the notification action at :231, and PREF_RETURN_PROMPT_ENABLED = "return_prompt_enabled" (:317)
    • the settings switch surfaced from TrackerScreen
  • Live: nothing runtime-observable from this box (native app).
  • Shipped by: android PR #11.

Not migrated: nothing left to do. (The iOS twin, #998, is the piece still outstanding in this epic — migrated to spikerj/spikersoft-ios#17.)

— Opus 5 Agent

Verified complete 2026-08-07 — closing. - **Code:** `spikersoft-android@04d9c7b` (PR #11, `feat/return-to-start-999`) — every bullet in the body is present on main: - `core/tracking/ReturnToStartDetector.kt` + `core/tracking/ReturnToStartDetectorTest.kt` (the iOS-identical matrix) - `core/tracking/ReturnPromptController.kt` - `core/audio/ReturnPromptSound.kt` with the transcoded asset committed at `app/src/main/res/raw/return_prompt.ogg` (the only file in `res/raw/`) - `core/tracking/RecordingService.kt` — `ALERT_CHANNEL_ID = "tracking_alerts"` (`:313`), `ACTION_STOP_AND_SAVE` (`:323`) with its handler at `:119` and the notification action at `:231`, and `PREF_RETURN_PROMPT_ENABLED = "return_prompt_enabled"` (`:317`) - the settings switch surfaced from `TrackerScreen` - **Live:** nothing runtime-observable from this box (native app). - **Shipped by:** android PR #11. Not migrated: nothing left to do. (The iOS twin, #998, is the piece still outstanding in this epic — migrated to spikerj/spikersoft-ios#17.) — Opus 5 Agent
Sign in to join this conversation.