Skip to main content

Android App Overview

The Qlarr Android app is a native mobile application for offline-first survey data collection.

Repository

qlarr-surveys/android

Role in the System

The Android app focuses exclusively on running surveys. It downloads survey designs and resources from the Backend, runs them locally using its own copy of the Survey Engine (KMP), and syncs responses back when connectivity is available.

Surveys are rendered through an embedded WebView that loads the Frontend React app from bundled assets. A JavaScript bridge connects the WebView to native Android capabilities (camera, GPS, audio recording, barcode scanning).

Technology Stack

  • Kotlin with Jetpack Compose (Material 3)
  • Survey Engine (KMP) — survey logic and navigation (via JitPack)
  • Room — local SQLite database for surveys and responses
  • Retrofit + OkHttp — backend API communication with JWT interceptor
  • WorkManager — background response sync
  • Koin — dependency injection
  • Coil — image loading
  • ExoPlayer (Media3) — video playback

Key Features

  • Offline-First: Surveys are downloaded and cached locally. All responses are stored in Room and synced when connectivity is available.
  • Background Sync: WorkManager queues response uploads with automatic retry and backoff.
  • Media Capture: Camera photos (with compression), video recording, file selection, and barcode/QR scanning via native Android APIs.
  • Sensor Integration: GPS location tracking and background audio recording during surveys.
  • Guest Mode: Bundled example surveys that work without authentication for demo purposes.
  • Survey Versioning: Detects when a newer survey version is available on the server.

Offline Data Collection

The Android app is purpose-built for collecting survey data in the field where internet connectivity is unreliable or unavailable. The entire offline workflow is designed so that surveyors never lose data:

  1. Survey download — When connected, the app downloads survey designs, resources (images, media), and autocomplete data from the backend. Everything is cached locally in Room and on-device file storage.

  2. Local execution — Surveys run entirely on-device using the embedded Survey Engine (KMP). No server communication is needed during data collection. The engine generates the runtime.js state machine from the cached design and handles all navigation, validation, and conditional logic locally.

  3. Response storage — Each completed response is saved to the local Room database with all its values, timestamps, events (GPS coordinates, audio recordings), and file attachments (photos, videos, signatures). Responses are marked as isSynced = false until successfully uploaded.

  4. Background sync — When connectivity is restored, Android's WorkManager queues a sync job that uploads responses in the background. The sync process:

    • Finds all unsynced, submitted responses across all active surveys
    • Uploads file attachments first (photos, videos, audio recordings), checking each file against the server to avoid duplicate uploads
    • Uploads the response data (values, timestamps, navigation state, events)
    • Marks each response as synced and updates local response counts
    • Retries automatically with linear backoff if the upload fails
  5. Version tracking — The app tracks the published version of each survey. When a newer version is available on the server, it notifies the surveyor so they can update before collecting new responses.

For more details on configuring surveys for offline use, see Offline Mode.

Architecture

WebView Integration

The app uses a custom QlarrWebView that loads the React frontend from bundled assets. The WebView intercepts requests to serve survey resources locally:

  • Survey runtime (runtime.js) — generated by the KMP engine from the cached design
  • Survey resources (images, media) — served from local file storage
  • Response attachments — served from local storage

A JavaScript interface (Android object) exposes native capabilities to the web frontend:

MethodPurpose
navigate(body)Navigate survey questions
start()Start a new response
autoSaveValues(values)Auto-save progress and quit
capturePhoto(key, maxSize)Open camera for photo capture
captureVideo(key, maxSize)Open camera for video recording
selectFile(key, accepted, maxSize)Open file picker
scanBarcode(key)Open barcode/QR scanner
searchAutoComplete(uuid, query)Search autocomplete values

Data Flow

  1. User logs in (email/password or Google) — tokens stored in SessionManager
  2. Survey list is fetched from the backend and cached locally
  3. Survey designs and resources are downloaded and stored in Room + local files
  4. User opens a survey — QlarrWebView renders the React frontend
  5. The KMP engine handles navigation, validation, and conditional logic
  6. Responses are saved to Room with isSynced = false
  7. WorkManager uploads responses and file attachments in the background
  8. Response counts are updated after successful sync

Local Database

The Room database stores two entities:

  • SurveyDataEntity — survey metadata, cached design, publish version, feature flags (GPS, audio, timings), response counts
  • Response — response values, navigation state, sync status, language, timestamps, events (location, audio recordings)

Requirements

  • Android 7.0+ (API 24)
  • Google Chrome (for WebView rendering)