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 byFieldwatchViewModel.kt. - Scanning is performed by
app/src/main/java/app/fieldwatch/radio/ScanService.ktwhich feeds raw packets intoBleAdParser.ktandWifiIeParser.kt. - Parsed data is persisted via
DeviceStore.kt,LogStore.kt, andSitStore.kt. - Reports are generated by classes such as
DebriefPdf.ktandSitExport.kt.
How It Is Wired
Entry Point
app/src/main/java/app/fieldwatch/MainActivity.ktlaunches the app and createsFieldwatchAppUiwhich observesFieldwatchViewModel.
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.xmldeclaresBLUETOOTH_SCAN,BLUETOOTH_CONNECT, andACCESS_FINE_LOCATION. - Filesystem:
app/src/main/assets/lookups/radiodb.binandradiodb.txtare read byRadioDb.kt. - Local storage: SQLite via
Roomis used inConfigStore.ktandDeviceStore.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.ymlruns./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.