Tejas VinayBengaluru

Work 02 Native Android and device data

Contrail

An Android group-ride app. Friends join with a code, the admin approves them, and everyone sees each other on a live minimap, with an alert when someone leaves the lead's line.

Platform
Android 8 to 16
Year
2026
Code
Private repo, code walkthrough on request.
Stack
  • Kotlin
  • Jetpack Compose
  • Firebase Realtime Database
  • MapLibre
  • Room
  • WorkManager
  • Android Auto

01 The problem

On a group ride, someone always misses a turn. Sharing your location in a chat app shows a dot, not whether that dot is still on the route, and it keeps running long after the ride ends.

Contrail is built for one ride at a time: create a party, share a code, ride, end it. The live copy is deleted afterwards, and each phone keeps its own history.

02 My role

Sole developer, from the written build plan through eight milestones: a background-location spike, live dots, parties and approval, the lead's trail and off-trail alerts, chat and quick actions, a floating minimap over Google Maps, a setup checklist, and Android Auto.

03 Architecture

There is no server. Every phone talks to one Firebase Realtime Database, and the security rules do the job an API would. Nobody can list rides or codes. Joiners wait in "pending" and can't read a single position until the admin approves them, and a kicked rider loses access the moment they're removed.

Timing values (sweep takeover after three minutes, auto-stop after an hour with no positions, a two-minute cleanup grace) live in one policy file. The Android build, the rules generator and the test simulator all read it, so they can't drift apart.

Contrail: one phone's path to the groupgenerated rulesGPS fixforeground serviceLatest-position writerone in flight, one latest slotDurable journaltrail + help, reconciled on reconnectRoom historystays on the phoneFirebase RTDBsecurity rules arethe APIOther ridersapproved membersonlyride-policy.jsonone file for app, rules, simulatorContrail: one phone's path to the groupliveGPS fixforeground serviceLatest-positionwriterone in flight, onelatest slotDurable journaltrail + help,reconciled onreconnectFirebase RTDBsecurity rules are the APIOther ridersapproved members only
the path this case study is about outside the system

04 Two hard decisions

  1. A

    Send only the latest position, never lose the trail

    Firebase queues every offline write. After a tunnel, that means replaying a minute of stale positions as if they were live. Contrail keeps one write in flight and one latest slot, and purges the backlog on disconnect.

    That purge would also wipe the lead's breadcrumb trail and any help alerts. Those go through a separate on-phone journal that survives the purge and process death, and reconciles on reconnect.

  2. B

    Off-trail alerts that don't cry wolf

    A rider is flagged only after more than 20 seconds over 100 m from the lead's trail at more than 10 km/h, and cleared at 60 m. Poor GPS fixes can't start or clear an alert.

    If more than half the group leaves the trail, the lead gets one "the group has split" alert instead of a burst of names.

05 The result

JVM unit tests
232
security-rules tests
36
help alert to every emulated rider
30 ms
release APK, arm64
16 MB

Version 0.8 across eight milestones, Android 8 to 16 (API 26–36), with zero lint errors.

Field testing on real phones is the next step. Everything here is desk- and emulator-validated.

Screens show seeded demo data on local or emulated devices. No real users or records.

Sources: every claim on this page traces to the contrail repo (Group Ride App — Build Plan.md, README.md, config/ride-policy.json, database.rules.json, app/build.gradle.kts).

Next case studyHealth Data Bridge