A single Android app that consolidates the trackers you'd otherwise juggle across five different apps: budget, study time, screen time, reminders, and notes. Built with Jetpack Compose and Material 3, backed by Room for local persistence, with optional Firebase (Auth + Firestore) sync across devices.
- Overview
- Screenshots
- Features
- Architecture
- Tech Stack
- Getting Started
- Firebase Setup
- Building & Testing
- Project Structure
- Roadmap
- Contributing
- License
ApexTracker is an MVVM Android app organized as six independent tracker modules living behind a single bottom-level menu screen. Every module works fully offline first (Room is the source of truth); signing in with Google adds optional Firestore-backed sync so data can follow you across devices.
| Overview | Budget Tracker | Study Tracker |
|---|---|---|
| Screen Time | Reminders | Notes |
|---|---|---|
Screenshots and GIFs above are placeholders — drop your own captures into
docs/screenshots/using the same filenames (or update the paths) before publishing.
Budget Tracker
- Track one-off budget items alongside recurring subscriptions, grouped by category.
- Subscriptions auto-generate their next
BudgetItemon their renewal date, including back-filling months that were missed while the app wasn't open. - Optional calendar view of spending by day.
Study Tracker
- Stopwatch-style session timer with HH:MM:SS display.
- Historical session log with compact duration summaries.
Screen Time
- Per-app foreground usage tracked via
UsageStatsManager, with an excluded-apps list to keep noise (launchers, system UI) out of the totals. - Cross-device usage comparison when signed in, refreshed on a lightweight polling loop.
Reminders
- One-off and recurring reminders (daily, weekly, monthly, custom day-of-week patterns) with exact
AlarmManagerscheduling. - Notifications survive reboots via a boot-completed receiver that re-arms all active alarms.
- Falls back to inexact alarms automatically if the user revokes the exact-alarm permission.
Notes
- Lightweight bulleted note editor with indent/outdent support.
Cross-cutting
- Four selectable color themes (Emerald, Ocean, Magma, Royal), each with dedicated light and dark variants.
- Google Sign-In (Credential Manager API) with optional Firestore sync of settings, budget data, subscriptions, notes, reminders, study sessions, and per-device screen time.
- Fully usable signed out — cloud sync is additive, never required.
MainActivity
-> AuthViewModel (Google Sign-In / FirebaseAuth)
-> FirebaseManager (Firestore read/write)
-> AppNavigation (NavHost)
-> menu
-> overview -> OverviewView -> OverviewViewModel
-> budget_tracker -> BudgetTrackerView -> BudgetViewModel
-> study_tracker -> StudyTrackerView -> StudyViewModel
-> screen_time -> ScreenTimeTrackerView -> ScreenTimeViewModel
-> reminders -> ReminderView -> ReminderViewModel
-> notes -> NoteView -> NoteViewModel
Each module follows the same shape: a Compose View, an AndroidViewModel, and a Room Entity + Dao pair, all backed by a single AppDatabase singleton.
| Route | View | ViewModel | Entities |
|---|---|---|---|
overview |
OverviewView.kt |
OverviewViewModel.kt |
Aggregates all DAOs |
budget_tracker |
BudgetTrackerView.kt |
BudgetViewModel.kt |
BudgetItem, Category, Subscription |
study_tracker |
StudyTrackerView.kt |
StudyViewModel.kt |
StudySession |
screen_time |
ScreenTimeTrackerView.kt |
ScreenTimeViewModel.kt |
ScreenTimeSession, ExcludedApp |
reminders |
ReminderView.kt |
ReminderViewModel.kt |
Reminder |
notes |
NoteView.kt |
NoteViewModel.kt |
Note |
Reminder delivery is handled outside the Compose layer: ReminderScheduler sets an exact AlarmManager alarm per active reminder, ReminderAlarmReceiver enqueues a ReminderWorker (WorkManager) which posts the notification, and ReminderBootReceiver re-arms everything after a device reboot.
For the full, continuously updated architecture notes (including known limitations and in-progress work), see CLAUDE.md.
| Layer | Choice |
|---|---|
| UI | Jetpack Compose, Material 3 |
| Architecture | MVVM (AndroidViewModel + StateFlow) |
| Local persistence | Room 2.8.4 |
| Cloud sync | Firebase Auth + Firestore |
| Auth | Credential Manager API + Google ID |
| Background work | WorkManager, AlarmManager |
| Image loading | Coil |
| Language | Kotlin 2.4.0 |
| Build | Android Gradle Plugin 9.2.1, KSP 2.3.9 |
- Android Studio (recent stable channel), which bundles a JDK 17+ JBR runtime.
- An Android device or emulator running API 26 (Android 8.0) or higher.
- JDK 17+ available on your
PATHor via Android Studio's bundled JBR — the system defaultjavaon some machines is older and will not run Gradle for this project.
git clone https://github.com/aadityad12/Trackers.git
cd Trackers
JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home" ./gradlew assembleDebug(Adjust JAVA_HOME to wherever a JDK 17+ install lives on your machine, e.g. via /usr/libexec/java_home -V on macOS.)
The app builds and runs fully offline without any Firebase configuration — sign-in and cloud sync simply stay disabled until you add a google-services.json (see below).
Cloud sync (Google Sign-In + Firestore) is optional but requires a real Firebase project:
- Create a project in the Firebase console and add an Android app with package name
com.example.apextracker. - Register your machine's debug SHA-1 fingerprint:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android - Download the generated
google-services.jsonand place it atapp/google-services.json(this file is gitignored and must never be committed). - Enable Google as a sign-in provider under Firebase Authentication, and create a Firestore database in the console.
- Rebuild — Google Sign-In and Firestore sync will now work end-to-end.
# Debug APK
JAVA_HOME="<jdk17-path>" ./gradlew assembleDebug
# Install on a connected device
JAVA_HOME="<jdk17-path>" ./gradlew installDebug
# Unit tests
JAVA_HOME="<jdk17-path>" ./gradlew test
# Lint (NewApi / error-severity issues are build-blocking)
JAVA_HOME="<jdk17-path>" ./gradlew lintDebug
# Instrumented tests (requires a connected device/emulator)
JAVA_HOME="<jdk17-path>" ./gradlew connectedAndroidTestUnit test coverage currently focuses on pure logic extracted out of the ViewModels: reminder scheduling, overview formatting, note bullet editing, pending-reminder cloud-ID resolution, and screen time usage aggregation.
app/src/main/java/com/example/apextracker/
├── MainActivity.kt # Entry point, theme state, navigation host
├── AuthViewModel.kt # Google Sign-In / FirebaseAuth
├── FirebaseManager.kt # All Firestore reads/writes
├── AppDatabase.kt # Room singleton + DAOs
├── Converters.kt # Room type converters
├── Budget*.kt # Budget tracker module
├── Study*.kt # Study tracker module
├── ScreenTime*.kt # Screen time module
├── Reminder*.kt # Reminders module + AlarmManager/WorkManager plumbing
├── Note*.kt # Notes module
├── Overview*.kt # Cross-module aggregate dashboard
├── DurationFormat.kt # Shared "Xh Ym" formatting
├── PeriodicRefresh.kt # Shared 30s polling helper
└── ui/theme/ # Theme, color tokens, typography
- Route Budget Tracker's Firestore sync through the same
cloudIdscheme the rest of the app uses. - Move cloud sync from "once at sign-in" to continuous, per-entity sync.
- Wire the currently-unreachable
BudgetCalendarViewinto a navigable tab. - Receipt OCR for the Budget Tracker ("extract from receipt").
- Always-on-display support for the Study Tracker.
- Home screen widgets, Canvas-based ring-chart visualizations, biometric lock for Budget/Notes, and Gemini-powered daily insights.
See CLAUDE.md for the full, current list of known issues and their fix status.
Issues and pull requests are welcome. Please run the build, unit tests, and lint locally before opening a PR:
JAVA_HOME="<jdk17-path>" ./gradlew assembleDebug test lintDebugNo license has been chosen for this project yet. All rights are reserved by the author until a license is added.