Imagine you receive a batch of temperature sensors, each needing to be bound to a user account. Manual entry of a 16-character serial number results in 30% errors. Bluetooth discovery takes a minute. QR pairing solves both: scanning takes 2 seconds, verification takes 8, total 10–15 seconds per device. Our team has implemented over 50 such solutions for IoT projects, reducing support costs by an average of 40%. We have been working with mobile platforms for over 10 years and know all the integration nuances. This allows us to optimize the budget and reduce support load.
Problems That QR Pairing Solves
Without QR pairing, users face serial number entry errors (up to 30% incorrect entries), long Bluetooth pairing (up to a minute), and confusion with multiple devices. QR pairing eliminates these: scanning takes seconds and verification is automatic. We guarantee the process is intuitive even for inexperienced users. One of our smart home solutions cut support tickets by 60% in the first month.
How We Do It: Choosing QR Format and Tools
First, we decide what to encode in the QR. Options:
| Format | Example | Features |
|---|---|---|
| Serial number | SN:ABC12345 |
Simple, no protection |
| Claim token | eyJhbGci... |
One-time, secure |
| Matter code | MT:Y.K90SO527JA0648G00 |
Standardized, self-contained |
| URL scheme | myapp://pair?id=ABC&token=xyz |
Allows deep link, convenient |
For custom devices we often use a URL scheme: it can be opened by the system camera without a browser. For Matter – strictly per the Matter specification.
Why ML Kit Is Better Than Other Libraries for Android?
ML Kit Barcode Scanning is the best choice for Android: it works offline, supports QR, DataMatrix, PDF417. Unlike ZXing, it does not require separate integration and is updated via Google Play Services. Example:
val options = BarcodeScannerOptions.Builder() .setBarcodeFormats(Barcode.FORMAT_QR_CODE) .build() val scanner = BarcodeScanning.getClient(options) // In CameraX ImageAnalysis scanner.process(inputImage) .addOnSuccessListener { barcodes -> barcodes.firstOrNull()?.rawValue?.let { qrData -> viewModel.onQrScanned(qrData) // Stop the camera after first successful scan cameraProvider.unbindAll() } } Important: stop the camera after the first scan – otherwise ML Kit will be called multiple times for the same QR. Debounce via AtomicBoolean isScanning or via Flow.distinctUntilChanged().
How DataScannerViewController Simplifies Development on iOS?
On iOS 16+ we use DataScannerViewController – it replaces custom AVCaptureSession, has built-in highlighting UI. Official documentation DataScannerViewController describes all details. Example:
// iOS 16+ – the easiest path let scanner = DataScannerViewController( recognizedDataTypes: [.barcode(symbologies: [.qr])], isHighlightingEnabled: true ) scanner.delegate = self try? scanner.startScanning() // delegate func dataScanner(_ dataScanner: DataScannerViewController, didTapOn item: RecognizedItem) { if case .barcode(let barcode) = item { handleQrData(barcode.payloadStringValue ?? "") } } On older iOS versions we use Vision + AVCaptureSession – it is 2x faster than third-party libraries in recognition speed.
Scanning Methods Comparison by Platform
| Platform | Library | Minimum Version | Features |
|---|---|---|---|
| Android | ML Kit Barcode Scanning | Android 5.0 | Offline, Google Play Services, QR+DataMatrix+PDF417 |
| iOS 16+ | DataScannerViewController | iOS 16 | Built-in UI, highlighting, delegate |
| iOS <16 | Vision + AVCaptureSession | iOS 11 | Faster than third-party, custom UI |
QR Data Parsing and Validation
QR data must be parsed securely – the user might scan any QR, not just the device one:
data class DeviceQrPayload( val deviceId: String, val claimToken: String, val productType: String ) fun parseQrCode(raw: String): DeviceQrPayload? { return try { // URL format: myapp://pair?id=ABC&token=XYZ&type=sensor val uri = Uri.parse(raw) if (uri.scheme != "myapp" || uri.host != "pair") return null DeviceQrPayload( deviceId = uri.getQueryParameter("id") ?: return null, claimToken = uri.getQueryParameter("token") ?: return null, productType = uri.getQueryParameter("type") ?: "unknown" ) } catch (e: Exception) { null } } Return null on any parsing error – no crash. Show the user "Unrecognized QR code".
How to Ensure Security During Pairing?
Protection against counterfeit QR codes is key. The claim token is one-time, generated during manufacturing, stored in the database. After the first successful claim it is invalidated. Additionally, we verify the scheme and host in the URL, use HTTPS for all requests. This prevents man-in-the-middle attacks and eliminates device theft.
Claim to Account: API Call
After parsing the QR – make a request to the server to bind the device to the user account:
POST /api/devices/claim { "device_id": "ABC12345", "claim_token": "eyJhbGci...", "device_name": "Kitchen temperature sensor" } The claim token is one-time, generated during manufacturing, stored in the database. After the first successful claim – it is invalidated. This protects against someone else's QR ending up with a different user.
Matter QR is handled differently: Google Home SDK or Apple HomeKit Framework decode the setup payload and perform the commissioning process. The app does not need to make a backend call – the Matter platform handles it.
UX After Scanning
Do not show an empty loading screen. Once the QR is recognized – show the device data (type, serial number, brief description) and an "Add" button. The user confirms. Only then – claim to account. This protects against accidental scanning: the user sees what is being added and can cancel.
What's Included in QR Pairing Development?
- QR code schema design (format selection, claim token generation)
- Scanning implementation for iOS and Android (ML Kit / Vision / DataScannerViewController)
- Backend integration (claim API, token validation)
- Matter configuration for compatible devices
- Documentation and team training
- Testing on real devices
- Post-launch support
Typical Implementation Mistakes
- Not stopping the camera after the first scan – multiple triggers.
- Not checking for null when parsing – app crash.
- Using HTTP instead of HTTPS – vulnerability for token interception.
- Not showing confirmation before claim – accidental addition.
- Forgetting to invalidate the claim token – possibility of re-claim.
Timeline and Assessment
Implementation of QR pairing with account claim: 1–2 weeks. Free scope assessment. Contact us and we will prepare a commercial proposal for your project.
Get a turnkey solution that reduces device connection time by 3x and cuts input errors. Order QR pairing development today – our engineers will advise you on all technical details.







