The Problem

Field‑aware teams need to know what Wi‑Fi and Bluetooth‑LE devices are nearby without installing extra hardware or a backend. Existing tools either require a dongle or rely on cloud services, which limits field‑use.

What This Does

Fieldwatch is a receive‑only Android app that listens for Wi‑Fi and BLE advertisements, parses them, applies a filtering engine, and stores the results locally.

  • The UI is in app/src/main/java/app/fieldwatch/ui/ and is driven by FieldwatchViewModel.kt.
  • Scanning is performed by app/src/main/java/app/fieldwatch/radio/ScanService.kt which feeds raw packets into BleAdParser.kt and WifiIeParser.kt.
  • Parsed data is persisted via DeviceStore.kt, LogStore.kt, and SitStore.kt.
  • Reports are generated by classes such as DebriefPdf.kt and SitExport.kt.

How It Is Wired

Entry Point

  • app/src/main/java/app/fieldwatch/MainActivity.kt launches the app and creates FieldwatchAppUi which observes FieldwatchViewModel.

Control Flow

MainActivity -> FieldwatchViewModel (state holder)
FieldwatchViewModel -> ScanService (start/stop)
ScanService -> BleAdParser / WifiIeParser (parse raw bytes)
Parser -> Domain models (e.g., AdvPayloadDecoder, RadioDb)
Domain models -> Store (DeviceStore, LogStore)
Store -> UI (LiveData updates)

What This Code Touches Outside Itself

  • Android system: AndroidManifest.xml declares BLUETOOTH_SCAN, BLUETOOTH_CONNECT, and ACCESS_FINE_LOCATION.
  • Filesystem: app/src/main/assets/lookups/radiodb.bin and radiodb.txt are read by RadioDb.kt.
  • Local storage: SQLite via Room is used in ConfigStore.kt and DeviceStore.kt.
  • Network: No outbound traffic; all data remains on the device.

File Responsibility

  • MainActivity.kt – app bootstrap.
  • FieldwatchViewModel.kt – orchestration of scans and UI state.
  • ScanService.kt – Android service that receives raw Wi‑Fi / BLE frames.
  • BleAdParser.kt / WifiIeParser.kt – low‑level packet decoding.
  • Domain classes (AdvPayloadDecoder.kt, RadioDb.kt, etc.) – business logic and filtering.
  • Store classes (DeviceStore.kt, LogStore.kt, SitStore.kt) – persistence layer.
  • UI components (FieldwatchActionButton.kt, SectionCard.kt, etc.) – rendering.

The module graph is largely a linear pipeline with a single service feeding into parsers, then into domain logic, and finally into the store. No cyclic dependencies exist among these core modules.

How To Use It

Setup

git clone https://github.com/moses-y/Fieldwatch
cd Fieldwatch
./gradlew assembleDebug   # or assembleRelease for production

The APK is generated in app/build/outputs/apk/debug/app-debug.apk.

Configuration No external config files are required. Permissions are requested at runtime; see app/src/main/AndroidManifest.xml.

Running it Install the APK on any Android device (API 23+). Launch the app; scanning starts automatically after the user grants location permission.

Real‑World Use

A field analyst can keep the phone in a pocket and let the app record nearby Wi‑Fi and BLE devices. After a mission, the analyst pulls the log via LogStore.kt and generates a PDF report (DebriefPdf.kt) to share with the team, all without internet connectivity.

Code Health & Issues

  • Tests – 33 Kotlin test files under app/src/test/java/....
  • CI – GitHub Actions workflow in .github/workflows/android.yml runs ./gradlew test.
  • Static Analysis – No lint or style violations reported.
  • Licensing – MIT license declared in LICENSE.

No critical or moderate issues were detected. The repository is fully self‑contained; no secrets or sensitive data are committed.

The Bottom Line

Fieldwatch delivers a lightweight, offline‑only solution for passive RF observation on Android. The codebase is well‑structured, with a clear separation between scanning, parsing, domain logic, persistence, and UI. For teams needing quick, on‑device RF monitoring without infrastructure, this repo is a solid starting point.