CrisisLens is a standalone Android app for emergency disaster responders. A responder photographs a scene — an injury, flood, collapsed structure, blocked road. The app reads live GPS coordinates from the device, analyzes the image using Gemma 4 E2B running entirely on-device via LiteRT-LM, and compresses everything into a structured JSON payload of 200 bytes or less. That payload is small enough to transmit over LoRa radio or Bluetooth mesh networks (e.g. Meshtastic) that cap at roughly 228 bytes per packet.
There is no backend. No server. No internet. The phone IS the entire system.
Cell networks go down in disasters. LoRa and Meshtastic mesh networks survive, but they are data-only and cap at ~228 bytes per packet — they cannot send images. Voice radio channels become saturated with 20+ teams; details get garbled and nothing is logged or parsed automatically. Structured reporting protocols like METHANE require trained responders, and volunteers or civilians have no equivalent. Visual information — injury type, structural damage, road blockage — cannot be transmitted in any structured way. Model-generated location descriptions like "urban ruins" are useless in a disaster zone where everywhere looks the same.
CrisisLens bridges this gap: GPS + image → on-device AI → 200-byte georeferenced payload → ready to relay over any primitive network.
- A responder opens CrisisLens and takes a photo of the scene (or selects one from the gallery).
- Device GPS is acquired with a 10-second timeout; if unavailable the app continues anyway with "GPS unavailable".
- Gemma 4 E2B (LiteRT-LM) runs inference on-device — no cloud, no API keys. The app attempts GPU acceleration first and falls back to CPU automatically when dispatch libraries are missing.
- The raw JSON output is postprocessed: location is injected from actual GPS (never trusted from the model), keys are reordered, enums are normalized, and the payload is trimmed to 200 bytes at word boundaries (desc first, then act) so a single LoRa/Meshtastic packet can carry it.
- The final payload looks like:
{"loc":"12.8406,77.6784","type":"flood","sev":"crit","inj":2,"desc":"Road submerged 3ft","act":"avoid south entry","conf":"high"}
- The app does NOT include model files in this repository. You must download
a compatible
.litertlmmodel onto the device yourself. - The app injects GPS coordinates into the final payload and enforces a 200-byte budget.
- The app attempts GPU/accelerator dispatch when available and falls back to CPU automatically.
Pre-built APKs are available from GitHub Releases.
Download the latest .apk and sideload it onto your device.
- Install the APK on your Android device (or build from source — see Build & run).
- On first run, accept the onboarding prompts for location permissions and optionally grant All Files Access if you want to place the model under Downloads and use an absolute path.
- Provide a model in one of two ways:
- Settings → Model Path: paste an absolute path to a
.litertlmfile on the device (recommended for large models stored on SD card / Downloads). - Settings → Browse: pick a
.litertlmfile from the system picker; the app copies it to internal storage (context.filesDir/selected_model.litertlm).
- Settings → Model Path: paste an absolute path to a
- Use the camera or pick an image, then tap Analyze. The app runs inference
and presents a compact JSON payload with a byte-count badge (green ≤ 200, red
200).
- gemma-4-E2B-it.litertlm — generic E2B build (recommended for most Android
devices). This file is large (~2.6 GB) and should be downloaded directly to
the device (e.g. into
/sdcard/Download/). - Device-specific builds (intel / qualcomm) exist — use the matching build for best performance on that hardware.
Models are available from the LitERT community and Hugging Face. Example (not bundled): https://huggingface.co/litert-community
ACCESS_FINE_LOCATION/ACCESS_COARSE_LOCATION— used to obtain a GPS fix with a 10-second timeout. If unavailable, the location field becomes "GPS unavailable" and analysis continues.MANAGE_EXTERNAL_STORAGE(All Files Access) — optional; makes it easier to use very large model files in Downloads without copying into app storage. If you do not grant it, use the Browse flow to copy a model into app internal storage.
Project: crisislens-android/ (Android Studio / Gradle project).
Smoke-test on device:
- Build and install the APK:
./gradlew assembleDebug adb install -r app/build/outputs/apk/debug/app-debug.apk - Open the app, complete onboarding, and provide a model path.
- Take a photo and tap Analyze. Verify the UI shows a JSON payload with byte count ≤ 200, and the history screen records the scan.
- Create a new repository on GitHub.
- Run from the repo root:
git init git add . git commit -m "Initial CrisisLens standalone Android app" git branch -M main git remote add origin https://github.com/<your-org>/CrisisLens.git git push -u origin main
- Do not add
.litertlmmodel binaries to the repository — they are large and should be downloaded on-device by each user. - The app persists the last 20 scans locally and supports export/share from the history screen (long-press to delete, tap to copy, Export button to share).
- The system prompt that governs Gemma 4's output schema lives in
crisislens-android/app/src/main/java/com/crisislens/engine/StandaloneEngine.kt(private valSYSTEM_PROMPT). It is the sole source of truth for the JSON schema understood by the enforcer.
MIT — see LICENSE.
This repository contains app source code only. Model files you download may
carry separate licenses; check the distributor's terms and do not redistribute
large model binaries in this repo.