Lan StopWatch is a visual activity tracker and behavioral logging tool for Android, designed to provide a clear "shape" of your day at a glance. It captures a precise history of "what" you did and "when" you did it, mapping your daily behavior—from sleep patterns to work sessions—onto a 24-hour circular dial.
While it functions as an interval stopwatch, its primary value lies in generating long-term statistics for self-comparison. By recording these daily activities, users can analyze their progress over time, identifying trends such as shifting sleep schedules, fluctuations in productivity, or changes in social habits.
More screenshots
- Platform: Android (Min SDK 24).
- Language: Kotlin.
- UI Framework: Jetpack Compose (Material 3).
- Database: Room Persistence Library.
- Dependency Injection: Koin (used for ViewModel and DAO management).
- Time & Math: Korlibs (Klock for interval math, Korma for geometry).
- Architecture: MVVM with Kotlin Coroutines and Flow for reactive data streams.
- 24-Hour Circular Dial: A custom Canvas-based visualization that maps daily events onto a clock face with real-time updates and sweep gradients.
- Behavioral Tracking: Create custom trackers to log anything from sleep cycles to gaming sessions.
- Interval Persistence: Automatically calculates and stores durations locally, ensuring data survives app restarts.
- Timezone Awareness: Captures GMT offsets for every interval to maintain accuracy during travel.
- Cross-Device Ready: Data models include
deviceIdfields, laying the groundwork for the upcoming local network sync feature.
- Flickering UI & State Persistence: One of the biggest challenges was a "flickering" effect where the activity circle would momentarily disappear during database updates. This was caused by the UI receiving empty data before the new state arrived. I solved this by leveraging
drawWithCache()and using a Koin-managed ViewModel to ensure the UI holds onto the previous data until the new state is fully ready. - Configuration Management: Handling screen rotations in Compose can be notoriously difficult for complex UI states (like cursor positions in text fields). To maintain a smooth experience, I opted to manage configuration changes manually in the
AndroidManifest(orientation|screenSize|density), which prevented unnecessary recompositions from clearing transient UI states. - The "Every Second" Recomposition: The app currently recomposes the UI every second to update the "ongoing" timers. While functional, finding the balance between real-time accuracy and battery efficiency remains an ongoing optimization goal.
- Geometry on Canvas: Mapping Unix timestamps to degrees on a circle required precise math, especially when accounting for timezone offsets and ensuring the "current time" indicator aligned perfectly with the system clock.
In Development
The app is currently just a demo and not ready for real use.






