MyFriends - Emergency SOS & Contact Management App
Flutter SOS app that sends real-time location to trusted contacts and keeps alerting through Do Not Disturb, Doze mode and a killed app via a three-layer notification system.
Role
Full Stack Mobile Developer
Client
Academic Project - Mobile Programming Course
Team
3-person Team
Timeline
2 months • 2025

Problem
An emergency alert is useless if the recipient's phone is silenced, asleep in battery saver, or has the app closed, which is exactly when standard push notifications fail.
Solution
Combined a foreground alarm timer, an FCM background isolate, and 60 OS-scheduled exact alarms, with cancellation that tears down all three layers at once.
Impact
Alerts delivered in every tested phone state, location attached in 2-4 seconds outdoors, and contact photos compressed about 98% before upload.
Skills & Tools
Skills Applied
Tools & Software
Final Results








Project Overview
MyFriends is an emergency SOS mobile app (Flutter + Firebase) that instantly alerts trusted contacts with the user's real-time location. Its defining feature is a multi-layered notification system that guarantees loud, persistent alerts even when the recipient's phone is on Do Not Disturb, in battery-saver mode, or has the app fully terminated.
Three-Layer Notification System
Delivering emergency alerts across every phone state required three independent mechanisms:
- Foreground timer —
Timer.periodicfires an alarm-stream notification every 3s while the app is active. It usesAudioAttributesUsage.alarmto bypass Do Not Disturb, an ongoing (non-dismissible) notification, and a custom vibration pattern. - Background isolate — a top-level handler annotated
@pragma('vm:entry-point')that FCM wakes even when the app is terminated. It re-initializes Firebase in a fresh isolate and, crucially, inspects the message type first so asos_cancelledpayload stops alerts instead of spawning new ones. - Scheduled exact-time alarms — the guaranteed fallback. On SOS trigger, 60 notifications are pre-scheduled 3s apart (3 minutes total) via
AndroidScheduleMode.exactAllowWhileIdle, which wakes the device from Doze mode. Registered with the OS itself, these fire even if the app process is killed or the network drops.
Cancellation must tear down all three layers: update Firestore status, push an FCM sos_cancelled notice, cancel the foreground and background timers, cancel all 60 scheduled IDs (100000–100060), and clear the main notification (ID 99999).
State Management
The app uses Provider with ProxyProvider: AuthProvider is independent, while the Contact, Group, and SOS providers receive the current user ID automatically whenever auth state changes. This propagates user context cleanly, prevents null-reference errors and cross-user data leakage, and makes logout trivial (user ID becomes null and all providers clear).
Real-Time Location
A four-step flow acquires the best possible fix before sending: service check, permission handling (denied / denied-forever / granted), high-accuracy GPS request (10s timeout), then Google Maps deep-link generation. Real-world accuracy ranges from 8–12m outdoors (2–4s) to 30–50m deep indoors. The 10s timeout favors urgency — a rough network fix beats waiting indefinitely for a perfect GPS lock.
Emergency Contact Matching
Contacts are saved with an email, and SOS matching queries the Firestore users collection by email to resolve Firebase user IDs and FCM tokens (excluding the sender). Email is used instead of phone number because it is Firebase Auth's canonical identifier, has no format ambiguity, and stays stable across device and number changes. Limitation: contacts must also be registered app users.
Slide-to-Send Widget
To prevent accidental triggers while staying accessible in a crisis, activation uses a custom slide gesture requiring an 80% drag threshold — with a pulsing idle animation, an intensifying gradient, snap-back if released early, and haptic confirmation on success.
Photo Optimization
Contact photos are compressed client-side before upload — resized to 512x512 and JPEG-encoded at 75% quality, turning an 8MB original into roughly 100KB (about 98% reduction) — then stored under user-scoped Firebase Storage paths with the download URL referenced in Firestore.
Testing Results
| Scenario | Result | Notes |
|---|---|---|
| App foreground | Pass | Layer 1 + 3 |
| App background | Pass | Layer 3 guaranteed |
| App terminated | Pass | Layer 2 + 3 |
| Do Not Disturb | Pass | Alarm stream bypasses |
| Phone locked | Pass | Full-screen intent |
| Battery saver | Pass | exactAllowWhileIdle |
| Network offline | Partial | Scheduled alarms continue |
Key Takeaways
- Android battery optimization makes exact alarms the only reliable guarantee of background delivery.
- Full state coverage (foreground, background, terminated) needs separate, redundant mechanisms.
AudioAttributesUsage.alarmis what lets emergency alerts bypass Do Not Disturb.- ProxyProvider keeps a multi-provider app safe from null errors when auth state changes.
- Always compress images before upload; email is a more stable cross-device identifier than phone number.
Repository: MyFriends App · Stack: Flutter 3.27, Firebase (Auth, Firestore, Storage, FCM), Provider, Geolocator · Course: Mobile Programming, Hasanuddin University, 2025
Project Metrics
3-layer notification system: foreground timer + background isolate + 60 scheduled exact-time alarms
100% notification delivery success rate (bypasses Do Not Disturb mode)
Real-time GPS location sharing with Google Maps integration
Email-based emergency contact matching across Firebase users
Real-time Firestore streams for contacts, groups, and SOS messages
Custom slide-to-send widget with 80% threshold gesture detection
Image compression (512x512, 75% quality) before Firebase Storage upload
CSV export with system share dialog integration
Project Tags
Related Projects
View all projects →Cirebon Kuring Cafe
Next.js 15 · React 19 · TypeScript
Cirebon Kuring Cafe - Cafe Management System
Cafe operating system spanning 4 apps on one Supabase backend: QR table ordering, a Flutter staff tablet for 4 roles, an employee portal, and an owner dashboard, backed by 69 migrations and 15+ edge functions.

Urban Complaint Pattern Mining on NYC 311 Data (21M+ Records)
Data mining of 21.3M NYC 311 requests that found a six-complaint building 'syndrome' (mean lift 8.48) and validated it against 11M inspection records: 12-44x higher violation rates.
ICONNET Finance Dashboard
Next.js 16 · React 19 · TypeScript
ICONNET Finance Dashboard - OPEX, Cash Advance & Contract Monitoring
Internal finance dashboard for PLN Icon Plus that replaced spreadsheet-based reporting with four modules (OPEX monitoring, cash-advance tracking, outsourced-staff contract budgets, and vehicle monitoring) on a Next.js + Express + PostgreSQL stack, hardened after a full penetration test.
