Developing a Mobile App for Inventory Management
Traditional inventory—printed forms, manual count, 1C verification in evening. Mobile app with barcode scanning changes process: employee scans barcode/QR, app immediately matches system, discrepancies recorded during scan. Sounds straightforward; implementation details determine real inventory speed.
Scanning: Built-in Camera vs Hardware Scanner
Built-in camera—most accessible. ML Kit Barcode Scanning (Android/iOS) via CameraX or AVFoundation decodes EAN-13, EAN-8, Code 128, Code 39, QR and dozen more. Works offline. Recognition delay on modern phones—100-200 ms.
But cases where camera can't deliver: warehouse with poor light, damaged labels, requirement to scan without raising item (distance reading). Here need Bluetooth scanners (Zebra CS60, Honeywell 1950g, Newland BS80) or industrial handhelds (Zebra TC21/TC26, Honeywell CT30). Connect as HID keyboard or via manufacturer SDK.
// Android: Zebra DataWedge integration via Intent
class ZebraDataWedgeManager(private val context: Context) {
private val DATAWEDGE_ACTION = "com.symbol.datawedge.api.ACTION"
private val SCAN_ACTION = "com.symbol.datawedge.data_string"
fun registerScanReceiver(onScan: (String) -> Unit): BroadcastReceiver {
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == SCAN_ACTION) {
val barcode = intent.getStringExtra("com.symbol.datawedge.data_string") ?: return
onScan(barcode)
}
}
}
context.registerReceiver(receiver, IntentFilter(SCAN_ACTION))
return receiver
}
}
Honeywell handhelds use similar broadcast via DataCollection SDK. Universal solution—abstract BarcodeScanner with implementations: CameraBarcodeScanner, ZebraBarcodeScanner, HoneywellBarcodeScanner. Config chosen at startup by device type.
Architecture: Offline-First Mandatory
Warehouse—unstable WiFi zone. Some areas have no coverage. App must work fully offline: load inventory list before start, record scans locally, sync on connection restore.
@Entity(tableName = "inventory_items")
data class InventoryItem(
@PrimaryKey val sku: String,
val name: String,
val expectedQuantity: Int,
val unit: String,
val location: String,
)
@Entity(tableName = "scan_records")
data class ScanRecord(
@PrimaryKey(autoGenerate = true) val id: Long = 0,
val sku: String,
val scannedQuantity: Int,
val scannedAt: Long = System.currentTimeMillis(),
val syncStatus: SyncStatus = SyncStatus.PENDING,
val userId: String,
)
enum class SyncStatus { PENDING, SYNCED, CONFLICT }
WorkManager launches sync on network appearance—NetworkType.CONNECTED constraint. On conflict (other employee scanned same SKU)—server returns conflict, app shows both values and asks manual resolution.
Serial Number Search and Manual Entry
Not every item has readable barcode. Manual SKU entry with autocomplete from local database—mandatory feature. SKU list loaded beforehand into FTS4/FTS5 Room table for fast full-text search by name.
Serial numbers—separate story. Position may require scanning each copy individually (laptops, printers, tools). "Serial accounting" mode: app waits N serial number scans for one position, shows progress 3/10 serial numbers entered.
Discrepancy Report
After inventory complete—discrepancy report: which items not found, which surplus, where actual vs plan mismatch. Formed locally, sent to server or exported to PDF via PdfDocument API (Android) / PDFKit (iOS).
1C integration via REST API (1C HTTP service) or intermediate service. Data format—JSON or XML per 1C-developer agreement. Upload inventory document back to 1C—standard final step.
Developing inventory app with offline work, Camera ML Kit, report export: 5-7 weeks. Zebra/Honeywell TSD support, serial accounting, bidirectional 1C integration: 10-14 weeks. Cost individually quoted.







