QR / Barcode Scanner
Scan QR codes and barcodes
Overview
Opens the camera to scan a QR code or barcode and returns the result. Both Android and iOS use the same JS API and the same response format.
| Feature | Android | iOS |
|---|---|---|
| QR code scan | ✓ (Android 7.0+) | ✓ |
| Barcode scan | ✓ (Android 7.0+) | ✓ |
Supported Plan: Basic and above (requires the qr license feature)
Prerequisites
QR scanning uses the camera permission. Configure it for the platform you target.
Android
The camera permission ships commented out in AndroidManifest.xml. Uncomment it to enable QR scanning.
<uses-permission android:name="android.permission.CAMERA" />iOS
Add the camera usage description to your Info.plist.
<key>NSCameraUsageDescription</key>
<string>Camera access is required to scan QR codes and barcodes.</string>Usage
Call unveilyBridge.qr.scan(cb) to open the scanner. cb is a callback function-name string that receives the result. Omit it to use the default 'onQRResult'.
// Pass an explicit callback name
window.unveilyBridge.qr.scan("onQRResult");
// Or use the default callback (onQRResult)
window.unveilyBridge.qr.scan();
function onQRResult(result) {
if (result.cancelled) {
return; // User closed the scanner
}
if (result.error) {
console.error("Scan failed:", result.error); // Error or plan not supported
return;
}
console.log("Scanned content:", result.text); // Scanned string
console.log("Format:", result.format); // e.g. "QR_CODE", "EAN_13"
console.log("Type:", result.type); // Content type (e.g. "URL", "TEXT")
}The result is delivered as an already-parsed JS object. You do not need to call JSON.parse().
Response Structure
The callback receives one of these three object shapes.
{ "text": "https://example.com", "format": "QR_CODE", "type": "URL" }{ "cancelled": true }{ "error": "..." }| Field | Description |
|---|---|
text | The scanned string (on success) |
format | Barcode symbology — QR_CODE, EAN_13, EAN_8, CODE_128, CODE_39, ITF, DATA_MATRIX, PDF_417, AZTEC, etc. |
type | Content type classification (e.g. URL, TEXT) |
cancelled | true when the user closes the scanner |
error | Error message when an error occurs or the plan/feature is not supported |
Errors surface through the result object's cancelled / error fields, not through a separate onError callback. There is only one callback.
Real-world Example
A pattern that navigates to the URL if the QR code is a URL, otherwise sends it to the server.
document.getElementById('scan-btn').addEventListener('click', () => {
window.unveilyBridge.qr.scan("onScanComplete");
});
function onScanComplete(result) {
if (result.cancelled) return;
if (result.error) {
alert('Scan failed. Please try again.');
return;
}
const text = result.text;
if (text.startsWith('http')) {
window.location.href = text;
} else {
sendToServer(text);
}
}
async function sendToServer(text) {
await fetch('/api/qr-result', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text })
});
}Server-side Handling
app.post('/api/qr-result', (req, res) => {
const { text } = req.body;
// Look up product by barcode value, etc.
const product = productService.findByBarcode(text);
res.json({ product });
});[HttpPost("qr-result")]
public async Task<IActionResult> ProcessQR([FromBody] QRRequest request)
{
var product = await _productService.FindByBarcodeAsync(request.Text);
return Ok(new { product });
}@PostMapping("/api/qr-result")
public ResponseEntity<?> processQR(@RequestBody QRRequest request) {
Product product = productService.findByBarcode(request.getText());
return ResponseEntity.ok(Map.of("product", product));
}<?php
$data = json_decode(file_get_contents('php://input'), true);
$text = $data['text'];
$stmt = $pdo->prepare('SELECT * FROM products WHERE barcode = ?');
$stmt->execute([$text]);
$product = $stmt->fetch(PDO::FETCH_ASSOC);
header('Content-Type: application/json');
echo json_encode(['product' => $product]);<%
Dim text
text = Request.Form("text")
Dim conn, rs, sql
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open Application("ConnectionString")
sql = "SELECT * FROM products WHERE barcode = '" & text & "'"
Set rs = conn.Execute(sql)
Response.ContentType = "application/json"
If Not rs.EOF Then
Response.Write "{""found"": true, ""name"": """ & rs("name") & """}"
Else
Response.Write "{""found"": false}"
End If
%>