Scroll to Goal — An Android app that helps you stay aligned with your goals by understanding what you consume on screen, not just how long you spend.
Doit runs quietly in the background, capturing content from social media and browser apps when you idle. It analyzes whether your scrolling aligns with your interests or drifts off-track, then gives you nudges — not locks — to stay on course.
-
Dwell Detection — An AccessibilityService monitors whitelisted apps (YouTube, Instagram, TikTok, Reddit, Chrome, X). After 3 seconds of idle time, it auto-captures a screenshot + on-screen text.
-
Session Analysis — Captures are grouped into sessions, uploaded to Firebase, and analyzed by a backend (Gemini). Each session gets an aligned vs. drifting breakdown based on your declared interests.
-
Deflection Alerts — When your alignment drifts below your target, the app flags it. Content-based zone-outs (detected by Gemini) and behavior-based zone-outs (same app 60min, past midnight scrolling) are tracked separately.
-
Bookmarks — Tap the floating widget to manually capture anything worth saving. Bookmarks are identified and stored in your personal library.
-
Weekly Reviews — Aggregated stats across all sessions for the past 7 days, with updated zone-out profiles from the backend.
DoitAccessibilityService ← Core: dwell detection, screenshots, floating widget
├── ScreenTextExtractor ← Walks AccessibilityNodeInfo tree for on-screen text
├── SessionFinalizer ← Packages captures into session dirs
└── SessionUploadWorker ← WorkManager: upload → poll → process results
FirebaseUploader ← Singleton: auth, file upload, job creation, bookmark ID
Analysis Layer
├── ManifestBuilder ← Builds capture manifests for backend
├── ResultProcessor ← Parses session results into Room entities
├── ReviewProcessor ← Parses weekly review results
├── DeflectionDetector ← Computes alignment threshold breaches
├── ZoneOutDetector ← Local behavior zone-out detection
└── WeeklyReviewBuilder ← Aggregates 7-day data for review jobs
Data Layer (Room)
├── UserProfile ← Interests, target alignment %, zone-out lists
├── SessionEntity ← Per-session alignment stats
├── DeflectionEvent ← Threshold breaches and zone-outs
├── SessionActivityEntity ← Per-app activity within sessions
├── SessionTimeBlockEntity ← Time-segmented session data
├── BookmarkEntity ← Manual captures with identification status
└── ReviewEntity ← Weekly review summaries
UI
├── NavActivity ← Bottom nav: Home, Library, Stats, More
│ ├── DashboardFragment ← Alignment ring, recent session, alerts
│ ├── BookmarksFragment ← Manual capture library
│ ├── StatsFragment ← Alignment chart, time blocks, zone-outs
│ └── MoreFragment ← Logs, auto captures, analyze, review
└── ImmersiveViewerActivity ← Full-screen swipeable image viewer
SplashActivity → IntroductionActivity → SignUpActivity → InterestsActivity → BalanceActivity → PermissionsActivity → NavActivity
Each step saves a SharedPreferences flag. On subsequent launches, the splash screen skips completed steps.
- Android Studio (or Gradle CLI)
- JDK 17 (required — JDK 25 is incompatible with Kotlin 1.9.22 / AGP 8.2.2)
google-services.jsoninapp/(Firebase project config)
# If your default JAVA_HOME isn't JDK 17:
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
./gradlew assembleDebug # Build debug APK
./gradlew installDebug # Build + install on connected device/emulatorThe app requires two runtime permissions (prompted during onboarding):
- Display over other apps (SYSTEM_ALERT_WINDOW) — floating capture widget
- Accessibility Service (BIND_ACCESSIBILITY_SERVICE) — screen content reading + screenshots
| Layer | Technology |
|---|---|
| Language | Kotlin 1.9.22 |
| Min SDK | 26 (Android 8.0) |
| Target SDK | 34 (Android 14) |
| Build | Gradle 9.0, AGP 8.2.2 |
| UI | Material 3, ViewPager2, BottomNavigationView |
| Database | Room 2.6.1 (KSP) |
| Background | WorkManager 2.9.0 |
| Backend | Firebase Auth + Storage + Firestore (BOM 32.7.0) |
| Coroutines | kotlinx-coroutines-play-services 1.7.3 |
| App | Package |
|---|---|
| YouTube | com.google.android.youtube |
com.instagram.android |
|
| TikTok | com.zhiliaoapp.musically |
| TikTok Global | com.ss.android.ugc.trill |
com.reddit.frontpage |
|
| Chrome | com.android.chrome |
| Samsung Internet | com.sec.android.app.sbrowser |
| X (Twitter) | com.twitter.android |
com.facebook.katana |
Defined in DoitAccessibilityService.TARGET_PACKAGES and res/xml/accessibility_service_config.xml (must stay in sync).
- Aligned — Content that matches your declared interests (e.g., writing, astronomy, ML)
- Drifting — Content that doesn't match your interests
- Deflection — A nudge triggered when alignment drops below your target threshold
- Zone-out — Detected patterns: content-based (Gemini) or behavior-based (local: same app 60min, past midnight, morning scrolling)
- Saturation — After 5 consecutive auto-captures without user interaction, the session ends to avoid noise
app/src/main/
├── java/com/doitpoc/
│ ├── analysis/ # Backend contract, result processing, deflection/zone-out detection
│ ├── data/ # Room database, entities, DAOs, mock data
│ ├── fragments/ # All fragments in Fragments.kt
│ ├── session/ # Session finalization and upload worker
│ ├── ui/ # Custom views (GlowBarView, PhoneMockupView)
│ ├── utils/ # FileUtils (log rotation, screenshot optimization)
│ └── views/ # CircularProgressView, AlignmentChartView
├── res/
│ ├── drawable/ # Vector icons, shape backgrounds, platform icons
│ ├── layout/ # 23 layout files (activities, fragments, items, widgets)
│ ├── menu/ # Bottom navigation menu
│ ├── values/ # Colors, strings, themes
│ └── xml/ # Accessibility service config, file paths
└── AndroidManifest.xml