Skip to content

Repository files navigation

Expense Tracking App

An offline-first Android personal-finance app with an AI assistant, OCR receipt scanning, monthly budgets with rollover, recurring subscriptions, and a home-screen Quick-Add widget. Built with Kotlin, Room, WorkManager, and a pluggable LLM provider layer (on-device Gemini Nano or any OpenAI-compatible cloud).

  • Package: mobile.com.expense_tracking_app
  • Min SDK: 26 (Android 8.0) · Target/Compile SDK: 36
  • Language: Kotlin 2.1 · Build: AGP 9.1, Gradle wrapper
  • Default currency: VND (Vietnamese đồng)

Features

Dashboard

  • Today / monthly / yearly spending totals with day-over-day and month-over-month deltas
  • Spending-trend chart (MPAndroidChart) and category breakdown
  • "AI Action Recommendation" card surfacing on-device or cloud-generated insights
  • Recent transactions list with quick edit/delete

Add expense

  • Bottom-sheet entry with amount quick-pick, category picker, notes, and date
  • One-tap Quick-Add templates (chips above the form mirror the home-screen widget)
  • Receipt scanning — camera or gallery → ML Kit OCR → LLM-powered line-item extraction → review/edit each line before saving
  • Optional "Recurring" toggle promotes a one-off entry into a subscription

Budgets

  • Per-category monthly limits with progress bars and alert thresholds
  • Calendar navigation — view past months read-only; future navigation is bounded (no >12 months ahead)
  • Rollover unused budget into the next month
  • Temporary budget override for the current month without changing the default
  • Monthly archival handled in the background by BudgetArchiveWorker

Recurring subscriptions

  • Weekly / monthly / yearly cycles with optional expiry date
  • Auto-record into transactions via ExpenseAutoInsertWorker
  • "Due soon" filter, pause/resume, validation against past dates and expiry-before-billing
  • Optional reminder before billing date

AI Assistant (chat)

  • Pluggable provider registry — choose any of:
    • On-device: Gemini Nano via ML Kit GenAI (Android 14+, supported Pixel/Samsung devices)
    • Cloud: Google Gemini, OpenAI, Anthropic Claude, DeepSeek, Groq, OpenRouter, or any OpenAI-compatible endpoint
  • Streams responses via OkHttp SSE
  • Tool-calling: the assistant can propose actions (log expense, add category, edit budget, create subscription) which you confirm in-app before they touch the database
  • API keys stored in EncryptedSharedPreferences
  • "Prefer on-device when available" toggle to keep data local

Home-screen widget

  • Quick-Add widget with swipeable template chips and a today-total readout
  • Tap a chip → QuickAddInsertWorker logs the transaction in the background
  • "+ Add" tile deep-links into MainActivity and opens the Add Expense sheet

Settings

  • Username + avatar (12 built-in avatars)
  • Manage spending categories (icon, color, monthly budget — up to a hard cap)
  • Manage Quick-Add templates (label, amount, optional note)
  • AI configuration — separate slots for chat provider and receipt-parsing provider, per-provider API key vault, connection test, model override, custom base URL for OpenAI-compatible endpoints

Architecture

Feature-module layout with shared core/ for data, AI, OCR, workers, and helpers. Each feature owns its Fragment + ViewModel + adapters; ExpenseTrackingApplication is the manual dependency-injection root (no Hilt/Koin).

mobile.com.expense_tracking_app/
├── ExpenseTrackingApplication.kt   # Repository graph + WorkManager bootstrap
├── MainActivity.kt                 # Bottom-nav host + FAB routing
├── core/
│   ├── data/
│   │   ├── AppDatabase.kt          # Room v4, destructive migration, category seed
│   │   ├── entities/               # Transaction, Category, BudgetLog, Subscription,
│   │   │                           # TransactionTemplate, Transfer, PaybackTransaction
│   │   ├── dao/                    # One DAO per entity
│   │   ├── repositories/           # Thin wrappers exposing Flow<...> APIs
│   │   ├── relations/              # Room @Relation projections
│   │   └── preferences/            # UserPreferences (DataStore-like wrapper)
│   ├── ai/
│   │   ├── AiRepository.kt         # Orchestrates provider, prompts, tool execution
│   │   ├── AiPreferences.kt        # Encrypted per-provider key vault
│   │   ├── LlmProviderRegistry.kt  # Registers + selects providers
│   │   ├── providers/              # OpenAI, Anthropic, Gemini, ML Kit, SSE client
│   │   ├── PromptTemplates.kt
│   │   ├── ProposedAction.kt       # Confirm-before-execute action payloads
│   │   ├── ToolExecutor.kt         # Applies confirmed actions to repositories
│   │   ├── AiContextBuilder.kt     # Snapshots spending context for prompts
│   │   └── RecommendationEngine.kt # Dashboard "AI Action" card
│   ├── ocr/
│   │   ├── MlKitOcrEngine.kt       # ML Kit text recognition
│   │   ├── LlmReceiptParser.kt     # OCR text → structured line items via LLM
│   │   └── ReceiptPrompt.kt
│   ├── workers/
│   │   ├── BudgetArchiveWorker.kt  # Rolls over budgets at month boundary
│   │   └── ExpenseAutoInsertWorker.kt # Posts due recurring expenses
│   ├── alarms/                     # Subscription reminders
│   ├── notifications/
│   ├── helpers/                    # Formatters, date utils, currency
│   ├── models/                     # UI-layer models
│   └── ui/                         # Reusable custom views (AmountQuickPickView, …)
├── feature_dashboard/
├── feature_expense/                # Add expense + transaction list + receipt review
├── feature_assistant/              # Chat UI
├── feature_budget/
├── feature_recurring/
├── feature_settings/               # Profile, categories, templates, AI config
├── feature_widget/                 # Quick-Add app widget
└── feature_lending/                # Hidden in v1.0 — see RELEASE.md §7

