A production-oriented Android call-filtering application that helps users control incoming calls with flexible blocker and permission rules. Smart Blocker combines real-time call handling, encrypted local storage, optional account synchronization, contact and call-log integration, and an extensive automated test suite.
- Block incoming calls that match user-defined rules.
- Explicitly permit selected calls even when another blocking rule also matches.
- Match a complete phone number, a number prefix, or a sequence found anywhere in the number.
- Optionally block calls with hidden numbers.
- Browse blocker and permission lists with search and filtering.
- Review calls handled by the application and the rule responsible for each result.
- Inspect system contacts and call history together with matching filter information.
- Create filters directly from phone numbers, contacts, or call details.
- Recognize, validate, and format international phone numbers.
- Store data locally or synchronize it for an authenticated account.
- Customize language and light/dark appearance.
Incoming call
↓
ForegroundCallService
↓
CallReceiver observes the phone state
↓
Normalize the incoming number
↓
Find the highest-priority matching rule
├── Blocker → reject the call
├── Permission → allow the call
└── No match → leave the call unchanged
↓
Record the filtered-call result
The foreground service registers a phone-state receiver while blocking is enabled. An incoming number is compared with locally stored filters. After the call finishes, the matching rule and call information are saved so the result can be shown in the application's history.
Every filter has two independent properties.
- Blocker rejects a matching incoming call.
- Permission allows a matching call and can override a broader blocking rule.
- Full number — matches one exact phone number.
- Begins with — matches a country code, area code, operator prefix, or any custom prefix.
- Contains — matches a sequence located anywhere in the incoming number.
This makes it possible to express both narrow rules for individual callers and wider rules covering number ranges.
- Blockers — blocking rules and their matching contacts and calls.
- Permissions — explicit allow rules.
- Calls — system and filtered-call history.
- Contacts — address-book entries with related filter information.
- Filter details — rule metadata, matching contacts, and matching calls.
- Settings — blocker state, hidden-number handling, account, language, theme, privacy, and feedback.
- Built-in help — linked explanations of filters, rule priority, calls, and contacts.
The project uses a layered architecture with clearly separated responsibilities:
presentation/
Fragments, ViewModels, adapters, dialogs, and UI models
↓
domain/
Entities, repository contracts, use cases, enums, and result types
↓
data/
Repository implementations, Room DAOs, DataStore, and Firebase access
↓
infrastructure/
Phone-state receiver, foreground service, constants, and platform integration
Dependency injection is provided by Hilt. ViewModels communicate with the UI through LiveData, while repositories use Kotlin coroutines and Flow for asynchronous data access.
Smart Blocker supports two operating modes:
- Local mode keeps filters, settings, and filtered-call history on the device.
- Account mode synchronizes supported user data through Firebase.
Local structured data is stored with Room and protected using SQLCipher. DataStore Preferences keeps lightweight application settings such as blocker state, hidden-number handling, theme, and language.
- Kotlin
- Android Views and Data Binding
- Android Navigation Component and Safe Args
- Hilt
- Kotlin Coroutines and Flow
- Room
- SQLCipher
- DataStore Preferences
- Firebase Authentication and Realtime Database
- Firebase Analytics, Crashlytics, and Performance Monitoring
- libphonenumber
- Glide
- Lottie
The repository contains unit and instrumented tests for repositories, use cases, ViewModels, navigation, filter creation, settings, dialogs, and primary UI flows.
Quality tooling includes:
- JUnit and Robolectric;
- Espresso and AndroidX Test;
- MockK;
- JaCoCo coverage reports;
- ktlint;
- Detekt;
- a dedicated
lint-checksmodule with a custom Android lint rule; - LeakCanary in debug builds.
Useful verification tasks:
./gradlew testDebugUnitTest
./gradlew connectedDebugAndroidTest
./gradlew jacocoTestReport
./gradlew ktlintCheck
./gradlew detekt
./gradlew lint- Android Studio with JDK 17
- Android SDK 34
- Android 10 or newer
- A device with telephony support for real call handling
- Permissions for phone state, call handling, call log, and contacts
Call-control behavior can differ between Android versions and device manufacturers because it depends on protected telephony APIs and system permissions.
The project expects environment-specific values for Firebase, authentication, analytics, advertising, signing, and other integrations. Keep these values outside version control.
Typical local configuration includes:
google-services.json;- Firebase Realtime Database URL;
- OAuth server client ID;
- application integration keys;
- release keystore path and credentials.
Do not commit production credentials, signing files, or private configuration values.
After providing the required local configuration:
git clone https://github.com/TarasovVP/SmartBlocker.git
cd SmartBlocker
./gradlew :app:assembleDebugThe generated debug APK can be installed on a compatible Android device for development and testing.
Smart Blocker is a mature, production-oriented project rather than a minimal call-blocking demo. It covers the complete flow from onboarding and account management to rule creation, live call handling, encrypted persistence, synchronization, diagnostics, accessibility, and automated testing.
Because call handling operates close to protected Android telephony functionality, real-device behavior depends on the granted permissions, Android version, default phone configuration, and manufacturer restrictions.