My parent lives alone. After a fall that nobody noticed for hours, I decided to build something that would.
Four months, 121 versions, and approximately 79,000 lines of Kotlin later, the app is live on Google Play. Here is the story — the technical challenges, the things that broke, and what I would do differently.
What the app does
Install it on your parent's Android phone. It watches. That is it.
For 7 days, it learns their routine — when they wake up, how active they are, where they go. After that, it monitors 24/7 and emails your family if something seems wrong:
- Unusual stillness (potential fall or medical event)
- Did not wake up on time
- At an unfamiliar location at an unusual hour
- Phone silent for too long
No buttons to press. No wearable to charge. No daily check-in calls. Install and forget.
The technical stack
- Kotlin + Jetpack Compose + Material Design 3
- Room + SQLCipher for encrypted local storage
- Google Gemini API for behavioral analysis (cloud, anonymized summaries)
- Resend API for transactional email alerts
- WorkManager + Foreground Service for 24/7 reliability
- Clean architecture:
:domain(pure Kotlin) ->:data->:ui->:app
## The hard part: staying alive on Android
This is where 80% of my development time went.
Android's job is to kill your app. OEMs make it worse. Here is what I learned:
### Problem 1: OEM battery killers
Samsung, Xiaomi, Honor, OPPO — they all have proprietary battery managers that kill background apps. The standard startForeground() is not enough.
My solution: 11-layer service recovery:
- Foreground service with IMPORTANCE_MIN channel
- WorkManager periodic watchdog
- AlarmManager backup chains
- BOOT_COMPLETED receiver
- SyncAdapter for process priority boost
- Batched accelerometer sensing (survives CPU sleep)
- Exact alarm permission recovery
- OEM-specific wakelock tag spoofing (Honor whitelists "LocationManagerService")
- START_STICKY restart
- Safety net AlarmClock at 8-hour intervals
- User-facing gap detection with OEM-specific guidance
Each layer was added because the previous ones were not enough on some device.
Problem 2: Sensor data lies to you
At 3 AM, your app wakes up to check the accelerometer. The sensor HAL returns data. You think it is fresh. It is not — it is 22-minute-old data sitting in the hardware FIFO buffer since the last time anyone read the sensor.
On Honor devices, the HAL even rebases event.timestamp on flush, so a delta check against elapsedRealtimeNanos() thinks the data is fresh. The solution: explicit sensorManager.flush(), discard warm-up readings, use onFlushCompleted() callback instead of fixed timers, and dual-clock comparison as a safety net.
### Problem 3: GPS does not work when you need it
getCurrentLocation(PRIORITY_HIGH_ACCURACY) returns nothing. The OEM killed the GPS hardware to save power.
Solution: Priority fallback chain — HIGH_ACCURACY -> wake probe -> BALANCED_POWER -> LOW_POWER -> getLastLocation(). Returns a GpsLocationOutcome sealed class so the caller knows exactly what happened.
## The AI: from on-device to cloud
I started with Gemini Nano (fully on-device). It worked on Pixels. It did not work on anything else. The addressable market was tiny.
So I moved to Gemini Flash (cloud API). The privacy trade-off: detailed behavioral data stays on-device in an encrypted database, but anonymized summaries (including location context) are sent to Google's AI for weekly analysis. No names, no personal identifiers.
The key architectural decision: API key sharding. Each Google Cloud project gets 10,000 requests per day free. I created 6 projects with independent API keys. The app rotates through them on rate-limit errors (429/403). That is 60,000 requests per day — enough for thousands of users at zero cost.
## Travel intelligence
The biggest UX win. Without it, every vacation generated 5 to 7 URGENT emails (one per night when the hard-floor detector fired at an unfamiliar location). By day 5, families ignored all emails.
Now: Day 1 sends one "your parent appears to be traveling" notification. Days 2 through 6: silence (unless something actually changes). Return home: "they have returned to a familiar area."
The state machine: HOME -> DAY_1 -> TRAVELING(n) -> TRIP_ENDED. Single-writer rule through TravelStateManager to prevent state corruption from concurrent assessments.
## What I would do differently
- Start with cloud AI from Day 1. I lost 2 months on Gemini Nano before accepting the device compatibility reality.
- Build the OEM compatibility layer first. The 11-layer recovery took 40+ versions to get right. It should have been the foundation, not an afterthought.
- Email before OAuth. I started with Gmail OAuth (user signs into their Google account). It was a UX nightmare. Resend API (transactional email, zero auth) took 1 day to implement and just works.
## Looking for early adopters
The app is free to download with a 21-day free trial (then $49 for the first year, $5 per year after that). I am looking for families to test it — install it on your parent's Android phone (Android 9 or newer), run it for a couple of weeks, and tell me what works and what does not.
If you have an elderly parent who lives alone and you worry about them:
- Join the early adopter group: https://groups.google.com/g/howareu-early-adopters
- Become a tester: https://play.google.com/apps/testing/com.howareyou
- Download: https://play.google.com/store/apps/details?id=com.howareyou
Website: howareu.app
Top comments (0)