Tech stack

Layer Choice
Language Kotlin 2.1 + Coroutines + Flow
UI View Binding, Material Components, ConstraintLayout, RecyclerView
Navigation AndroidX Navigation 2.8 (single-Activity, bottom nav)
State ViewModel + LiveData
Persistence Room 2.8 (KSP) + EncryptedSharedPreferences
Background work WorkManager 2.10
Charts MPAndroidChart 3.1
OCR ML Kit Text Recognition
On-device LLM ML Kit GenAI (Prompt + Summarization, beta)
Cloud LLM OkHttp 4.12 + OkHttp-SSE, Kotlinx Serialization
Testing JUnit, Turbine, Room-testing, Work-testing, Espresso, ArchCoreTest

Dependencies are version-catalogued in gradle/libs.versions.toml.


Getting started

Prerequisites

  • Android Studio (Hedgehog or newer recommended)
  • JDK 17 (AGP 9 requires it)
  • Android SDK 36
  • A device or emulator running API 26+

Clone & open

git clone <repo-url>
cd ExpenseTrackingApp

Open the project in Android Studio and let Gradle sync.

Build & install a debug APK

./gradlew :app:installDebug

Or hit Run ▶ in Android Studio with a device connected.

Configure the AI assistant (optional)

The app runs without any AI key — the chat tab and receipt scanner simply show a "set up AI" prompt. To enable them:

  1. Launch the app → Settings → AI configuration.
  2. Pick a provider, paste an API key, optionally choose a model.
  3. (Cloud-only) Tap Test connection to verify.

To pre-seed a DeepSeek key for development, add to local.properties:

deepseekApiKey=sk-...

This is baked into BuildConfig.DEEPSEEK_API_KEY and migrated into the encrypted vault on first launch. Leave this blank for production builds — users supply their own keys.


Permissions

Declared in AndroidManifest.xml:

Permission Why
INTERNET Cloud LLM calls, OCR receipt parsing
ACCESS_NETWORK_STATE Pre-flight connectivity check for AI features
CAMERA Receipt photo capture (declared optional)
POST_NOTIFICATIONS Subscription due-date reminders
SCHEDULE_EXACT_ALARM Exact-time reminders for recurring expenses

The camera hardware feature is declared required="false" so the app installs on devices without one.


Database

Room v4, single expense_tracker_database file. The schema is not exported and uses fallbackToDestructiveMigration — pre-release a wipe is acceptable; for v1.1+ you'll want to switch to explicit migrations.

Entities:

  • Transaction — every logged expense (amount, category FK, note, date, receipt ref)
  • Category — name, icon, color, default monthly budget, temp-budget override
  • BudgetLog — historical per-month snapshots written by BudgetArchiveWorker
  • Subscription — recurring expense definitions
  • TransactionTemplate — Quick-Add chips shown in widget + add-expense sheet
  • Transfer + PaybackTransaction — lending/borrowing (feature hidden in v1.0)

A SeedCallback inserts six default categories with zero budgets on first launch.


Testing

./gradlew test                    # JVM unit tests
./gradlew connectedAndroidTest    # Instrumented tests (device/emulator required)

Instrumented tests live under app/src/androidTest and cover Room DAOs, repositories, WorkManager workers, and ViewModel flows (with Turbine).


Release builds

Production builds (signed App Bundle for Google Play) are documented in detail in RELEASE.md. Quick reference:

./gradlew :app:bundleRelease      # Play Store AAB
./gradlew :app:assembleRelease    # Sideloadable APK

R8 + resource shrinking are enabled for release. Keystore credentials are read from local.properties (gitignored). Without them, the release build still completes but produces an unsigned APK.


Roadmap

  • v1.0 (current) — Dashboard, Add Expense, Budget, Recurring, Assistant, Widget, Settings
  • v1.1+ — Re-enable the Lending/Transfer tab (code is preserved; see RELEASE.md §7)
  • Explicit Room migrations (drop fallbackToDestructiveMigration)
  • Multi-currency support (currently VND-only)
  • Schema export for migration testing

License

Not yet specified.

About

Expense Tracking App with AI-integration (your own API key)

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages