Architecture - HmnDev-Tech/BLE-Droid GitHub Wiki

Architecture

Single-module Android app (app/), Kotlin + Jetpack Compose, version catalog in gradle/libs.versions.toml.

app/src/main/java/com/bledroid/
  BleDroidApp.kt                  Application entry
  MainActivity.kt                 Compose host, nav stack
  engine/BleAdvertiserEngine.kt   advertise loop + radar scan + classifier
  generators/                     per-protocol payload builders
    FastPairGenerator.kt          service data 0xFE2C
    AppleDevicePopupGenerator.kt  mfr data 0x004C type 0x07
    AppleActionModalGenerator.kt  mfr data 0x004C type 0x0F
    SamsungBudsGenerator.kt       mfr data 0x0075
    SamsungWatchGenerator.kt      mfr data 0x0075 (watch)
    SwiftPairGenerator.kt         mfr data 0x0006
    LovespouseGenerator.kt        mfr data 0x00FF
    SpamGenerator.kt              Mix All: interleaves the above
  helpers/HexUtils.kt             hex encode/decode
  models/Models.kt                shared data classes
  service/SpamForegroundService.kt  foreground notification + control
  ui/BleDroidViewModel.kt         single ViewModel, app state
  ui/components/Components.kt     shared Compose components
  ui/navigation/Routes.kt         nav routes
  ui/screens/                     Dashboard, spam screens, CustomBle,
                                  SpamRadar, Settings, MixAll
  ui/theme/                       Material 3 Expressive theme

Data flow

UI (Compose screen)
  -> BleDroidViewModel
    -> SpamForegroundService (when foreground service enabled)
      -> BleAdvertiserEngine
        -> generator (protocol payload)
        -> BluetoothLeAdvertiser
    <- scan callback -> classifier -> radar state -> SpamRadarScreen
  • Engine owns the advertise loop (interval, TX power, packet counter) and the scan loop that classifies incoming advertisements by manufacturer ID and payload.
  • Generators are pure functions: input = selected devices/preset, output = raw payload bytes. No Android APIs inside — easy to unit test.
  • ViewModel is the single source of truth for UI state; the service publishes counters back to it.

Conventions

  • Kotlin official style (ktlint defaults), no hardcoded strings in UI — add them to res/values/strings.xml.
  • State flows down, events flow up through the ViewModel.
  • New protocol = new generator + registration in SpamGenerator + a screen/route.

See Contributing before opening a PR.