A privacy-focused, offline-first Android application built with Flutter and Native Kotlin designed to secure your sleep from unwanted calls and messages while ensuring that actual emergencies can still get through.
No servers, no cloud APIs, no network access, and zero data tracking. 100% private.
Modern smartphones have "Do Not Disturb" (DND) modes, but they present several critical issues:
- Too Rigid / No Auto-Reply: When you activate standard DND, callers hear your phone ring out or get blocked entirely. They have no idea you are sleeping, nor do they know how to reach you if there's a genuine emergency.
- Media Stream Muting: Many default silence utilities mute the global audio system. If you want to fall asleep listening to a podcast or white noise (
STREAM_MUSIC), you shouldn't have to mute it just to silence incoming call ringtones (STREAM_RING). - Device Incompatibilities: Advanced modern features like Android's
CallScreeningServiceare heavily vendor-dependent (mostly Google Pixel) and carrier-dependent, meaning they fail to work on a wide variety of Android devices. - Bypass Spam: Anyone can repeatedly call or send messages to bypass basic DND. We need a way to filter bypass requests so that only trusted, pre-approved contacts can override the silence, and only when they've received instructions.
We built Sleep Protection to solve these specific challenges with a robust, hybrid architecture:
Instead of muting the entire system, the app isolates Android audio streams. It leaves STREAM_MUSIC (music, white noise, video playback) fully untouched. Only the ringtone (STREAM_RING) is silenced using Android's priority interruption filter (INTERRUPTION_FILTER_PRIORITY). You can sleep to your favorite tunes while calls remain dead silent.
Rather than relying on fragile Call Screening APIs, we use native NotificationManager DND settings coupled with an SMS Broadcast Receiver. This combination works reliably on practically all Android devices from Android 5.0 up to the latest versions.
To prevent random number spam and manual bypasses by strangers:
- The app intercepts incoming SMS messages during sleep hours.
- If a contact is not whitelisted, they are silently ignored (no auto-reply).
- If they are in your Whitelist (Trusted list), the app sends an automated SMS response explaining that you are sleeping and giving them a special bypass instruction: Reply "EMERGENCY" to override.
- If the whitelisted contact replies with "EMERGENCY" within 1 hour of receiving that auto-reply, the app temporarily restores the ringer for 2 minutes so their next call/message rings at full volume.
You don't need to open the app every night. We implemented an Android TileService that places a custom Sleep Protection toggle directly in your Quick Settings panel (notification shade drawer) for instant activation/deactivation.
The app uses a hybrid architecture, combining the cross-platform rendering capabilities of Flutter for the frontend UI with highly optimized Android background services written in native Kotlin.
Flutter UI (Dart)
│
└── MethodChannel ("com.sleepapp.anel/bridge")
│
▼
┌───────────────────────────────────────┐
│ MainActivity.kt │
│ - Flutter ↔ native bridge │
│ - Service lifecycle management │
└───────────────────────────────────────┘
│
┌───────────────────────┼───────────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│SleepDnd │ │SMSInterceptor│ │SleepProtect │
│Service.kt │ │Receiver.kt │ │TileService.kt│
│(DND control) │ │(SMS receiver)│ │(QS Tile) │
└──────────────┘ └──────────────┘ └──────────────┘
│ │
└───────────┬───────────┘
▼
┌──────────────────────────────────────────────┐
│ SettingsManager.kt (SharedPreferences JSON) │
│ SmsHelper.kt (SMS dispatcher) │
│ RingerHelper.kt (Audio mode switcher) │
│ InteractionLog.kt (Event database) │
└──────────────────────────────────────────────┘
SleepDndService: A foreground Android service running withSTART_STICKY. It maintains the active sleep protection state even under heavy system memory pressure and displays a low-priority notification to satisfy Android background requirements.SMSInterceptorReceiver: A high-priority broadcast receiver (priority = 2147483647) that captures incoming SMS messages to determine if they should be auto-replied or trigger an emergency bypass.SleepProtectionTileService: Integrates with the system status bar, keeping the tile state perfectly synced with the app's internal shared settings.SettingsManager: Manages app state and trusted contacts. It uses a secure JSON serialization structure instead of brittle delimiter strings to ensure telephone numbers with special characters don't break the list parsing.BootCompletedReceiver: Listens for device restarts to automatically reboot the background protection service if it was running prior to shutdown.
- Protection Switch: Quick global toggle in the app.
- Time Schedule: Configure start/end sleep hours.
- Quick Settings Tile: Toggle sleep protection directly from the Android status bar.
- Trusted Whitelist: Manage a secure list of contacts allowed to trigger bypasses.
- SMS Intercept + Auto-Reply: Automatic response to whitelisted contacts during sleep hours.
- Strict EMERGENCY Override: 2-minute ringer restoration window triggered by whitelisted contacts replying "EMERGENCY".
- Audio Stream Separation: Silence calls/notifications without affecting music playback or system alarms.
- System Log History: View a local timeline of calls silenced, auto-replies sent, and bypasses activated.
- Boot Persistence: Service automatically restarts after a device reboot.
- DND and Battery Optimization Checkers: In-app guidance to ensure permissions are configured correctly.
To operate as a robust offline system utility, the app requires:
RECEIVE_SMS&SEND_SMS: To intercept incoming texts and send automated emergency instructions.READ_PHONE_STATE: To detect incoming calls and check ringer statuses.MODIFY_AUDIO_SETTINGS: To restore and silence the audio ringer programmatically.POST_NOTIFICATIONS: To keep the background service active via a foreground notification.FOREGROUND_SERVICE&FOREGROUND_SERVICE_SPECIAL_USE: For uninterrupted background execution.RECEIVE_BOOT_COMPLETED: To ensure protection persists across device reboots.ACCESS_NOTIFICATION_POLICY: To toggle Android's "Do Not Disturb" system status.
- Flutter SDK (v3.x+)
- Android SDK (API level 21+)
- Android device (for testing permissions and services)
# 1. Navigate to the flutter project directory
cd sleep_protection_flutter
# 2. Get dependencies
flutter pub get
# 3. Build debug APK
flutter build apk --debugThe compiled APK will be located at:
build/app/outputs/flutter-apk/app-debug.apk
adb install build/app/outputs/flutter-apk/app-debug.apkWhen testing changes or deploying for the first time, verify using the following checklist:
- Service Toggle: Switch protection ON in the app. Confirm the foreground service starts and the "Sleep Protection Active" notification appears.
- Quick Settings Tile: Add the tile to your quick settings. Tap to toggle; confirm the tile state ("Active"/"Inactive") and the app's switch state stay in perfect lockstep.
- SMS Interception:
- Send an SMS from a non-whitelisted number during sleep hours. Confirm no auto-reply is sent.
- Add a test number to the Whitelist. Send an SMS from this test number during sleep hours. Confirm an auto-reply containing the bypass instructions is sent.
- Emergency Bypass:
- From the whitelisted test number, send "EMERGENCY" within 1 hour of receiving the auto-reply.
- Confirm a system notification alerts you that the ringer has been restored for 2 minutes.
- Call the device; confirm it rings aloud.
- Reboot Persistence: Enable protection, restart the phone, and verify that the foreground service starts back up automatically once the device boots.