Notification Guard

Notification Guard logo

Notification Guard filters incoming Android notifications against weekday + time-based profiles (night, lunch break, working hours, weekend, custom) and fully custom per-app rules with multiple exception types per rule (keyword or contact). A hardcoded privacy filter ensures that notifications from sensitive app categories — banking, authenticator, medical, public-sector — are always let through without their content ever entering the store.

PropertyValue
PlatformAndroid 7+ (API 24)
StackTauri v2 · Rust · Svelte 5
Languages7
Repositorygit.pronix.org/oiv1Ni3o/notification-guard
  flowchart LR
    A[App notifications] --> B[Local capture<br/>on-device only]
    B --> C[(Encrypted local storage)]
    C --> D[User view]
    D --> E[Manual export]
    B -.->|never| F[("Cloud / Server")]
    style F stroke-dasharray: 5 5,stroke:#c00,color:#c00

What the app does

  • 🕒 Weekday + time profiles — Profiles activate by day of week AND time of day. Built-in profiles (night, lunch break, working hours, weekend) plus user-defined profiles. App categories are bundled into profiles — no need to author a rule per app.
  • ✏️ Visual rule editor — Add and edit per-app rules in a dedicated editor view. Each rule supports multiple exceptions of two types: by keyword (notification text matches) or by contact (sender / messenger contact).
  • 📦 Catalogued top apps — 77 curated app presets across five categories (Social, Games, News, Shopping, Streaming). Filterable by installed apps.
  • 🧠 Sub-10 ms rules engine — Rust-based evaluation in under 10 ms per notification. Privacy filter runs first; user rules take priority over profiles; profiles match by weekday and time-of-day. Per-rule exceptions of two types: contact or keyword.
  • 🗑️ TTL cleanup — Blocked notifications are deleted automatically after a configurable retention (24 h default). “Clear all” with a tap.

Privacy

Local-only architecture. No server, no account, no tracking, no analytics. The Android manifest declares no internet permission.

What you can expect

  • Fully local — all data stays on the device
  • No servers, no cloud, no third-party SDKs
  • No internet access (manifest contains no android.permission.INTERNET)
  • No crash reporters, no analytics, no telemetry
  • SQLite database in the app-private storage
  • Automatic cleanup of blocked notifications via TTL
  • Manual “Clear all” available at any time

Privacy filter — sensitive apps are never blocked

The NotificationListenerService unavoidably sees every notification. A pre-filter sorts sensitive app categories out BEFORE the rules engine ever sees them — these notifications never enter the store, and their content is never persisted.

Protected categories (auto-detected):

  • 🏦 Banking — major banks, savings banks, neobanks
  • 🔐 Authenticator / 2FA — Google Authenticator, FreeOTP, Aegis, app-specific 2FA flows
  • 🏥 Medical — health insurance (TK, AOK, Barmer, …), pharmacy and medication-tracker apps
  • 🏛️ Government — federal services, tax authorities (Elster), public-sector identity apps

Regular apps pass through to the rules engine unchanged.

Google Play compliance

Six hard architectural constraints derived from current Google Play policies (Data Safety, Permissions Declaration, Notification Listener). Each one is tracked as a Gitea issue.

IDRequirementStatus & implementation
C1Prominent disclosure & consent✓ Met — 4-step wizard covering disclosure, profile selection, category selection, permission activation. Clear notes: local, no server, no network.
C2No SYSTEM_ALERT_WINDOW✓ Met — The manifest does not declare the permission. Re-notifications go through NotificationManager.
C3Data retention TTL✓ Met — Configurable retention (24 h default). Periodic cleanup task (Tokio interval, 60 min). “Clear all” button with confirmation dialog.
C4Contact picker instead of READ_CONTACTS○ Planned — Will be added as an optional opt-in module using the Android Contact Picker — no READ_CONTACTS.
C5Privacy filter (blocklist of sensitive app categories)✓ Met — Hardcoded default blocklist as a pre-filter inside the rules engine. First check in evaluate() — match → immediate Pass, no evaluation, no storage.
C6No network layer✓ Met — Manifest verified (aapt dump badging). No HTTP client dependencies in any Cargo.toml. The app runs entirely in airplane mode.

Declared permissions

Four manifest permissions, each with a concrete functional purpose. No runtime permissions, no restricted special access beyond the core listener.

  • android.permission.BIND_NOTIFICATION_LISTENER_SERVICE — Core function. Without this permission the app cannot read or filter any notifications. Activated explicitly by the user via system settings.
  • android.permission.RECEIVE_BOOT_COMPLETED — Reconnects the listener service after a device restart. Without it, the app would be blind after every reboot until launched manually.
  • android.permission.WAKE_LOCK — Reliably triggers snooze timers from Doze mode (planned for phase 2).
  • android.permission.POST_NOTIFICATIONS — Surfaces our own re-notifications (released or snoozed) — instead of an overlay window (see C2).

Technology

  • Frontend — Svelte 5 (Runes) inside the Tauri WebView, responsive from 360 px, bottom-tab layout on mobile.
  • Localizationsvelte-i18n with OS-locale detection via tauri-plugin-os. Available languages: English, German, French, Spanish, Chinese, Japanese, Korean.
  • Backend — Rust + Tauri v2 host. Three in-house plugins (Listener, Rules Engine, Store) plus the official Notification and OS plugins.
  • Mobile layer — Android Kotlin: NotificationListenerService bridges events through the Tauri plugin API into the Rust pipeline.
  • Database — SQLite via rusqlite (WAL, foreign keys on). 5 migrations. App-private file, no external access.
  • Build & signing — Universal APK and AAB (Google Play AAB requirement). Dev builds signed with a local keystore. APK currently ~14 MB.

Architecture highlights

  • Plugin isolation — The three in-house plugins (notif-listener, rules-engine, notif-store) have no cross-dependencies. Communication goes exclusively through the Tauri host as a mediator.
  • Privacy filter at the pipeline entry — Sensitive apps are filtered out before the rules engine sees them — the content of sensitive notifications is never logged or stored.
  • Profiles vs. rules — Beginner UX via predefined profiles + app categories; power-user UX via individual rules in an “advanced” view. Both paths share the same engine.
  • Mobile specifics — Custom plugin Android modules with AndroidManifest merging. Permission onboarding handles the Android 13 restricted-settings lockout for sideloaded APKs.

Notification Guard — Repository: git.pronix.org/oiv1Ni3o/notification-guard