Mobile
Driver Apps Mobile
A native Android app for delivery drivers — scan a parcel, capture proof of delivery with a photo and signature, and keep every drop tracked, even out in the field with no signal.
Overview
Logistics operations face critical challenges: manual manifest tracking causes delivery errors, paper-based proof-of-delivery creates accountability gaps, and a lack of real-time visibility causes delays. This driver app digitises the entire delivery workflow with native Android performance.
The challenge
Field drivers needed a reliable mobile solution that works offline and syncs seamlessly — handling manifest lifecycle, digital POD with photos and signatures, barcode scanning for check-in/out, and return-nota creation, all at enterprise-grade reliability.
The solution
Built with Kotlin and Jetpack Compose on MVVM. Manifest management with a 4-state lifecycle, digital POD with photo + signature, ML Kit barcode scanning, automated return nota, smart image compression, and an atomic design system for a consistent UI.
System design decisions
A delivery app lives in the hardest place for software to work: out in the field, on a phone, often with no signal at all. The interesting problems weren't on the screen — they were about staying reliable when the network isn't. Here are three of those decisions.
01Works with no signalLetting drivers work even with zero signal
PatternOffline-first — the phone's own database is the source of truth, with a background sync queue
The problemDrivers spend the day in basements, loading docks, and rural roads — exactly where signal disappears. If the app needs the internet for every tap, a driver gets stuck mid-delivery and can't even record that a parcel was handed over.
What I didSo the app reads and writes to a database on the phone itself — every action works instantly whether there's signal or not. Anything that needs to reach the server, like a confirmed delivery or an updated manifest, goes into a queue and sends itself automatically the moment a connection comes back.
The resultA driver never waits on a loading spinner and never loses work. They can finish a whole route offline, and everything quietly syncs up on its own once they're back in coverage.
02Proof that survivesMaking sure proof of delivery always makes it back
PatternOn-device image compression + a retrying upload queue made safe to repeat (idempotency)
The problemProof of delivery is a photo plus a signature — captured in exactly the spots where signal is worst. A full-size photo can be several megabytes; on a weak connection it fails to upload, and a naive retry could send the same proof twice or flood the server.
What I didSo each photo is shrunk on the phone before it ever leaves — small enough to squeeze through a weak connection, still clear enough to prove the drop. Uploads go through the same queue, retry on their own if they fail, and are tagged so the server simply ignores a duplicate if the same proof arrives more than once.
The resultEvery delivery comes back with its proof attached, even from the worst dead zones — without burning through the driver's data or ever counting the same delivery twice.
03No skipped stepsKeeping every parcel's history honest
PatternA state machine for the manifest lifecycle, with each transition checked before it's allowed
The problemA delivery moves through clear stages — assigned, picked up, delivered, returned. If the app let those jump around, you'd get parcels marked "delivered" that were never picked up, or two updates turning one manifest into a mess. Accountability falls apart.
What I didSo I modeled the manifest as a strict sequence where each stage can only move to the next valid one. The app simply won't let a driver mark something delivered if it wasn't picked up first, and the screen always shows only the actions that are actually possible right now.
The resultEvery parcel ends up with a clean, trustworthy history — no impossible states, no guesswork about what happened, and any dispute is settled by a record that can't have gaps.
Results & impact
100%Digital proof-of-delivery
Real-timeManifest status tracking
Dual-roleDriver & Security access
4-stateManifest lifecycle
ML KitBarcode scanning
AtomicDesign system
Tech stack
KotlinJetpack ComposeMaterial 3MVVMML KitCameraXGo