Alex Therakathu
Back to the work

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.

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.