# Original v1 brief (verbatim) Preserved as written, before any of it was implemented or corrected. See [README.md](README.md) for which parts were changed and why — several would not have compiled or would have dropped GPS fixes under load. The project was called **MotoTrack** at this point, with package `com.example.mototrack`. Both were renamed to Rippr / `com.rippr` during development. --- ## Project Specification: MotoTrack Single-Session Android Recorder **Goal:** Build a bare-bones, highly resilient Native Android app (Kotlin) to record GPS telemetry during motorcycle group rides today. **Design Priority:** Unbreakable execution over UI beauty. Must run as an un-killable **Foreground Service** that records telemetry to a local SQLite database and streams updates over HTTP/REST when online. ### 1. Setup & Installation Prerequisites: Android Studio (Koala/Ladybug+), a physical Android phone on 8.0+ (API 26+) with USB debugging on, and a cable. Project setup: New Project → Empty Activity (Jetpack Compose); Name `MotoTrack`; package `com.example.mototrack`; Minimum SDK API 26; Kotlin. Dependencies specified: ```kotlin plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) id("kotlin-kapt") } dependencies { implementation("com.google.android.gms:play-services-location:21.2.0") val roomVersion = "2.6.1" implementation("androidx.room:room-runtime:$roomVersion") implementation("androidx.room:room-ktx:$roomVersion") kapt("androidx.room:room-compiler:$roomVersion") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0") implementation("androidx.compose.material3:material3:1.2.1") } ``` ### 2. Task breakdown **Task 1 — Manifest & permissions.** `ACCESS_FINE_LOCATION`, `ACCESS_COARSE_LOCATION`, `FOREGROUND_SERVICE`, `FOREGROUND_SERVICE_LOCATION`, `POST_NOTIFICATIONS`, `INTERNET`; `MainActivity` exported with a LAUNCHER intent filter; `TrackingService` declared with `android:foregroundServiceType="location"`. **Task 2 — Local storage (Room).** `TrackPoint` entity with `id`, `timestamp`, `latitude`, `longitude`, `speedKmh`, `altitudeM`. `TrackPointDao` with `insertPoint`, `getAllPoints`, `getMaxSpeed`, `getPointCount`. `AppDatabase` at version 1 with a `@Volatile` singleton. **Task 3 — Un-killable foreground service.** `TrackingService` holding a `FusedLocationProviderClient`, a `CoroutineScope(Dispatchers.IO + SupervisorJob())`, and a `LocationCallback` that converts `loc.speed * 3.6f` to km/h and launches a coroutine per fix to `insertPoint`. `startForeground` with `FOREGROUND_SERVICE_TYPE_LOCATION` on Q+, `START_STICKY`, a `LocationRequest` at `PRIORITY_HIGH_ACCURACY` / 1000 ms with a 500 ms minimum interval, and an `IMPORTANCE_LOW` notification channel. **Task 4 — Simple UI & controller.** `MainActivity` with `mutableStateOf` fields for `isRecording`, `maxSpeed` and `pointCount`; a `RequestMultiplePermissions` launcher; a `LaunchedEffect` polling `getMaxSpeed()` and `getPointCount()` every second; and a single button toggling between START and STOP RECORDING. ### 3. Verification & deployment 1. Attach device, click Run 'app' in Android Studio 2. Grant location and notification permissions 3. Tap START RECORDING; confirm the persistent notification appears 4. Lock the screen and take a 1-minute test walk/drive 5. Unlock: verify Max Speed and Points Captured are updating --- ## Notable in hindsight - **"Streams updates over HTTP/REST"** appears in the goal but no task defines it. The uploader was built anyway, since it was clearly intended. - **The 1 Hz polling loop** in Task 4 was replaced by a Room `Flow`. - **A coroutine launched per GPS fix** (Task 3) offers no back-pressure guarantee; this became the unbounded `Channel` and single batched writer that still underpins recording. - **`super.onCreate()`** in Task 4 is missing its argument and would not compile. - The verification steps assume Android Studio. Everything ended up driven from the CLI instead — see [../DEVELOPMENT.md](../DEVELOPMENT.md).