Android · Kotlin
Stop Scroll
Screen-time tools measure time in an app. Stop Scroll measures time spent scrolling, which is a different and more useful number: forty minutes in Instagram might be five minutes of messaging and thirty-five of feed.
- Separates active scrolling from idle time through an
AccessibilityService - Different idle rules for list feeds (Reddit, YouTube) and full-screen video (TikTok, Reels, Shorts)
- Week-over-week and month-over-month comparisons, with honest clipping of partial periods
- Charts drawn directly on
Canvas— no charting dependency
Kotlin · Jetpack Compose · Material 3 · Room
How it works
Two kinds of feed, two ways of measuring
List-shaped feeds — Reddit, the YouTube home feed — report their own scrolling. TYPE_VIEW_SCROLLED carries both the timing and the distance, and the event names the view that scrolled, so its resource id identifies the surface without walking the view tree.
Full-screen video feeds report nothing at all. A dump of YouTube Shorts contains no node marked scrollable="true" anywhere: the pager is never exposed as an accessibility-scrollable container, so no amount of swiping emits an event. There the feed is found by its view id (reel_recycler) and timed by being on screen. That measures time in the feed rather than time with your thumb moving — which is the number you wanted anyway, since most of a Shorts session is watching. Those bouts report no scroll distance, because none was ever measured.
Why one threshold would not do
SessionTracker folds the event stream into bouts, and short-video feeds get a longer idle window and more dwell credit than text feeds. One swipe on TikTok holds attention far longer than one flick on Reddit; a single threshold for both would either shred TikTok sessions into fragments or credit a Reddit glance as a full minute of scrolling.
A bout always ends at its last scroll plus the dwell credit, never at the moment the tracker noticed it had ended — so noticing late costs nothing in accuracy.
Comparisons that don't flatter
While a period is still running, the earlier period is clipped to the same elapsed span. A Tuesday-morning "this week" measured against a complete previous week would always show a comforting drop. Once the period is finished, both are taken whole.
Nothing leaves the device
The app holds no internet permission. Nothing is read from the screen — only which app scrolled, when, and how far. It all lives in a Room database on the device, with a configurable retention window and a delete-everything button.
Drawing rather than depending
The charts are drawn directly on Canvas rather than pulled from a charting library, over one palette of eight categorical slots validated as a set for colour-blind separation and stepped separately for light and dark surfaces. A package keeps the slot it was first given, so filtering a chart never repaints the series that remain, and the ninth app onwards folds into a neutral "Other" rather than being handed a generated hue.
Twenty-nine unit tests cover the timing and aggregation logic.