Skip to content

Repository files navigation

AndroWatch

See what your Android device reveals — and why it matters for fingerprinting.

MIT License CI Release API docs minSdk 26 compileSdk 37

AndroWatch is an open-source Android privacy audit app inspired by Loupe. It collects on-device fingerprint signals through public Android APIs, groups them by access cost, and explains why each reading can contribute to tracking.

All data stays on your phone unless you explicitly export a JSON report.


Table of contents


Features

Feature Description
30 signal categories Device identity, network, sensors, apps, WebView canvas/WebGL, and more
3 sensitivity tiers Passive · Permissioned · Advanced
Privacy rationales Every signal includes a short explanation of fingerprinting relevance
Runtime permission gates Dangerous permissions requested only when you open a category
Live collectors Battery, motion, and audio route update in real time
JSON export Share a structured report via Android share sheet (FileProvider)
Material 3 UI Jetpack Compose, dynamic color, edge-to-edge
i18n Extensive values-* string resources
Release hardening R8 minify, resource shrink, privacy-safe logging

Signal categories (30)

Passive (17) — no dangerous permissions

DeviceIdentity · GoogleAccount · SystemInfo · Display · Locale · Accessibility · DeviceMotion · Battery · Storage · Network · Fonts · InstalledVoices · AppInfo · Pasteboard · Audio · Graphics · Telephony

Permissioned (10) — runtime permission required

Motion · Location · Cameras · Bluetooth · LocalNetwork · Contacts · Photos · Calendar · Reminders · MusicLibrary

Advanced (3) — side-channels / on-demand probes

InstalledAppsProbe · WebViewFingerprint · PreviousInstallsLog

Full API mapping: docs/ANDROID_API_MAP.md


Signal tiers

flowchart LR
    P[Passive<br/>17 collectors] --> UI[Compose UI]
    R[Permissioned<br/>10 collectors] --> UI
    A[Advanced<br/>3 collectors] --> UI
    UI --> E[JSON Export]
Loading
Tier Runtime prompt Examples
Passive None Build.*, Settings, ConnectivityManager
Permissioned Per category Location, camera, contacts, Bluetooth scan
Advanced On-demand / side-channel WebView canvas hash, URI scheme app probing

Architecture

10-module Gradle project — dependencies flow downward only:

:app
 ├── :collector:assembly → tier-passive / tier-permissioned / tier-advanced
 │                         └── :collector:engine → :collector:contract
 ├── :feature:export
 └── :core:model, :core:permission

See docs/ARCHITECTURE.md for the full module graph and data flow.

Module Role
:app Compose shell, CategoryViewModel, navigation
:core:model FingerprintSignal, SignalCategory, Sensitivity
:core:permission PermissionCenter — category → permission mapping
:collector:contract SignalCollector / LiveSignalCollector interfaces
:collector:engine Probes, interpreters, WebView/GLES/mDNS helpers
:collector:tier-* 30 category collectors
:collector:assembly CollectorRegistry wiring
:feature:export ReportExporter JSON + share intent

Install from GitHub Releases

  1. Open Releases.
  2. Download the APK matching your device CPU:
APK suffix Device
arm64-v8a Most phones & tablets (2017+)
armeabi-v7a Older 32-bit ARM
x86_64 Emulators / some Chromebooks
x86 Older 32-bit emulators
  1. Enable Install unknown apps for your browser/files app.
  2. Install the APK.
# Or via ADB (replace ABI and version)
adb install AndroWatch-0.1.0-arm64-v8a-release.apk

Build it yourself

Prerequisites

Tool Version
JDK 17+ (Temurin recommended)
Android SDK API 37 (platforms;android-37, build-tools;36.x)
adb For device install (platform-tools)

Copy local.properties.examplelocal.properties and set sdk.dir, or set ANDROID_HOME.

One-shot commands

Linux / macOS

git clone https://github.com/LTechnologies0/AndroWatch.git
cd AndroWatch
cp local.properties.example local.properties   # edit sdk.dir

# Debug APK (single ABI — fast)
./gradlew :app:assembleDebug

# Run unit tests
./gradlew test

# Install on connected device
./gradlew installToPhone
# or
adb install -r app/build/outputs/apk/debug/app-arm64-v8a-debug.apk

# Release APKs (all 4 ABIs, signed if keystore present)
./scripts/generate-release-keystore.sh   # first time only
./gradlew :app:assembleRelease

Windows (PowerShell)

git clone https://github.com/LTechnologies0/AndroWatch.git
cd AndroWatch
Copy-Item local.properties.example local.properties   # edit sdk.dir

.\gradlew.bat :app:assembleDebug
.\gradlew.bat test
.\gradlew.bat installToPhone

Fedora / Bazzite (USB debugging)

# udev rules for ADB (once, requires sudo)
sudo ./scripts/setup-udev.sh 2>/dev/null || true

adb devices
./gradlew installToPhone

Build variants

Command Output
assembleDebug 1 APK (arm64-v8a by default)
assembleDebug -Ponionphone.devAbi=x86_64 Debug for emulator
assembleRelease 4 signed APKs (one per ABI)
dokkaGenerate HTML API docs in build/dokka/html/

Local release signing

./scripts/generate-release-keystore.sh
# Creates release.keystore + keystore.properties (both gitignored)
./gradlew :app:assembleRelease

Never commit keystore.properties, *.keystore, or local.properties.


API documentation (KDoc)

All public APIs are documented with KDoc in source. HTML reference is generated with Dokka:

./gradlew dokkaGenerate
# → build/dokka/html/index.html

Published automatically to GitHub Pages on every push to main:

https://ltechnologies0.github.io/AndroWatch/

(workflow: .github/workflows/docs.yml)


Security

  • Local-first: no network upload of fingerprint data
  • No hardcoded secrets: signing via keystore.properties (gitignored) or CI secrets
  • Release stripping: verbose collector logs removed by R8 (gradle/privacy-logging.pro)
  • Backup disabled in manifest

See SECURITY.md for vulnerability reporting.

CI secrets (maintainers)

GitHub Secret Purpose
RELEASE_KEYSTORE_BASE64 Base64-encoded .keystore file
RELEASE_KEYSTORE_PASSWORD Keystore password
RELEASE_KEY_ALIAS Key alias (androwatch)
RELEASE_KEY_PASSWORD Key password

Generate values with ./scripts/generate-release-keystore.sh.


GitHub automation

Only three workflow files to avoid run spam — each push/PR produces a single CI run with conditional jobs (cancel-in-progress cancels superseded runs).

Workflow Trigger Jobs / Purpose
CI Push main, PR, weekly, manual test-and-debug, codeql, dependency-review (PR), docs → Pages (main), scorecard
Community Issues, PRs, weekly labeler, greetings, auto-assign, triage, stale, release-drafter
Release Tag v*.*.* Signed multi-ABI APKs → GitHub Release
Dependabot Weekly 1 grouped Gradle PR + 1 grouped Actions PR

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Run ./gradlew test :app:assembleDebug
  4. Add KDoc for new public APIs
  5. Open a pull request

Android vs iOS (Loupe parity notes)

Topic Android (AndroWatch) iOS (Loupe)
App probing Package visibility limits (API 30+) Broader enumeration
Device ID ANDROID_ID (scoped) identifierForVendor
Install persistence EncryptedSharedPreferences probe Keychain-based

License

MIT © 2026 AndroWatch contributors


Inspired by Loupe · Built with Kotlin & Jetpack Compose

About

Android privacy audit app — see what your device reveals for fingerprinting (Loupe-inspired)

Topics

Resources

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages