Selective Mute for the Modern Era. Precisely schedule times to silently ignore calls from specific contacts without blocking them.
Standard "Do Not Disturb" is a blunt instrument—it silences everyone. Third-party call blockers are aggressive, often hanging up on the caller and sending them straight to voicemail, which can be socially awkward.
PoliteIgnore acts as a Selective Mute. It allows you to schedule specific time windows (e.g., "M-F, 9 AM - 5 PM") during which calls from specific contacts will effectively be ignored.
- Zero Ringtone.
- Zero Vibration.
- Zero Rejection. The caller hears the standard ringing tone until voicemail picks up, unaware they are being silenced.
- System Integration: Leveraging the native Telecom API, the screen lights up to show the call, but your phone remains completely silent.
This project is built with modern, idiomatic Android practices, focusing on performance, clean architecture, and standard Material Design 3 guidelines.
- Language: Kotlin
2.0.21(Mobile Native) - Build System: Gradle Kotlin DSL (AGP
8.7.2) - UI Framework: Jetpack Compose (Material 3 with Dynamic Colors & Dark Mode)
- Architecture: MVVM (Model-View-ViewModel) with Unidirectional Data Flow
- Dependency Injection: Dagger Hilt
2.51.1 - Local Persistence: Room Database
2.6.1(SQLite abstraction) - Asynchronous Processing: Kotlin Coroutines & Flow
- Background Processing: WorkManager
2.9.0(with Hilt integration) - Core Telecom API:
CallScreeningService
Unlike legacy apps that relied on flaky broadcast receivers, PoliteIgnore implements the CallScreeningService API introduced in Android 10. This allows the app to intercept the incoming call state before the Android OS triggers the ringtone or vibration motor. By returning a CallResponse with setSilenceCall(true), we effectively mute the call at the system level while keeping the line open.
The Android System enforces a strict ~5-second timeout for CallScreeningService.onScreenCall(). If the app fails to respond within this window, the system default behavior (ringing) takes over.
Running a cold query against a Room Database on disk can sometimes exceed this limit, especially on older devices or after the app process has been killed.
Solution: We implemented a Database Warm-up Strategy using WorkManager.
- A background worker (
DatabaseWarmupWorker) runs every 12 hours. - It executes a lightweight
SELECT 1query to force SQLite to initialize and populate its page cache in RAM. - This ensures that when a real call comes in, the database read is virtually instant (sub-millisecond), guaranteeing we never miss the 5-second deadline.
Per Android's security design, CallScreeningService only intercepts Cellular/SIM calls. VoIP calls from third-party applications like WhatsApp, Telegram, or Signal use their own network stacks and bypass this system API entirely. This limitation is by design and cannot be overridden by third-party apps.
PoliteIgnore is designed with a "Privacy First" philosophy.
- Role:
ROLE_CALL_SCREENING- Required to intercept calls. - Permission:
READ_CONTACTS- Required to select numbers from your address book. - Offline On-Device: Zero network calls. No analytics. No tracking. User data never leaves the device's secure storage.
Stable Release: Download the latest signed APK from the Releases page.
- Android Studio Ladybug (or newer)
- JDK 17+
- Clone the repository:
git clone https://github.com/zankrut20/PoliteIgnore.git
- Open in Android Studio and sync Gradle.
- Build the project:
./gradlew assembleDebug
Since this app relies on incoming cellular calls, testing on an emulator requires simulating the GSM modem.
Via Android Emulator:
- Open the Extended Controls window (three dots
...in the toolbar). - Go to Phone.
- Enter a phone number (e.g.,
+15551234567) that matches a silenced profile in the app. - Click Call Device.
Via ADB Terminal:
adb emu gsm call +15551234567To end the call:
adb emu gsm cancel +15551234567




