An Android water-intake tracker — a Jetpack Compose app plus a home-screen widget that share the same data.
- Home-screen widget (Glance) — a circular progress ring showing today's total vs. goal, with a flush + to log a quick increment. Tapping the tile opens the app.
- App — Today screen with the ring, quick-add chips (+8 / +16 / +32 oz), a custom-amount sheet, a 7-day chart, and the day's log. Step through past days, tap any entry to edit/delete, and set the daily goal in Settings.
- Widget and app stay in sync through a shared DataStore.
Requires Android Studio (or the Android SDK + JDK 17).
Open the android-widget/ folder in Android Studio, or for command-line builds point Gradle at your SDK:
echo "sdk.dir=/path/to/Android/Sdk" > android-widget/local.propertiescd android-widget
./gradlew :app:assembleDebug # build the debug APK
./gradlew :app:installDebug # install on a connected device/emulatorcd android-widget
./gradlew :app:testDebugUnitTest # fast local JVM unit tests (no device needed)
./gradlew :app:connectedDebugAndroidTest # instrumented UI tests (needs a device/emulator)For day-to-day work prefer testDebugUnitTest — it skips JaCoCo instrumentation and
finishes in seconds. CI runs the createDebug*CoverageReport variants instead, which add
coverage instrumentation overhead, only because it uploads coverage to Coveralls. Reach for
those locally only when you need a coverage report.
TapSip runs standalone — no phone required. It uses the native three-button layout (action bar on the right edge):
- UP logs a drink, DOWN removes one (undoing an unsynced add first, otherwise subtracting from today's total).
- SELECT opens an options menu: Drink size (8/12/16/24 oz), Daily goal (48/64/80/100/128 oz), History (a 7-day chart with the current streak), and Sync now.
- The ring turns green and buzzes when the goal is reached. At midnight the watch archives the finished day and resets the ring on its own; the streak counts consecutive days that met the goal.
When the companion Android app is present it still works as before: the watch mirrors its log ops to the phone (offline-tolerant queue) and goal changes sync both ways. So the same build serves standalone Pebble users and people with the Android app.
The watchapp's sync/queue/ring/history/streak logic lives in a UI- and SDK-free
core (pebble/src/c/water_core.{c,h}) so it can be unit-tested on the host with
just a C compiler — no Pebble SDK, emulator, or watch needed:
cd pebble/test
make test # build + run the unit tests
make coverage # line coverage of water_core via gcovCI runs make test on every PR and reports make coverage for visibility.
| Path | Description |
|---|---|
android-widget/app/src/main/java/com/watertracker/widget/ |
Glance home-screen widget (WaterTrackerWidget, AddWaterAction) + host MainActivity |
android-widget/app/src/main/java/com/watertracker/widget/app/ |
Compose app — screens, components, icons, data model, DataStore repository, design tokens |
android-widget/app/src/test/ |
Unit tests for the data/logic layer |
pebble/src/c/water.c |
Pebble watchapp — UI, persistence, AppMessage sync glue |
pebble/src/c/water_core.{c,h} |
UI/SDK-free sync-queue, total, and ring logic (host-testable) |
pebble/test/ |
Host C unit tests for water_core + Makefile |
water-tracker-compact.jsx |
Original design reference for the widget ring |