An Android application that automatically tracks your expenses by reading banking app notifications. The app uses advanced regex patterns to extract transaction details and stores them locally with privacy-first approach.
- Notification Listener Service: Monitors notifications from banking apps in real-time
- Smart Detection: Only processes notifications from known banking applications
- Transaction Filtering: Identifies transaction-related notifications using keyword matching
-
Card Number Recognition: Extracts card numbers in various formats:
- Last 4 digits:
xxxx 1234,****1234,XX1234 - Full masked cards:
XXXX XXXX XXXX 1234 - Text-based:
Card ending 1234 - Account formats:
A/c XX1234
- Last 4 digits:
-
Multi-Currency Amount Detection: Supports multiple currency formats:
- USD:
$123.45,USD 123.45 - INR:
₹123.45,Rs.123.45,INR 123.45 - EUR:
€123.45,EUR 123.45 - GBP:
£123.45,GBP 123.45 - Generic amounts with commas:
1,234.56
- USD:
- Room Database: Efficient local storage with reactive queries
- Transaction Repository: Clean architecture pattern for data access
- Privacy-Focused: All data stored locally, no external transmission
-
Transactions Screen:
- List of all transactions with card number, amount, and timestamp
- Summary card showing total expenses
- Search functionality
- Category filtering chips
-
Transaction Management:
- Manual categorization of transactions
- Predefined categories (Food, Shopping, Transportation, etc.)
- Custom category creation
- Transaction deletion
-
Settings Screen:
- Permission status indicator
- Easy access to notification settings
- Privacy information
- Setup instructions
- Default Category: All transactions start as "Uncategorized"
- Predefined Categories:
- Food & Dining
- Shopping
- Transportation
- Bills & Utilities
- Entertainment
- Healthcare
- Travel
- Education
- Groceries
- Others
- Custom Categories: Users can create their own categories
The app follows MVVM (Model-View-ViewModel) architecture with clean separation of concerns:
app/
├── data/ # Data layer
│ ├── Transaction.kt # Entity model
│ ├── TransactionDao.kt # Database access
│ ├── TransactionDatabase.kt # Room database
│ └── TransactionRepository.kt # Data repository
├── service/
│ └── BankNotificationListenerService.kt # Notification listener
├── utils/
│ ├── NotificationParser.kt # Regex parsing logic
│ └── PermissionUtils.kt # Permission helpers
├── viewmodel/
│ └── TransactionViewModel.kt # ViewModel for UI
├── ui/
│ ├── screens/
│ │ ├── TransactionsScreen.kt # Main screen
│ │ └── SettingsScreen.kt # Settings screen
│ └── theme/ # App theming
├── navigation/
│ ├── Screen.kt # Route definitions
│ └── AppNavigation.kt # Navigation graph
└── MainActivity.kt # Entry point
- Android Studio (latest version)
- Android device/emulator running Android 10 (API 29) or higher
- Kotlin 2.0+
# Clone the repository
git clone <repository-url>
# Open in Android Studio
# File > Open > Select project directory
# Sync Gradle
# File > Sync Project with Gradle Files
# Build and Run
# Run > Run 'app'The app REQUIRES notification access to function. Follow these steps:
- Install and launch the app
- Navigate to Settings screen (gear icon)
- Click "Enable Notification Access" button
- You'll be taken to system settings
- Find "Expense Tracker" in the list
- Toggle the switch to enable
- Accept the warning prompt
- Return to the app
Alternative manual path:
Settings > Apps > Special app access > Notification access > Expense Tracker > Enable
The app currently recognizes notifications from:
Indian Banks:
- SBI (State Bank of India)
- ICICI Bank
- HDFC Bank
- Axis Bank
- Kotak Mahindra Bank
- Yes Bank
- Paytm
- PhonePe
- Google Pay
International Banks:
- Chase
- Bank of America
- Wells Fargo
- Citibank
- PayPal
- Venmo
- Cash App
To add more banks, edit BankNotificationListenerService.kt:
private val bankingApps = setOf(
"com.yourbank.package", // Add package name here
// ... existing entries
)# Pattern 1: Masked card with last 4 digits
(?:x{4}|X{4}|\*{4})\s?(?:x{4}|X{4}|\*{4})?\s?(?:x{4}|X{4}|\*{4})?\s?(\d{4})
# Pattern 2: Card ending text format
(?:card|Card|CARD)\s+(?:ending|Ending|ENDING)\s+(?:in\s+)?(\d{4})
# Pattern 3: Account number format
(?:A/c|a/c|Account)\s+(?:x{2}|X{2}|\*{2})?(\d{4})# USD format
(?:USD|US\$|\$)\s?([0-9,]+\.?\d{0,2})
# INR format
(?:INR|Rs\.?|₹)\s?([0-9,]+\.?\d{0,2})
# Generic amount after keywords
(?:amount|Amount|AMOUNT|of|charged|debited|spent)\s+(?:Rs\.?|₹|\$|€|£)?\s?([0-9,]+\.?\d{0,2})- Enable notification access for the app
- Make a test transaction using your bank card
- When you receive the transaction notification, the app will automatically:
- Extract the transaction details
- Save to local database
- Display in the transactions list
For development/testing without real transactions, you can insert test data:
// In TransactionViewModel or a test screen
viewModel.insertTransaction(
Transaction(
cardNumber = "****1234",
amount = 99.99,
currency = "$",
category = "Uncategorized",
timestamp = System.currentTimeMillis(),
rawText = "Test transaction",
bankApp = "com.test.bank"
)
)The app includes validation for:
- ✅ Valid card number formats
- ✅ Positive transaction amounts
- ✅ Proper currency detection
- ✅ Transaction vs non-transaction notifications
- ✅ Multiple banking app formats
- Local-Only Storage: All data is stored in a local Room database
- No Network Transmission: Zero external API calls or data sharing
- Minimal Permissions: Only requests notification access
- User Control: Users can disable access anytime via system settings
- Card Masking: Card numbers are automatically masked
- Users are informed about data collection
- Data is stored locally, not transmitted
- Users can delete individual transactions or all data
- Clear privacy policy in settings
- Data persists until manually deleted by user
- No automatic data expiration
- User can clear all data by uninstalling the app
The app includes comprehensive error handling:
// Notification parsing errors
try {
val transaction = NotificationParser.parseNotification(text, packageName)
if (transaction != null) {
repository.insertTransaction(transaction)
} else {
Log.d(TAG, "Failed to parse notification")
}
} catch (e: Exception) {
Log.e(TAG, "Error processing notification", e)
}Issue: Transactions not appearing
- Solution: Ensure notification access is enabled in system settings
- Check: Settings > Notification Access > Verify app is enabled
Issue: Incorrect amount or card number
- Solution: Check notification format, may need to add new regex pattern
- Action: Report the notification format for pattern improvement
Issue: Wrong banking app detected
- Solution: Add the correct package name to
bankingAppsset
// Room Database
implementation("androidx.room:room-runtime:2.6.0")
implementation("androidx.room:room-ktx:2.6.0")
ksp("androidx.room:room-compiler:2.6.0")
// Navigation
implementation("androidx.navigation:navigation-compose:2.7.5")
// DataStore (for future preferences)
implementation("androidx.datastore:datastore-preferences:1.0.0")
// Compose
implementation(platform("androidx.compose:compose-bom:2024.09.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.ui:ui-tooling-preview")
// Lifecycle
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")- Export transactions to CSV/Excel
- Budget tracking and alerts
- Spending analytics and charts
- Recurring transaction detection
- Multi-card management
- Dark theme support
- Widget for quick expense view
- Backup and restore functionality
- OCR for receipt scanning
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new patterns/features
- Submit a pull request
This project is open source. Please ensure compliance with data privacy regulations when using or modifying.
For issues, feature requests, or questions:
- Open an issue on GitHub
- Check existing documentation
- Review regex patterns in
NotificationParser.kt
- Built with Jetpack Compose
- Uses Room for local database
- Follows Material Design 3 guidelines
- Implements Android best practices for notification listeners
Note: This app is for personal expense tracking. Always review and verify tracked transactions for accuracy. The app does not access your bank account directly, only reads notifications.