Skip to content

AgilePhilosopher/Reiki-session

Repository files navigation

Reiki Session — Wear OS interval timer for Pixel Watch 3

A quiet, eyes‑closed interval timer for Reiki and meditation sessions, built for the Pixel Watch 3 (Wear OS 5). You pick two things — how long the whole session lasts and how long to hold each hand position — and the watch gently buzzes on every position change and again, more firmly, when the session ends. No position names, no numbers, no fuss: just two countdowns and your hands.

The timer runs in a foreground service with a wake lock, so the cues keep coming even when the screen is off and the watch is dozing — exactly what you need when your eyes are closed and your wrist is resting.

Setup screen Running session Settings Session summary

Features

  • Two simple dials — session length and per‑position length, with a live hint of how many positions fit (e.g. 10 positions).
  • Dual countdowns during a session — time left on the current position (large) and time left in the whole session (below).
  • Distinct haptics — a double "heartbeat" buzz on each position change, and three strong half‑second pulses at the very end.
  • Pause / Stop — pause both countdowns (handy when a client turns over from back to front); stop ends the session and shows the summary.
  • Shake to pause — a firm wrist shake toggles pause without opening the screen.
  • Heart‑rate summary — optional. A Fitbit‑style "Done" screen reports duration, positions, average / minimum BPM and start → end heart rate.
  • Keep screen on — optional, for when you want the display to stay lit.
  • Drift‑free timing — the timer is anchored to wall‑clock time, so it stays accurate even when the app is backgrounded and the CPU sleeps.
  • Settings — keep‑screen‑on, heart rate, linked vs independent session math, and default position / session durations, all persisted between runs.

Linked vs independent sessions

The Session by positions setting controls how the two dials relate:

  • On (linked) — the session length is always a whole number of positions. Stepping the session moves it one position at a time; changing the position re‑snaps the session to a clean multiple. The hint reads e.g. 10 positions.
  • Off (independent) — session and position are set separately (session steps by one minute). The number of positions is rounded up and shown as ≈ N.

How it works

  • SessionService — a foreground service (foregroundServiceType="health") that owns the timer, holds a PARTIAL_WAKE_LOCK, drives the Vibrator, and publishes session state the UI observes. Because it's a foreground service with a wake lock, vibration cues survive screen‑off and Doze.
  • Drift‑free timer — elapsed time is computed from SystemClock.elapsedRealtime anchors (start time, accumulated pause time) rather than counting ticks, so a backgrounded session never runs long.
  • Heart rate — captured through Health Services ExerciseClient (HEART_RATE_BPM). Health Connect is unavailable on the watch, so a lightweight Health Services workout is used purely to sample BPM for the summary.
  • Shake detectionShakeDetector watches the accelerometer for a burst of spikes above a g‑force threshold within a short window, with a cooldown.
  • UI — Jetpack Compose for Wear OS. The whole app is three screens: setup, running session, and the post‑session summary, plus a settings screen reached by the gear button below the setup screen (swipe right to leave without saving).

Tech stack

Kotlin · Jetpack Compose for Wear OS · Health Services Client · Foreground service

  • wake lock · SharedPreferences.

compileSdk 35 · minSdk 30 · targetSdk 34 · AGP 8.5.2 · Kotlin 1.9.24 · Gradle 8.7 · JDK 17 (Temurin).

Project structure

app/src/main/java/com/pavel/reikitimer/
  MainActivity.kt     Compose host: setup screen, settings screen, navigation
  SessionScreen.kt    Running‑session UI + Fitbit‑style summary
  SessionService.kt   Foreground service: timer, wake lock, vibration, heart rate
  SessionState.kt     Observable UI state + summary model
  SessionMath.kt      Pure timing math (positions, clamping, snapping)
  TimeFormat.kt       mm:ss / h:mm:ss formatting
  ShakeDetector.kt    Accelerometer shake-to-pause
  Settings.kt         Settings data class
  SettingsStore.kt    SharedPreferences persistence
app/src/test/java/    JVM + Robolectric unit tests
docs/                 Design notes and screenshots

Build

./build.sh    # debug APK -> app/build/outputs/apk/debug/app-debug.apk

build.sh sources env.sh (which sets JAVA_HOME / ANDROID_HOME) and runs ./gradlew assembleDebug.

Install on Pixel Watch 3

The watch has no data USB port, so install over Wi‑Fi (Mac and watch on the same network). On the watch: Settings → System → About → tap Build number ×7 → Developer options → enable ADB debugging and Wireless debugging → Pair new device (this shows an IP:port and a pairing code).

./deploy-watch.sh pair    <IP:PAIRING_PORT> <CODE>   # once
./deploy-watch.sh install <IP:DEBUG_PORT>            # IP:port from the Wireless debugging page

The debug port rotates each time wireless debugging reconnects — read the current one from the Wireless debugging screen. Turn wireless debugging off afterwards to save battery.

Emulator

source env.sh && emulator -avd reiki_wear   # Wear OS 5, arm64

Tests

./gradlew testDebugUnitTest

Two tiers: pure‑JVM logic tests (timing math, formatting, shake detection, UI state) and Robolectric tests for Android‑dependent pieces — 30 tests across SessionMathTest, SessionUiStateTest, TimeFormatTest, ShakeDetectorTest, SettingsStoreTest, and SessionServiceTest.


A personal project, shared in case it's useful to other Reiki and meditation practitioners. The violet hands icon nods to the crown‑chakra colour often used to depict Reiki energy.

About

Quiet interval timer for Reiki & meditation on Pixel Watch 3 (Wear OS): dual countdowns, haptic cues, heart-rate summary.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors