A location-based voice reminder Android app built with Kotlin and Jetpack Compose. Set reminders tied to specific locations — when you arrive, LetMeKnow speaks your reminder out loud using Sarvam AI's Bulbul TTS engine.
Built for the Sarvam AI "Build with Bulbul" competition.
- Long-press anywhere on Google Maps to set a reminder location
- Adjustable geofence radius (3m – 50m)
- Real-time visualization of reminder zones on the map
- Automatic triggering when you enter the geofence area
- Text-to-Speech powered by Sarvam AI's Bulbul v3 model
- Supports 11 Indian languages: English, Hindi, Bengali, Tamil, Telugu, Gujarati, Kannada, Malayalam, Marathi, Punjabi, and Odia
- Automatic text translation for non-English languages before TTS synthesis
- Audio caching per reminder for instant playback on trigger
- Optionally set a date and time for your reminder
- The app monitors your location in the background and triggers the reminder only when you're at the location AND the scheduled time arrives
- Reminders expire automatically if not triggered within 15 minutes of the scheduled time
- Foreground service with persistent notification for reliable geofence monitoring
- Periodic schedule checker (every 30 seconds) for time-based reminders
- Automatic restart on device boot — your reminders survive reboots
- Vibration + voice alert when a reminder triggers
- View all active reminders on the map (green zones) and in a list
- Edit or delete reminders with swipe-to-delete
- Status tracking: Pending → Active → Triggered / Expired
- Error feedback for TTS/network failures shown directly on reminder cards
- Logs screen to review triggered and expired reminder history
Coming soon
MVVM + Clean Architecture
├── data/ # Room DB, Sarvam API, Repository implementations
├── domain/ # Reminder entity, Language enum, ReminderStatus
├── presentation/ # Compose UI, ViewModels, Navigation
├── geofence/ # GeofenceManager, BroadcastReceiver, TransitionHandler
├── service/ # LocationForegroundService
├── audio/ # TtsAudioPlayer, VibrationHelper
├── di/ # Hilt dependency injection modules
├── receiver/ # BootCompletedReceiver
└── util/ # Constants, DateTimeUtil
Key patterns:
- Hilt for dependency injection (with KSP)
- Room for local persistence
- Retrofit + OkHttp for Sarvam API calls
- StateFlow for reactive UI updates
- Coroutines with SupervisorJob for background work
- Mutex-based concurrency control for geofence transitions
| Component | Technology |
|---|---|
| Language | Kotlin 2.0.21 |
| UI | Jetpack Compose (Material3) |
| DI | Hilt 2.53.1 |
| Database | Room 2.6.1 |
| Networking | Retrofit 2.11.0 + OkHttp 4.12.0 |
| Maps | Google Maps SDK + Maps Compose 6.2.1 |
| Location | Google Play Services Location 21.3.0 |
| TTS | Sarvam AI Bulbul v3 API |
| Min SDK | 26 (Android 8.0) |
| Target SDK | 35 |
- Android Studio (Ladybug or newer recommended)
- Android SDK 35
- A Google Maps API key (get one here)
- A Sarvam AI API key (get one here)
-
Clone the repository
git clone https://github.com/patel/letmeknow.git cd letmeknow -
Add your API keys
Create or edit
local.propertiesin the project root:sdk.dir=/path/to/your/Android/Sdk MAPS_API_KEY=your_google_maps_api_key SARVAM_API_KEY=your_sarvam_ai_api_key
-
Build and run
./gradlew assembleDebug
Or open the project in Android Studio and run on a device/emulator.
Note: A physical device is recommended for testing geofencing and location features. Emulators can simulate location but geofence behavior may be unreliable.
The app requests the following permissions at runtime:
| Permission | Purpose |
|---|---|
| Fine Location | Precise geofencing and map interaction |
| Background Location | Monitor geofences when app is in background |
| Notifications | Foreground service notification |
| Vibrate | Vibration alert on reminder trigger |
| Internet | Sarvam AI API calls and Google Maps |
| Boot Completed | Restart monitoring after device reboot |
- Open the app — the map centers on your location
- Long-press on the map to select a location
- Adjust the radius using the slider (3m – 50m)
- Tap Set Reminder to open the creation sheet
- Enter your reminder message
- Select a language (defaults to English)
- Optionally toggle Schedule and pick a date/time
- Tap Save
Immediate reminders (no schedule):
- A geofence is registered at the location
- When you physically enter the zone, the reminder triggers immediately
- You hear a vibration followed by the voice message
Scheduled reminders:
- When you enter the geofence zone before the scheduled time, the reminder is marked Active
- A background checker monitors the clock every 30 seconds
- When the scheduled time arrives and you're in the zone, it triggers
- If you don't arrive within 15 minutes of the scheduled time, the reminder expires
PENDING ──→ ACTIVE ──→ TRIGGERED
│ │
│ └──→ EXPIRED (15 min past schedule)
└──→ EXPIRED
- Pending: Created, geofence registered, waiting for entry
- Active: User entered the zone, waiting for scheduled time
- Triggered: Voice played, moved to logs
- Expired: Scheduled time passed without trigger
- View reminders: Tap the list icon on the map screen
- Edit: Tap a reminder card in the list (for scheduled reminders)
- Delete: Swipe right on a reminder card
- View logs: Tap "View Logs" in the reminder list to see triggered/expired history
| Language | Code |
|---|---|
| English | en-IN |
| Hindi | hi-IN |
| Bengali | bn-IN |
| Tamil | ta-IN |
| Telugu | te-IN |
| Gujarati | gu-IN |
| Kannada | kn-IN |
| Malayalam | ml-IN |
| Marathi | mr-IN |
| Punjabi | pa-IN |
| Odia | od-IN |
Non-English messages are automatically translated to the target language before TTS synthesis.
# Debug build
./gradlew assembleDebug
# Release build (requires signing config)
./gradlew assembleReleaseThis project is part of the Sarvam AI "Build with Bulbul" competition.