QR・バーコードスキャナー
QR コードとバーコードをスキャンする
概要
カメラを開いて QR コードまたはバーコードをスキャンし、結果を返します。Android と iOS は同じ JS API と同じレスポンス形式を使用します。
| 機能 | Android | iOS |
|---|---|---|
| QR コードスキャン | ✓(Android 7.0+) | ✓ |
| バーコードスキャン | ✓(Android 7.0+) | ✓ |
対応プラン: Basic 以上(ライセンス機能 qr が必要)
事前準備
QR スキャンはカメラ権限を使用します。対象プラットフォームに合わせて権限を設定してください。
Android
AndroidManifest.xml ではカメラ権限がコメントアウトされた状態で配布されます。QR スキャンを使用するにはコメントを解除してください。
<uses-permission android:name="android.permission.CAMERA" />iOS
Info.plist にカメラ使用の説明を追加する必要があります。
<key>NSCameraUsageDescription</key>
<string>QR コードおよびバーコードのスキャンにカメラへのアクセスが必要です。</string>使い方
unveilyBridge.qr.scan(cb) を呼び出すとスキャナーが開きます。cb は結果を受け取るコールバック関数名の文字列です。省略するとデフォルトの 'onQRResult' が使用されます。
// コールバック名を明示的に指定
window.unveilyBridge.qr.scan("onQRResult");
// またはデフォルトのコールバック(onQRResult)を使用
window.unveilyBridge.qr.scan();
function onQRResult(result) {
if (result.cancelled) {
return; // ユーザーがスキャナーを閉じた
}
if (result.error) {
console.error("スキャン失敗:", result.error); // エラーまたはプラン未対応
return;
}
console.log("スキャン内容:", result.text); // スキャンされた文字列
console.log("フォーマット:", result.format); // 例: "QR_CODE", "EAN_13"
console.log("タイプ:", result.type); // コンテンツタイプ(例: "URL", "TEXT")
}結果はすでにパースされた JS オブジェクトとして渡されます。JSON.parse() を呼び出す必要はありません。
レスポンスの構造
コールバックは次の 3 つの形式のいずれかのオブジェクトを受け取ります。
{ "text": "https://example.com", "format": "QR_CODE", "type": "URL" }{ "cancelled": true }{ "error": "..." }| フィールド | 説明 |
|---|---|
text | スキャンされた文字列(成功時) |
format | バーコードのシンボル体系 — QR_CODE, EAN_13, EAN_8, CODE_128, CODE_39, ITF, DATA_MATRIX, PDF_417, AZTEC など |
type | コンテンツタイプの分類(例: URL, TEXT) |
cancelled | ユーザーがスキャナーを閉じると true |
error | エラー発生時、またはプラン/機能が未対応の場合のエラーメッセージ |
エラー処理は別の onError コールバックではなく、結果オブジェクトの cancelled / error フィールドで行います。コールバックは 1 つだけです。
実践例
QR コードが URL であればページに移動し、それ以外はサーバーに送るパターンです。
document.getElementById('scan-btn').addEventListener('click', () => {
window.unveilyBridge.qr.scan("onScanComplete");
});
function onScanComplete(result) {
if (result.cancelled) return;
if (result.error) {
alert('スキャンに失敗しました。もう一度お試しください。');
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 })
});
}サーバー側の処理
app.post('/api/qr-result', (req, res) => {
const { text } = req.body;
// バーコードの値で商品を検索するなどの処理
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
%>