TrackerDetector is an Android app from Alsatian Consulting for people concerned about digital surveillance around their phone. It continuously and passively watches Wi-Fi, Bluetooth, cellular behavior, and GPS integrity, then raises rule-based alerts when suspicious patterns appear. Everything runs on-device — there are no accounts, no sign-in, and no cloud.
Important: Alerts indicate suspicious signals and patterns, not legal proof. Always combine alert history with your own context — place, time, movement, and the infrastructure you would normally expect nearby.
- Publisher: Alsatian Consulting, LLC — https://www.alsatian.consulting
- Package:
dev.alsatianconsulting.trackerdetector - Version: 1.1 (versionCode 5) · minSdk 26 (Android 8.0) · targetSdk / compileSdk 36
- License: Apache-2.0 (see
LICENSEandNOTICE) - Full documentation: see the project Wiki and the
wiki/folder in this repository.
A local-first, rule-based counter-surveillance and tracker-detection tool for Android. It surfaces indicators associated with Bluetooth trackers, rogue/cloned Wi-Fi access points, surveillance and radio equipment, cellular anomalies, and GPS manipulation, and gives you the evidence — grouped alerts, device measurements, a map, and exports — to make your own judgment.
- Bluetooth trackers — AirTag, Apple Find My, AirPods, Tile, Chipolo, Pebblebee, Samsung SmartTag, Samsung Find My Mobile, and Google Find My families, with separate following (moves with you) and nearby-persistent (stays close) logic.
- Wi-Fi threats — Wi-Fi Pineapples, rogue/cloned access points, mismatched network identities, and pattern signatures for surveillance and specialized-radio equipment (bodycams, LPR/camera systems, tactical radios) and drones.
- Cellular anomalies — unknown towers/areas versus offline OpenCellID reference data, short-serving towers, reject artifacts, IMSI / MCC-MNC mismatches, LAC jumps, and technology changes.
- GPS manipulation — mock providers, impossible speed, jump-without-satellite-shift, persistent GPS/network divergence, altitude anomalies, and poor-signal / jamming conditions.
- Rooted diagnostics (optional) — silent type-0 SMS indicators, cellular reject reasons, and traffic-channel lock detection from low-level radio logs.
Every alert has a severity (high / medium / low, or off) and can be tuned or disabled. See the wiki Alerts Reference and Rules & Severity for the full catalog.
Ten destinations are reachable from the navigation drawer: Status, Summary, Map, WiFi Access Point Measurement, Bluetooth Device Measurement, Cellular Tower Management, GPS Security, Database, Settings, About. See the wiki Screens & Layouts page for a walkthrough of every screen, button, and menu.
- Imports: offline OpenCellID reference (
.csv.gz) for serving-tower comparison; device-list files for alert / ignore / expected-Wi-Fi lists; and previously exported TrackerDetector.sqlitedatabases, one or several at a time, viaDatabase > Import. Imports append: a device present in both is merged (earliest first-seen, latest last-seen, summed sample counts) rather than overwritten, and exactly-matching alerts are skipped, so re-importing the same file does not duplicate history. - Exports: alerts and observations as CSV, JSON, KMZ/KML, WiGLE-style Wi-Fi CSV, managed device lists, and the full SQLite database. All exports are user-initiated and written to a location you choose via the Android file picker; large exports are automatically zipped. Export text is sanitized — control characters stripped, delimiters escaped, and spreadsheet formula triggers defused — while numeric fields stay numeric.
- Storage: alert and observation data lives in the app's private storage in a Room (SQLite) database that is encrypted at rest (SQLCipher, keystore-wrapped key). It persists until you clear it, enable clear-on-startup, or uninstall.
- Network: the app makes no outbound network calls and stores nothing on remote servers.
- Install and open the app.
- Work through the permission explanation pages (Location, Bluetooth, Nearby Wi-Fi Devices, Notifications) and grant each permission. On Android 11+, Background Location is a separate "Allow all the time" grant.
- Allow the battery-optimization exemption when prompted so scanning survives the screen being off.
- The app opens on Status and scanning starts automatically. Watch the severity tiles; tap a tile to review active alerts for that domain.
- Open a measurement screen (Wi-Fi / Bluetooth / Cellular / GPS) to inspect individual devices, or use Geiger mode to locate a source by signal strength.
- Visit Settings to tune rules, manage device lists, import OpenCellID data, or enable boot-start.
- Export evidence (CSV / JSON / KMZ / SQLite) before clearing alerts if you may need it later.
Scanning runs as a foreground service and keeps running when the app is not on screen. Pressing Home, switching apps, or swiping the app off the recents list leaves collection running, and reopening rejoins the same session instead of starting a new one. If Android tears the process down for any reason other than a deliberate quit, a restart watchdog brings collection back.
The only way to stop scanning is the navigation drawer → Quit, which stops the service, cancels the watchdog, and closes the app. Opening the app again starts a new run.
This depends on the battery-optimization exemption requested during onboarding (or later via Settings > Advanced > Request unrestricted battery). Android throttles or kills background scanning for battery-optimized apps, causing missed detections, and it only permits the watchdog to relaunch collection for exempted apps.
Common workflows and role-based playbooks (journalists, sources, personal safety) are in the wiki Use Cases page.
- JDK 17 —
brew install openjdk@17(macOS) ·sudo apt install openjdk-17-jdk(Debian/Ubuntu) - Android SDK (API 36) — via Android Studio, or command-line tools; set
ANDROID_HOMEor createlocal.propertieswithsdk.dir=<path> - Gradle — bundled via the
./gradlewwrapper; no separate install needed
git clone https://github.com/AlsatianConsulting/TrackerDetector.git
cd TrackerDetector
./gradlew :app:assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk
adb shell am start -n dev.alsatianconsulting.trackerdetector/.MainActivityOr open the project in Android Studio and press Run.
Release signing is not committed to this repository. Provide your own keystore through either environment variables or a local properties file, then build:
# Option A — environment variables
export TD_RELEASE_STORE_FILE=/absolute/path/to/your.jks
export TD_RELEASE_STORE_PASSWORD=********
export TD_RELEASE_KEY_ALIAS=your-alias
export TD_RELEASE_KEY_PASSWORD=******** # optional; defaults to store password
# Option B — a properties file at continuity/generated/release-keystore.properties
# storeFile=/absolute/path/to/your.jks
# storePassword=********
# keyAlias=your-alias
# keyPassword=********
./gradlew :app:assembleRelease # -> app/build/outputs/apk/release/app-release.apk
./gradlew :app:bundleRelease # -> app/build/outputs/bundle/release/app-release.aabIf no signing material is supplied, the release build still compiles but produces an unsigned artifact.
Run the steps individually to isolate the problem:
# 1. Point Gradle at your SDK if ANDROID_HOME is not set
echo "sdk.dir=$HOME/Library/Android/sdk" > local.properties # macOS example
# 2. Confirm JDK 17 is active
java -version
# 3. Download dependencies only (surfaces network/SDK issues early)
./gradlew dependencies
# 4. Build with a clean daemon and full logging
./gradlew clean :app:assembleDebug --no-daemon --stacktrace- Ensure API 36 and matching build-tools are installed in the SDK.
- Once the Gradle cache is populated, later builds can run offline with
--offline. - If a release build reports it is unsigned, supply the signing material as shown in section 4.
Screenshots below are captured from a real device with active scanning. Device identifiers (MAC/BSSID) are blurred; layout, controls, and columns are intact.
| Status | Bluetooth Device Measurement | Map |
|---|---|---|
The full annotated set — every screen, menu, and detail pane — is in the wiki Screens & Layouts page and the wiki/screenshots/ folder.
Kotlin + Jetpack Compose, single Gradle module under app/. See ARCHITECTURE.md and DETECTION_ENGINE.md for detail.
TrackerDetector/
├── build.gradle.kts · settings.gradle.kts · gradle.properties · gradlew · gradlew.bat
├── LICENSE · NOTICE
├── README.md · ARCHITECTURE.md · DETECTION_ENGINE.md · PRIVACY_POLICY.md · RELEASE_NOTES.md
├── app/
│ ├── build.gradle.kts · proguard-rules.pro
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── assets/ # rules.json, watchlists.json, oui_lookup.csv, ble_company_ids.csv, …
│ │ ├── java/com/trackerdetector/ # service, data (DetectionEngine, Room), model, scanner, ui, util
│ │ └── res/
│ ├── androidTest/ # instrumented tests
│ └── test/ # unit tests
├── gradle/wrapper/
└── wiki/ # full documentation + redacted screenshots
- Alert/observation data lives in the app's encrypted private storage; it does not survive uninstall.
- Bluetooth detection relies on passive BLE scanning; rotating MAC addresses limit cross-session correlation.
- Cellular unknown-tower checks need an imported OpenCellID
.csv.gz; without it,cell.unknown_reference/cell.unknown_areacannot fire reliably. - Android has no monitor mode, so Wi-Fi injection/deauthentication attacks cannot be observed.
- GPS spoofing detection is heuristic; sophisticated setups may not trip every rule.
- Rooted diagnostics require root, available radio logs, and cooperative vendor behavior.
- All detection and storage is entirely local; nothing is transmitted.
- The user-data database is encrypted at rest (SQLCipher).
- Exports may contain GPS coordinates, Wi-Fi BSSIDs, Bluetooth MAC addresses, and cellular tower identifiers — handle them accordingly.
- To remove all data: reset the database in Settings, enable clear-on-startup, or uninstall.
See PRIVACY_POLICY.md for the full policy.
Copyright © Alsatian Consulting, LLC. Licensed under Apache-2.0 — see LICENSE and NOTICE.
