An incident workflow has to work under stress, limited connectivity, poor lighting, and interrupted attention. The goal is a complete, reviewable record without forcing the guard to choose between the app and the situation in front of them. Capture speed should be measured with real users, not promised as one universal number.
This post covers the technical design decisions behind incident reporting workflows in guard tour apps, from capture through sync to chain of custody.
Photo and video capture with embedded metadata
A photo can strengthen an incident record when its origin, handling, and context are preserved. EXIF fields are metadata supplied by software and can be edited. They should not be described as tamper-proof evidence or used as the only basis for authenticity.
When the guard captures a photo through the app, the following metadata should be written to the image file before it is saved to disk:
GPSLatitude,GPSLongitude, andGPSAltitudefrom the most recent location fix.DateTimeOriginalusing the device clock in UTC, plus a custom EXIF tag or XMP field containing the GPS-derived timestamp for cross-reference.- A custom field for
device_id(the unique identifier of the guard's phone) andguard_id(the authenticated user). - The
orientationtag so the image renders correctly regardless of how the phone was held.
On Android, ExifInterface can read and write supported image metadata. On iOS, Image I/O can create an output image with a metadata dictionary. Keep incident media in application-controlled storage when policy requires it, encrypt it appropriately, and upload an integrity hash and server receipt. Decide retention, export, and access with the organization's legal and privacy owners.
For video, the situation is more constrained. MP4 metadata support varies across devices. The practical approach is to store video metadata (GPS, timestamps, device info) in a sidecar JSON file linked to the video by a shared UUID, and include both in the upload payload.
Offline form submission queue
The incident report form must save locally before any network activity occurs. The guard taps "Submit" and the report is immediately persisted to the local database. From their perspective, the report is filed. The sync to the server happens in the background.
Each report record in the local database includes:
- A locally generated UUID as the primary key.
- All form fields: incident type, severity, description, guard ID, site ID.
- References to associated media files stored on disk.
- A
sync_statusfield:pending,uploading,synced, orfailed. - A
retry_countandlast_retry_atfor backoff tracking.
The background sync worker processes the queue in FIFO order. It uploads the structured report data first, receives a server-side report ID, then uploads associated media files referencing that ID. If media upload fails, the text portion is still on the server. The worker retries media uploads with exponential backoff: 30 seconds, 1 minute, 2 minutes, up to a maximum of 15 minutes between attempts.
Severity classification and escalation logic
Not every incident requires the same response speed. A propped-open door is different from an active intrusion. The app should present a clear severity picker, typically three or four levels:
- Low: Maintenance issues, minor policy violations. Syncs with the regular queue.
- Medium: Property damage, unauthorized access attempts. Queued for priority sync and generates a push notification to the supervisor on file.
- High: Break-ins, assaults, fire, medical emergencies. Triggers immediate sync attempt (bypassing the regular queue), sends push notifications to the supervisor and the client's emergency contact, and can optionally initiate a phone call to a dispatch center.
- Critical: Active shooter, bomb threat. Same as High, but also triggers alerts to law enforcement contacts configured for the site.
Escalation logic runs locally on the device. Even if the report cannot sync immediately, the app should attempt to send a lightweight notification payload (just the incident type, severity, location, and guard ID) through a secondary channel. A simple SMS to the supervisor's phone number is a reliable fallback when push notifications cannot be delivered due to connectivity issues.
GPS stamping and timestamp integrity
Every incident report needs a verified location and time. The challenge is that both can be manipulated on a compromised device.
For location, request a high-accuracy GPS fix at the moment the guard opens the incident form, not when they submit it. Use FusedLocationProviderClient on Android with PRIORITY_HIGH_ACCURACY, or CLLocationManager on iOS with desiredAccuracy set to kCLLocationAccuracyBest. Store the accuracy value (in meters) alongside the coordinates. A fix with 50-meter accuracy in an underground parking structure is less reliable than a 5-meter fix outdoors, and the operations center needs to see that distinction.
For timestamps, preserve the device wall clock, monotonic elapsed time for the current boot, location-fix time where present, a stable client event ID, and server receipt time after sync. Each has limits: users can change wall time, monotonic clocks reset across reboot, and location time is not proof of authorship. Use the combination to detect anomalies and preserve order, not to claim tamper-proof evidence.
On sync, the server records its own receive timestamp. If the gap between the report's creation time and the server receive time is unusually large (accounting for expected offline periods), the report is flagged for review.
Chain of custody for evidence
In security work, incident reports and their attached media sometimes end up in court proceedings or insurance claims. The chain of custody must be traceable from capture to storage.
Each media file gets a SHA-256 hash computed at the moment of capture, before any processing or compression. This hash is stored in the incident report record. When the file is uploaded to the server, the server independently computes the hash and compares it. If they match, the file has not been altered in transit or on disk. If they do not match, the file is flagged and the original is preserved for investigation.
The report's metadata trail should log every state change: created at (timestamp), submitted by (guard ID on device ID), synced at (timestamp), received by server at (timestamp), reviewed by (supervisor ID) at (timestamp). This audit log is append-only and stored separately from the editable report fields.
UI patterns that work with gloves
Security guards frequently work in conditions where standard mobile UI patterns fail. Winter gloves, nitrile gloves at medical sites, and rain-wet fingers all reduce touchscreen accuracy. The incident reporting UI must account for this.
Touch target sizing
Apple's Human Interface Guidelines recommend 44x44 point minimum touch targets. For gloved use, increase this to 56x56 points minimum. Buttons for severity selection and the submit action should be full-width, at least 56 points tall, with generous spacing between options. A guard wearing insulated gloves cannot reliably tap a 32-point radio button.
Reducing text input
Typing on a phone with gloves is painful and slow. Design the form to minimize free-text input. Use pre-populated incident type selectors (trespass, vandalism, fire, medical, access control, maintenance). Provide a set of quick-select description tags ("broken glass," "door propped open," "individual on premises," "water leak") that the guard can tap to build a report without typing. Reserve the free-text field for additional details, and make it optional.
Voice notes as an alternative
Voice recording is faster than typing, especially with gloves. Provide a prominent "Record Voice Note" button that captures audio using the device microphone. Store the audio file as M4A (AAC codec) for reasonable file size and broad compatibility. A 60-second voice note at 64kbps is approximately 480KB, small enough to sync even on weak connections. The voice note is attached to the report like any other media file, with the same hashing and metadata treatment.
One-handed operation
Guards often hold a flashlight, radio, or keys in one hand. Place all critical actions in the lower half of the screen, reachable with the thumb. The camera capture button should launch directly into the camera without navigating through menus. On Android, use ActivityResultContracts.TakePicture() for a single-tap photo capture flow.
Putting it together
A well-designed incident reporting workflow should take a guard from "something happened" to "report filed with photo evidence" in under 45 seconds. The form opens with the GPS fix already in progress. The guard selects an incident type with one tap, picks a severity with one tap, snaps a photo, and optionally records a voice note. They hit submit, the report is saved locally, and they are back on patrol. The sync, retry logic, hash verification, and escalation notifications all happen in the background without any further interaction from the guard.
DEVSFLOW Guarding designs offline incident-reporting and evidence workflows for field security operations. Review our security workforce engineering scope.