Skip to content

zankrut20/PoliteIgnore

Repository files navigation

PoliteIgnore 📵

Selective Mute for the Modern Era. Precisely schedule times to silently ignore calls from specific contacts without blocking them.

Kotlin Android Compose License


🚀 The Solution

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.

Light Mode

Dashboard Light Profile Light Group Profile Light

Dark Mode

Dashboard Dark Profile Dark Group Profile Dark


🛠 Tech Stack & Architecture

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

⚡ Engineering Highlights

1. The System Intercept (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.

2. The 5-Second Timeout & WorkManager Hack

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 1 query 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.

3. Cellular Scope

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.


🔒 Privacy & Permissions

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.

📥 Download & Install

Stable Release: Download the latest signed APK from the Releases page.


🏗 Build Locally

Prerequisites

  • Android Studio Ladybug (or newer)
  • JDK 17+

Steps

  1. Clone the repository:
    git clone https://github.com/zankrut20/PoliteIgnore.git
  2. Open in Android Studio and sync Gradle.
  3. Build the project:
    ./gradlew assembleDebug

🧪 Testing Guide

Since this app relies on incoming cellular calls, testing on an emulator requires simulating the GSM modem.

Via Android Emulator:

  1. Open the Extended Controls window (three dots ... in the toolbar).
  2. Go to Phone.
  3. Enter a phone number (e.g., +15551234567) that matches a silenced profile in the app.
  4. Click Call Device.

Via ADB Terminal:

adb emu gsm call +15551234567

To end the call:

adb emu gsm cancel +15551234567

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages