Re-exported at 46a0726, which adds README.md plus docs/ARCHITECTURE, DEVELOPMENT, TESTING, v1 history including the original brief, and a v3 backlog. 112 files, and the bundle now carries 19 commits. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.0 KiB
Original v1 brief (verbatim)
Preserved as written, before any of it was implemented or corrected. See 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:
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
- Attach device, click Run 'app' in Android Studio
- Grant location and notification permissions
- Tap START RECORDING; confirm the persistent notification appears
- Lock the screen and take a 1-minute test walk/drive
- 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
Channeland 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.