-
Notifications
You must be signed in to change notification settings - Fork 10
SMS Router Client Application
This document covers the overall architecture, structure, and configuration of the Effective Office SMS Router client application. This is an Android application that serves as a message forwarding service, intercepting incoming SMS messages and forwarding them to configured webhooks (Mattermost, Telegram) with per-SIM configuration, delivery logging, and retry mechanisms.
| Component | Technology / Library | Notes |
|---|---|---|
| Language / Runtime | Kotlin, JVM 17 | Android application development |
| UI Framework | Jetpack Compose | Modern declarative UI for settings and message screens |
| Dependency Injection | Koin | Service locator–based dependency injection |
| Networking | Ktor Client | HTTP client for webhook requests |
| Database | Room | Local storage for SMS delivery logs |
| State Management | ViewModel + LiveData | Reactive state management |
| Build Tooling | Gradle 8.x | Project build configuration |
The SMS Router follows a clean architecture pattern with clear separation of concerns between data, domain, and presentation layers.
| Source | Processing Path | Purpose |
|---|---|---|
| SMS Receiver | BroadcastReceiver → ForwardSmsUseCase → SmsApiService | Intercept and forward SMS messages |
| Settings UI | SettingsViewModel → SettingsRepository → SharedPreferences | Persist per-SIM configuration |
| Delivery Logs | SmsLogsRepository → Room Database → Messages UI | Track forwarding status and history |
The application processes SMS messages through a pipeline that includes interception, transformation, forwarding with retry logic, and persistent logging of delivery status.
- MainActivity: Entry point that initializes Koin dependency injection and hosts the Compose UI
- Settings Screen: Allows configuration of per-SIM webhook URLs, secret keys, webhook types, and Telegram chat IDs
- Messages Screen: Displays delivery logs and forwarding status with real-time updates
- Permission Management:: Runtime permission requests for SMS-related permissions
Key Android configuration extracted from app/build.gradle.kts:
android {
namespace = "band.effective.office.smsrouter"
compileSdk = 34
defaultConfig {
applicationId = "band.effective.office.smsrouter"
minSdk = 24
targetSdk = 33
versionCode = 3
versionName = "1.0.0"
}
buildFeatures {
compose = true
buildConfig = true
}
}
| Module Category | Modules | Dependencies |
|---|---|---|
| Application | app |
Core modules, shared module |
| Core |
data, domain, presentation
|
External libraries, Room, Ktor |
The application is organized around several key components:
- SmsReceiver: Stack navigation between Welcome, Menu, and Autoplay surfaces
- ForwardSmsUseCase: Creation and destruction of child components using Decompose
- SmsApiServiceImpl: Performs HTTP requests to webhooks with retry logic and timeout handling
- SettingsViewModel: Manages UI state for per-SIM configuration
- SmsLogsRepository: Persists and retrieves delivery logs from Room database
The settings system uses SharedPreferences for per-SIM configuration:
class SettingsViewModel(
private val settingsRepository: SettingsRepository,
private val simcardProvider: SimCardProvider,
) : ViewModel() {
// Handle intents from the UI
fun sendIntent(intent: Intent) {
when (intent) {
is Intent.UpdateWebhookUrl -> updateWebhookUrl(intent.simId, intent.url)
is Intent.UpdateSecretKey -> updateSecretKey(intent.simId, intent.key)
is Intent.UpdateWebhookType -> updateWebhookType(intent.simId, intent.webhookType)
is Intent.UpdateChatId -> updateChatId(intent.simId, intent.chatId)
is Intent.SaveSettings -> saveSettings()
}
}
}
The application uses runtime configuration for webhook settings:
| Configuration | Storage | Purpose |
|---|---|---|
| Webhook URLs | SharedPreferences | Target endpoints for SMS forwarding |
| Secret Keys | SharedPreferences | Authentication for webhook requests |
| Webhook Types | SharedPreferences | Mattermost vs Telegram payload format |
| Telegram Chat IDs | SharedPreferences | Target chat for Telegram messages |
Webhook requests include Authorization: Bearer header and format-specific payloads:
- Mattermost: { "text": "" }
- Telegram: { "chat_id": "", "text": "" }