Introduction to FlowBell
Relevant source files
The following files were used as context for generating this wiki page:
- README.md
- app/src/main/kotlin/com/fathiraz/flowbell/data/services/NotificationListenerService.kt
- app/src/main/kotlin/com/fathiraz/flowbell/data/local/database/FlowBellDatabase.kt
- app/src/main/kotlin/com/fathiraz/flowbell/MainActivity.kt
- app/src/main/kotlin/com/fathiraz/flowbell/presentation/app/App.kt
- app/src/main/kotlin/com/fathiraz/flowbell/core/di/DataModule.kt
- app/src/main/kotlin/com/fathiraz/flowbell/core/utils/HttpRequestUtils.kt
FlowBell is a single-module Android application designed to serve as a notification bridge. It monitors system notifications through a NotificationListenerService, filters them based on user-defined rules, and forwards the data as JSON payloads to a configured webhook endpoint in near real-time. The project is built using modern Android development practices, including Jetpack Compose for the UI, Koin for dependency injection, and Room for on-device persistence.
The application allows users to replace paid integration services by owning their own data pipeline. It features batch delivery of notifications, comprehensive history tracking with HTTP status codes, and per-app control to granularly enable or disable forwarding for specific applications.
Sources: README.md:1-55, app/src/main/kotlin/com/fathiraz/flowbell/data/services/NotificationListenerService.kt:56-62
Core Architecture
FlowBell follows a Clean Architecture approach, separating responsibilities into three primary layers despite residing in a single Gradle module:
- Presentation: Utilizes Jetpack Compose, MVVM pattern, and
StateFlow. Navigation is managed via a singleMainActivityusingnavigation-compose. - Domain: Contains plain Kotlin data classes (Entities) and repository interfaces to ensure business logic remains testable and decoupled from implementation details.
- Data: Handles persistence via Room (
FlowBellDatabase), network communication through OkHttp inHttpRequestUtils, and system-level interactions via theNotificationListenerService.
Sources: README.md:113-125, app/src/main/kotlin/com/fathiraz/flowbell/core/di/DataModule.kt:25-58
System Data Flow
The flow of information from a system notification to a remote webhook follows a structured pipeline:
- Capture: The
NotificationListenerServicedetects a newStatusBarNotification. - Filtering: The service checks if the originating app is enabled and if the content passes keyword filters.
- Queueing: Validated notifications are added to a
ConcurrentLinkedQueuefor batching. - Transmission: Every five seconds, the batch job drains the queue and uses
HttpRequestUtilsto POST the data to the webhook. - Logging: Results (success/failure, HTTP codes, latency) are saved back to the Room database.
Sources: README.md:127-135, app/src/main/kotlin/com/fathiraz/flowbell/data/services/NotificationListenerService.kt:135-215
The diagram shows the lifecycle of a notification from arrival to remote delivery and local logging.
Sources: README.md:127-135, app/src/main/kotlin/com/fathiraz/flowbell/data/services/NotificationListenerService.kt:135-215
Database Schema
FlowBell uses Room for all on-device storage. The database handles notification history, per-app settings, and global user preferences.
Key Entities
| Table | Description | Primary Key |
|---|---|---|
notification_queue | Stores history of captured notifications and their delivery status. | id (Auto-increment) |
app_preferences | Tracks which apps are enabled for forwarding and their specific filter words. | packageName |
user_preferences | Global settings including Webhook URL, theme mode, and debug status. | id (Default 1) |
Sources: app/src/main/kotlin/com/fathiraz/flowbell/data/local/database/FlowBellDatabase.kt:33-125, app/src/main/kotlin/com/fathiraz/flowbell/core/di/DataModule.kt:28-35
Migration History
The database has evolved through multiple versions to support new features:
- Version 2-3: Added
user_preferencesfor webhook storage. - Version 5-6: Added HTTP details (Method, Response Code, Body, Duration) to
notification_queue. - Version 8-9: Added global and per-app filter words columns.
- Version 9-10: Added
notification_filter_enabledtoggle.
Sources: app/src/main/kotlin/com/fathiraz/flowbell/data/local/database/FlowBellDatabase.kt:45-185
Notification Processing Logic
The NotificationListenerService is the engine of the application. It handles deduplication and batching to optimize battery and network usage.
The sequence diagram illustrates the internal processing and validation steps within the service before a webhook is triggered.
Sources: app/src/main/kotlin/com/fathiraz/flowbell/data/services/NotificationListenerService.kt:135-180, app/src/main/kotlin/com/fathiraz/flowbell/data/services/NotificationListenerService.kt:335-375
Webhook Payload Structure
Payloads are standardized as JSON and include device metadata, app information, and the notification content:
{
"id": "uuid",
"timestamp": "ISO-8601",
"app": { "packageName": "...", "name": "..." },
"notification": { "title": "...", "text": "...", "priority": "..." },
"device": { "id": "fingerprint", "platform": "android", "version": "..." },
"security": { "nonce": "...", "algorithm": "HMAC-SHA256" }
}
Sources: README.md:195-235, app/src/main/kotlin/com/fathiraz/flowbell/data/services/NotificationListenerService.kt:560-600
Dependency Injection and Initialization
The application uses Koin for dependency management. Modules are defined in DataModule, DomainModule, and PresentationModule.
Initialization Sequence
When the App class starts, it initializes the following components:
- Timber: Planted with a
DebugTreeand optionalCrashlyticsintegration. - Debug Tools:
DebugToolsManagerinitializes Chucker and Beagle. - Koin: Starts the DI container with all defined modules.
- Beagle: Configures the debug menu with modules like
AppInfo,NetworkLogList, andDeviceInfo.
Sources: app/src/main/kotlin/com/fathiraz/flowbell/presentation/app/App.kt:40-100, app/src/main/kotlin/com/fathiraz/flowbell/core/di/DataModule.kt:25-58
Network Configuration
The HttpRequestUtils provides a centralized OkHttpClient configured with:
- Timeouts: 30s connection, 45s read, 30s write.
- Interceptors: Chucker for traffic inspection and Beagle for network logging.
- DNS Resolution: Custom multi-method resolution (InetAddress) to troubleshoot network issues.
Sources: app/src/main/kotlin/com/fathiraz/flowbell/core/utils/HttpRequestUtils.kt:32-60, app/src/main/kotlin/com/fathiraz/flowbell/core/utils/HttpRequestUtils.kt:70-120
Conclusion
FlowBell serves as a robust, privacy-focused utility for Android users needing to integrate on-device events with external automation platforms. By leveraging NotificationListenerService and a batching persistence model, it ensures reliable delivery while minimizing system impact. Its modern tech stack and comprehensive logging make it an extensible foundation for developers and automation builders alike.
Sources: README.md:43-65, app/src/main/kotlin/com/fathiraz/flowbell/data/services/NotificationListenerService.kt:115-133