Hardware and Local Testing
Countertop Supermarket Lane
This should be the primary reference setup for supermarkets.
- touch POS terminal or all-in-one countertop PC
- fixed barcode scanner
- 80mm receipt printer
- printer-driven cash drawer
- browser kiosk running
POS Cashier Web
Mobile / Secondary Kit
Use this for supervisors, queue-busting, and smaller merchants.
- Android phone
- optional Bluetooth scanner
- optional Bluetooth, USB-host/OTG or private-LAN ESC/POS printer
- POS Android app
The Android app now includes a transport router plus generic Bluetooth Classic SPP, USB-host printer-class bulk OUT and private-LAN raw-TCP ESC/POS adapters. It offers 32-character/58 mm and 48-character/80 mm profiles, stores both the selected device and its transport locally, marks every reprint, and retains failed jobs in a Room-backed queue for operator retry. Checkout and the spool depend only on the country- and vendor-neutral printer contract. An integrated handheld printer can therefore be added as a small status-aware vendor adapter without adding Ciontek, Sunmi, Kenya or another market concept to sale code. Discovery isolates adapter failures, so missing Bluetooth permission cannot hide a connected USB, configured network or installed built-in printer adapter.
The generic built-in-printer boundary is now implemented. It advertises no device when a build has no licensed bridge, maps ready/busy/paper-out/cover-open/ offline states into the common contract, sanitizes private SDK failures and distinguishes exact-job completion from accepted-but-unconfirmed submission. Eight focused tests cover those guarantees. The exact Ciontek, SUNMI or other vendor AAR bridge is still conditional on the purchased model, firmware and SDK.
The app accepts rapid keyboard-wedge barcode input from a real external HID device. A second adapter accepts a configurable foreground Android broadcast from a managed scanner service. A third, hardware-independent fallback uses the camera and a bundled on-device decoder. It deliberately does not advertise a camera or a merely configured broadcast as a working scanner: each software adapter becomes ready only after its permission/configuration requirements and a valid test scan. Terminal activation and the periodic sync worker publish country-neutral battery, network, printer and scanner readiness to the POS service. A configured printer is only reported ready after its selected adapter passes a real check: bonded-device visibility, enabled Bluetooth and permission for SPP; temporary Android device permission and a successful interface claim for USB; or a bounded TCP connection to a private resolved address for a network printer.
USB-host ESC/POS printer
Use an Android terminal that advertises USB host/OTG support. Connect only a
printer whose USB descriptor exposes printer class 7 at the device or
interface level and a bulk OUT endpoint. Open Settings → Receipt printer,
select Find Bluetooth and USB printers, choose the device, and approve the
Android access dialog. Permission is temporary and ends when the printer is
disconnected. The app stores only an opaque local identity derived from the
vendor/product pair and Android device path; it does not persist a serial
number. If exactly one same-model printer reconnects under a new path, it is
resolved safely. Multiple indistinguishable same-model devices require the
operator to select the intended printer again.
The adapter claims only the qualified printer interface, writes bounded 16 KiB
chunks to its bulk OUT endpoint, and then releases and closes the connection.
It never inspects mass-storage, HID, card-reader or vendor-class devices. USB
bulk output cannot portably confirm paper completion, so a full write remains
SUBMITTED_UNCONFIRMED. Any timeout or partial write requires paper inspection
and is not automatically retried. Test the exact OTG cable, powered hub, charger
path and full-shift power behavior; many phones cannot charge while acting as
the USB host. This follows the official Android USB host
contract and
UsbManager permission lifecycle.
Local-network ESC/POS printer
Use a DHCP reservation or static private address for the printer. In Settings
→ Receipt printer, enter the hostname or IPv4 address and the device's raw
ESC/POS TCP port, commonly 9100; do not enter an HTTP administration URL or
IPP port. Save it, choose the correct paper width and print a test receipt.
The adapter resolves the hostname and refuses any result that is not loopback,
link-local, private/site-local, or IPv6 ULA. It uses a 3-second connect bound and
a 12-second whole-print bound. A successful socket write is one-way transport
acceptance, not proof of paper output. If a failure occurs after writing starts,
the app does not try another address or mark the job retryable because the
printer may already hold a partial or complete receipt. Place printers on a
dedicated merchant LAN/VLAN; raw port 9100 is normally unencrypted and must
not be exposed to the public internet.
Camera barcode fallback
Open Checkout → Scan with camera on an authenticated POS terminal. Android
requests CAMERA permission only when this action is selected. CameraX binds
the rear camera to the foreground checkout lifecycle with keep-only-latest
analysis, and the bundled ML Kit model supports Code 128/39/93, Codabar,
EAN-13/8, ITF, UPC-A/E, QR, PDF417, Aztec and Data Matrix without downloading a
model. The analyzer closes every frame, returns only a bounded validated value
to the existing catalog lookup path, and stores or uploads no image.
Readiness has three independent gates: camera present, permission granted and a successful valid decode in the current app process. This makes a phone or tablet useful for the low-cost pilot without claiming the camera is equivalent to a high-throughput scan engine. Physical lane testing must still qualify focus speed, low light, damaged labels and repeated scans. See CameraX image analysis and ML Kit barcode scanning.
Integrated scanner intent contract
Open Settings → Integrated scanner broadcast and configure the contract provided by the handheld vendor. The included DataWedge-compatible starting profile is:
| Setting | Value |
|---|---|
| Delivery | Broadcast intent |
| Action | com.emali2.pos.SCAN |
| Category | android.intent.category.DEFAULT |
| Barcode data extra | com.symbol.datawedge.data_string |
| Symbology extra | com.symbol.datawedge.label_type |
| Target package | com.emali2.pos |
The action, category and both extra keys are runtime configuration, not POS domain constants. A Ciontek, Sunmi, Zebra or other managed device can therefore use its documented names without adding a country-specific checkout path. The receiver exists only while an authenticated POS activity is in the foreground, accepts the exact configured action/category, rejects unsafe or oversized values, permits the GS1 group separator, and suppresses repeated delivery of the same scan within 750 milliseconds. It does not persist barcode values in Settings. The pure processor suite and a package-targeted Android 14 instrumentation test cover this contract; the selected handheld's real scanner service remains the physical acceptance gate.
For Zebra DataWedge, configure Component Information for package
com.emali2.pos and enable its app-signature check when the device supports it.
Android warns that exported context receivers can otherwise receive broadcasts
from other installed applications, so enable this bridge only on a managed or
dedicated POS device with an approved scanner service. An incoming scan can
only initiate catalog lookup/basket entry; it cannot authorize payment,
refund, supervisor override or drawer operation. See Zebra Intent Output
and Android broadcast security guidance.
Kenya pilot procurement (country-neutral product)
Recommended local-first setup:
- existing Samsung NFC phone
- second low-cost Android phone
- wireless or Bluetooth 2D barcode scanner
- Bluetooth receipt printer
- laptop for POS Backoffice and POS Cashier Web
For supermarkets specifically:
- favor countertop hardware over handheld SmartPOS
- keep handheld SmartPOS for mobile use cases, not the main checkout lane
Handheld with built-in printer: current Kenya cost
Prices and stock were rechecked on 24 July 2026. These are Kenya pilot
procurement observations only: neither the Android hardware contract nor the
Emali2 POS application requires KRA, eTIMS, M-PESA or any other country-specific
service. The recommended first
integrated-printer evaluation unit is the Ciontek CS30 at KSh 23,000, but
only after an in-person acceptance demo. The local listing identifies an
Android 14/11 unit; Ciontek's OEM specification lists Android 14, 2 GB RAM,
16 GB storage, a 58 mm printer at 70 mm/s, and an optional Zebra/Symbol 4710 2D
scanner. More importantly for the current Emali2 build, Ciontek documents a
Bluetooth printer mode that accepts ESC/P commands. That makes the CS30 the
best candidate for using the existing generic printer bridge before building a
vendor AAR integration. Ciontek says its SDK and technical support are available
after a sample order, while a publicly available CS30Pro integration guide
describes an older Android 10-era PosApiHelper/AIDL contract. That older guide
is useful only for evaluating the shape of a future adapter; it is not
acceptance evidence for the current Android 14 CS30 firmware. Obtain the exact
sample's matching SDK, license terms, demo and status-code contract before
compiling vendor binaries into Emali2.
The refreshed seller pages put mainstream integrated-printer handhelds at about KSh 23,000–33,000. They list the CS30 in stock at KSh 23,000; an H10S with Android 13, 2 GB/16 GB, a built-in 58 mm printer and a stated free SDK at KSh 25,000 excluding VAT; an Android 12 NB55 with 3 GB/16 GB, NFC, a stated 1D/2D scan engine and 58 mm printer at KSh 28,000; generic marketplace units at KSh 23,990–32,999; the YCP-58 at KSh 5,000; and the Deli E14952 at KSh 8,500. The H10S and NB55 are the more current-OS comparisons, but a listing or “free SDK” claim is not enough: obtain the actual AAR/API, license and a paper-out/status demonstration before purchase. These are web offers, not quotations; confirm VAT, delivery, warranty and the exact SKU in writing before payment.
| Pilot option | Listed price | Qualification decision |
|---|---|---|
| Ciontek SmartPOS CS30 | KSh 23,000 | First integrated evaluation choice. Require Android 11 or newer, signed-APK installation and a successful ESC/P or supplied-SDK print demo |
| H10S Android 13, 2 GB/16 GB, 58 mm printer | KSh 25,000 ex VAT | Modern-OS comparison choice. Require delivery of the advertised SDK, third-party APK installation, exact printer status behavior and scanner-option confirmation |
| NB55 Android 12, 3 GB/16 GB, NFC, stated 1D/2D scanner and 58 mm printer | KSh 28,000 | Scanner-equipped comparison choice. Require the exact scan engine, broadcast/SDK contract, printer status API and signed-APK installation to be demonstrated |
| Generic marketplace Android terminal with 58 mm printer | KSh 23,990–32,999 | Marketplace comparison only; no dependable OEM, SDK or firmware assurance in the listings |
| Comstore 4 GB/32 GB, 58 mm printer | KSh 25,000 | Reject as the primary new pilot unit: the current listing identifies Android 10, below the Android 11 floor; its 5 MP camera is not a qualified scan engine |
| Ciontek CS50 or 3 GB CS30G | KSh 26,000 | Alternative after the exact SKU, Android build and hardware SDK are confirmed |
| SUNMI V2s | KSh 35,800–38,000 locally | Better-documented 58 mm/80 mm/s OEM platform, but the local listings conflict: one says Android 11 with 2 GB/16 GB and another says Android 7.1, while SUNMI's current T5940 standard specification is Android 12 Go with 1 GB/8 GB. Buy only the exact demonstrated SKU |
| SUNMI V2 Pro | KSh 43,000 ex VAT | Do not select for a new pilot: the current local listing is in stock with a built-in 58 mm printer but identifies Android 7/7.1 |
| SmartPOS H5, Android 8.1, 1 GB/8 GB | KSh 19,999 | Compatibility testing only; technically above API 26 but too old and constrained for a new production pilot |
| Fingerprint CS30G/CS50 variants | KSh 28,000–30,000 | Do not pay the premium until fingerprint is a confirmed Emali2 workflow |
Sources: AndroidPOSKenya CS30 listing, Ciontek CS30 OEM specification, Ciontek SDK/support FAQ, Viva CS30 SDK integration page, public CS30Pro SDK guide (older Android 10 reference only), Jumia CS30 listing and Android POS comparisons, TDK H10S listing, Carl & Kyle NB55 listing, Jumia Android POS price comparison, Nebula Comstore listing, SUNMI V2s OEM specification, and Kenya SUNMI V2s listings from TechHub and Sawa Gadgets, plus Fgee's SUNMI V2 Pro listing.
The V2s model name alone is therefore not an acceptance criterion. Record the model/variant identifier, OS build, RAM/storage, GMS state, scan-engine option and printer API observed on the actual unit in the purchase acceptance report.
Printer delivery confidence
The Android print queue now distinguishes device confirmed from
transport accepted, unconfirmed. A generic Bluetooth SPP, USB bulk OUT or raw-TCP socket can prove
that Android flushed the ESC/POS bytes, but it normally cannot prove that the
printer had paper or completed the receipt. Such a job is stored as
SUBMITTED_UNCONFIRMED, receives no printedAt value and is never silently
auto-retried. The operator must inspect the paper output; any new attempt is an
explicit marked reprint. Only a qualified bidirectional vendor SDK or another
status-capable transport may return device-confirmed completion.
The app-side BuiltInPrinterBridge now enforces this boundary without carrying
any brand or country rule in checkout. A bridge is not included in the generic
APK: it must be compiled only for the exact accepted device SDK and must map all
private status/error values to the closed, sanitized POS model.
This is a selection advantage for a vendor SDK that exposes truthful paper, cover and completion status, but it does not block the KSh 23,000 CS30 evaluation: its documented Bluetooth ESC/P mode can exercise the current country-neutral bridge with the safer unconfirmed outcome.
The app now persists BLUETOOTH_SPP, USB, NETWORK or VENDOR_SDK with the
selected printer and routes every print, readiness check and guarded drawer
request to that exact adapter. A later CS30 adapter must translate exact-firmware
initialization, print-start, paper-out, cover, temperature/voltage and completion
statuses into the shared failure and delivery-confidence model. It may return
DEVICE_CONFIRMED only after the exact device reports successful completion;
submitting a command to an SDK is not sufficient.
Recommended purchase order
Do not order two integrated terminals yet. Ask AndroidPOSKenya to reserve one CS30 and perform the following acceptance demo before payment:
- Show the Android version, RAM/storage, model number and Google Play/GMS state.
- Install the signed Emali2 debug/UAT APK without seller-controlled kiosk or application allow-list restrictions.
- Pair or expose the built-in printer in ESC/P Bluetooth mode and print the Emali2 test receipt. If that mode is unavailable, supply the matching AAR, API documentation and sample application before purchase.
- Print at least 25 receipts, exercise paper-out, reboot, sleep/wake and reconnect, and show that a failed job can be retried as a marked reprint.
- Identify whether the unit includes the optional professional 2D engine. A camera alone is not scanner qualification. If the engine is present, supply its Android intent or SDK contract, configure the action/category/extra keys in Emali2, and scan EAN-13, Code 128 and an on-screen QR code into the app.
- Confirm warranty length, return terms, replacement printer heads, battery, charger and 58 × 40 mm paper availability on the invoice.
Capture the exact evidence and purchase decision in the POS Hardware Acceptance Report. Do not accept a family name, another app's print demo or a marketing compliance badge in place of the checks in that report.
The lowest-risk lab bundle is therefore:
| Item | Budget |
|---|---|
| One conditional Ciontek CS30 | KSh 23,000 |
| YCP-58 Bluetooth/USB fallback printer | KSh 5,000 |
| Deli E14952 wired 1D/2D scanner | KSh 8,500 |
| Five 57 × 35 mm thermal rolls | about KSh 500 |
| Hardware subtotal | about KSh 37,000 |
Delivery, USB-C OTG adapter, SIM/data and a spare charger are extra. The fallback printer and scanner keep physical UAT moving if the integrated printer or optional scan engine needs a vendor adapter. For the absolute cheapest peripheral-only proof with an existing Android phone, use the YCP-58 and a KSh 4,000 wired 1D HID scanner: approximately KSh 9,000, plus paper and an OTG adapter. Current peripheral sources: YCP-58 and Nebula scanner/printer catalogue.
Fixed-lane peripheral cost in Kenya
These prices exclude the PC, touch display or tablet that runs Cashier Web. Listings do not always use the same VAT or delivery treatment, so compare final written quotations rather than adding unlike prices.
| Peripheral | Current listed price | Pilot use |
|---|---|---|
| YCP-58 Bluetooth/USB 58 mm printer | KSh 5,000 | Mobile receipt proof, not the preferred busy-lane printer |
| RD-P58E Bluetooth 58 mm printer | KSh 5,500 | Second portable-printer comparison model |
| CK710 80 mm USB/Ethernet printer | KSh 9,500 (out of stock) | Price comparison only; do not include it in the current purchase order |
| E-POS ECO250 USB/serial/Ethernet printer | KSh 14,500 | Better-connected fixed-lane candidate; verify cutter and drawer port |
| Wired USB HID 1D scanner | KSh 4,000 | Cheapest physical EAN/Code 128 proof |
| Deli E14952 wired 1D/2D scanner | KSh 8,500 | Recommended low-cost QR and product-barcode proof; confirm Android HID behavior in the seller demo |
| Honeywell omni-directional 1D/2D USB kit | KSh 15,339.84 | Better-supported fixed-lane comparison |
| RJ11 cash drawer | KSh 6,500 locally | Connect through a compatible receipt printer, not directly to Android |
A currently buyable low-cost fixed-lane peripheral kit is approximately KSh 29,500: the ECO250, Deli 1D/2D scanner and KSh 6,500 drawer. The same printer with the Honeywell scanner and drawer is approximately KSh 36,340, excluding the cashier computer/touch display, tax treatment, delivery and consumables. Prices come from the Nebula POS catalogue, its ECO250 listing, CK710 stock listing, and AndroidPOSKenya catalogue; obtain a written final quotation because web prices and stock can change.
Kenya is only the first procurement and certification reference. Hardware, tender and fiscal adapters remain selected through the store operating profile; the POS domain does not call a tax authority or mobile-money brand directly.
Cash Drawer
Cash drawers are recommended for real cash lanes, but not required for early software development.
Best approach:
- use a printer-driven RJ11 or RJ12 drawer
- trigger drawer open from the receipt printer
- only open on:
- cash sale
- cash refund
- supervisor-approved no-sale
Local Testing Matrix
POS Cashier Web
- keyboard wedge barcode input
- product lookup and basket creation
- mixed tender capture
- receipt print popup
- session recovery by terminal
POS Android
- rapid external HID keyboard-wedge scan; slow ordinary typing must not be mistaken for a barcode
- revoke camera permission, select Scan with camera, grant it at runtime, scan a valid Code 128/EAN/QR label and confirm exactly one catalog lookup/basket addition
- verify Settings changes from permission/validation pending to camera scanner Ready, then restart the process and confirm a fresh validation is required
- configure the handheld's explicit target package, scan action, category and decoded-data extra under Integrated scanner broadcast
- confirm the intent bridge says Listening; test required until a real scan is received, then changes to Validated without showing or storing the scan value in Settings
- send the same broadcast twice inside 750 milliseconds and confirm only one catalog lookup/basket addition occurs
- background or sign out of the POS app and confirm scanner broadcasts no longer reach checkout
- local image rendering
- offline-first session and receipt behavior
- handheld checkout UX
- pair the printer in Android system settings
- grant
BLUETOOTH_CONNECTandBLUETOOTH_SCANon Android 12+ - select the device under Settings → Receipt printer
- select the 58 mm/32-column or 80 mm/48-column profile and print a test before using sale receipts
- print a test receipt, then a marked reprint from Receipts & Refunds
- power the printer off, confirm the job remains visible, power it on, and use Retry print queue
- after a successful Bluetooth send, confirm the app says output is unconfirmed and does not fabricate a printer-completed timestamp
- verify paper width, accented customer names, QR/barcode support, cut behavior, paper-out handling, and reconnect on the actual model
- enroll the terminal and verify its first heartbeat reports the real network, battery, printer transport and scanner readiness
- leave periodic sync enabled and verify terminal health refreshes approximately every 15 minutes
- confirm a camera-only device without permission/validation and an unvalidated broadcast profile are not marked scanner-ready
- with the drawer empty and closed, connect it through the printer, explicitly enable drawer testing, and send one test pulse
- confirm drawer testing starts disabled after selecting a different printer and that drawer pulses never enter Retry print queue
The generic adapter has an unknowable physical-delivery boundary: a Bluetooth
disconnect after the printer accepts bytes can leave paper output uncertain.
Android therefore records transport acceptance as unconfirmed and does not
auto-retry it. Operator retries are always labelled REPRINT COPY. Do not
auto-retry an unmarked fiscal original through this bridge.
POS Backoffice
- inventory onboarding
- item images
- loyalty and engagement configuration
- branch operations and reporting
Pre-Pilot Additions
- countertop printer and cash drawer
- customer-facing display if needed
- dedicated lane touch terminal
- bank-approved PDQ only when card-present integration starts