メイン コンテンツにジャンプ

How to Build an Ionic Barcode Scanner with Capacitor

Build an Ionic barcode scanner with Capacitor 8: set up the app, add @capacitor/barcode-scanner, scan QR codes and barcodes on iOS, Android, and web.

How to Build an Ionic Barcode Scanner with Capacitor

Capacitor バーコードスキャナーの Ionic アプリを作成するには、Capacitor の Capacitor を使用して Ionic アプリを作成し、Capacitor の Capacitor 統合を使用してアプリを作成し、公式の Capacitor バーコードスキャナーをインストールしてください。 @capacitor/barcode-scanner __CAPGO_KEEP_0__ 8: Ionic バーコードスキャナーを構築する minSdkVersion __CAPGO_KEEP_0__ 8: Ionic バーコードスキャナーを構築する CapacitorBarcodeScanner.scanBarcode() iOS と Android からボタンをタップすると、ネイティブのフルスクリーン スキャナーが開きます。Web ではブラウザ スキャナーが開き、スキャンしたテキストとフォーマットが返されます。

このチュートリアルでは、Ionic Angular で Capacitor 8 を使用して機能するスキャナー アプリを構築し、フォーマット フィルタリング、エラー処理、Android スキャニング エンジン、連続スキャン、エンタープライズ ハードウェア スキャナー、一般的なエラーについて説明します。

作成するもの

単一ページの Ionic アプリのスキャン ボタンが作成されます。

  • カメラ スキャナーを開きます。
  • 各結果のフォーマットを表示します。
  • スキャンした値をコピーまたは開きます。
  • キャンセルとパーミッション エラーをきれいに処理します。

code は Angular のスタンドアロン コンポーネントを使用します。プラグインの呼び出しは React または Vue の場合にのみテンプレートのシンタックスが異なります。

前提条件

  • Node.js LTS と Bun。
  • Android の場合: Android Studio と SDK、カメラが搭載されたデバイスまたはエミュレータが必要です。
  • iOS用: Xcode 26を搭載したMac、App Store Connectはアップロードに必要なため、2026年4月以降は必要です。
  • 物理的なデバイスが最適です。エミュレータでは仮想カメラでスキャンできますが、実際の照明と焦点はバーコードの重要な要素です。

ステップ 1: イオニック アプリを作成します

bunx @ionic/cli start barcode-scanner blank --type=angular-standalone --capacitor
cd barcode-scanner

The Ionic CLIはAngularアプリケーションを生成します。 @capacitor/core そして @capacitor/cli すでにインストールされているかどうかを確認してください。 capacitor.config.ts: appId これは、逆ドメイン名でなければなりません。たとえば com.example.scanner, そして webDir これはビルド出力と一致する必要があります (Ionic Angular用)。www ネイティブプラットフォームにコピーするものが存在するように、ビルドしてください:

ステップ 2: AndroidとiOSを追加します

bun run build

ステップ 2: AndroidとiOSを追加します

bun add @capacitor/android @capacitor/ios
bunx cap add android
bunx cap add ios

Capacitor 8は、Swift Package Managerを使用して新しいiOSプロジェクトを作成します。古いアプリをアップグレードする場合は、代わりに古いアプリのアップグレードガイドを参照してください。 Capacitor 8のアップグレードガイド 最初に進みましょう。

ステップ 3: バーコードスキャナープラグインをインストールします

bun add @capacitor/barcode-scanner
bunx cap sync

@capacitor/barcode-scanner is the Capacitor team’s official scanner. Version 3.x supports Capacitor 8.

__CAPGO_KEEP_0__ チームの公式スキャナは、__CAPGO_KEEP_1__ 8をサポートするバージョン 3.xです。

プラグインはAndroid API 26以上が必要です。 Capacitor 8は24に設定されますので、変更してください。 android/variables.gradle:

ext {
    minSdkVersion = 26
    // keep the other values Capacitor generated
}

プラグインはAndroid __CAPGO_KEEP_0__ 26以上を必要とします。__CAPGO_KEEP_1__ 8は24に設定されているため、

Androidでは、スキャンごとにデコードエンジンを選択できます: ZXing (デフォルト、プラグインがリストするすべての形式をサポート) または Google ML Kit (難しいコードに対して高速ですが、MaxiCode、RSS-14、RSS Extended、またはUPC/EAN拡張をサポートしません)。

iOSの設定 ios/App/App/Info.plist:

<key>NSCameraUsageDescription</key>
<string>The camera is used to scan barcodes and QR codes.</string>

カメラの使用を説明する文を追加してください。

ステップ 4: スキャナーサービスを書きます

サービス内でプラグインの呼び出しを実行すると、再利用とテストが容易になります。

// src/app/services/scanner.service.ts
import { Injectable } from '@angular/core';
import { Capacitor } from '@capacitor/core';
import {
  CapacitorBarcodeScanner,
  CapacitorBarcodeScannerAndroidScanningLibrary,
  CapacitorBarcodeScannerCameraDirection,
  CapacitorBarcodeScannerScanOrientation,
  CapacitorBarcodeScannerTypeHint,
  CapacitorBarcodeScannerTypeHintALLOption,
} from '@capacitor/barcode-scanner';

export interface ScanResult {
  value: string;
  format: string;
  scannedAt: Date;
}

export type ScanOutcome =
  | { status: 'ok'; result: ScanResult }
  | { status: 'cancelled' }
  | { status: 'denied' }
  | { status: 'error'; message: string };

@Injectable({ providedIn: 'root' })
export class ScannerService {
  async scan(onlyQr = false): Promise<ScanOutcome> {
    try {
      const { ScanResult, format } = await CapacitorBarcodeScanner.scanBarcode({
        hint: onlyQr
          ? CapacitorBarcodeScannerTypeHint.QR_CODE
          : CapacitorBarcodeScannerTypeHintALLOption.ALL,
        scanInstructions: 'Point the camera at a barcode',
        cameraDirection: CapacitorBarcodeScannerCameraDirection.BACK,
        scanOrientation: CapacitorBarcodeScannerScanOrientation.ADAPTIVE,
        cancelButtonAccessibilityLabel: 'Cancel scanning',
        torchButtonOnAccessibilityLabel: 'Turn flashlight off',
        torchButtonOffAccessibilityLabel: 'Turn flashlight on',
        android: {
          scanningLibrary: CapacitorBarcodeScannerAndroidScanningLibrary.MLKIT,
        },
        web: {
          showCameraSelection: true,
        },
      });

      return {
        status: 'ok',
        result: {
          value: ScanResult,
          format: CapacitorBarcodeScannerTypeHint[format] ?? String(format),
          scannedAt: new Date(),
        },
      };
    } catch (err: any) {
      const code: string = err?.code ?? '';
      if (code.endsWith('0006')) return { status: 'cancelled' };
      if (code.endsWith('0007')) return { status: 'denied' };
      return { status: 'error', message: err?.message ?? 'Scan failed' };
    }
  }

  get platform() {
    return Capacitor.getPlatform();
  }
}

エラーは、次の形式のコードで返されます。 OS-PLUG-BARC-XXXX. iOSでは、 0006 はユーザーがキャンセルしたことを意味し、 0007 はカメラへのアクセスが拒否されたことを意味します。キャンセルは正常な結果として扱い、Androidのテスト中にはcodeのraw値をログに記録して、ターゲットデバイス上で同じマッピングを確認してください。

The format を使用すると、 CapacitorBarcodeScannerTypeHint[format] または QR_CODE の名前に戻されます。 EAN_13.

ステップ 5: ページをビルドする

// src/app/home/home.page.ts
import { Component, inject, signal } from '@angular/core';
import { DatePipe } from '@angular/common';
import {
  IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonLabel,
  IonFab, IonFabButton, IonIcon, IonToggle, IonNote, ToastController,
} from '@ionic/angular/standalone';
import { addIcons } from 'ionicons';
import { scanOutline } from 'ionicons/icons';
import { ScannerService, ScanResult } from '../services/scanner.service';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  imports: [
    DatePipe, IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem,
    IonLabel, IonFab, IonFabButton, IonIcon, IonToggle, IonNote,
  ],
})
export class HomePage {
  private scanner = inject(ScannerService);
  private toast = inject(ToastController);

  results = signal<ScanResult[]>([]);
  onlyQr = signal(false);
  scanning = signal(false);

  constructor() {
    addIcons({ scanOutline });
  }

  async scan() {
    if (this.scanning()) return;
    this.scanning.set(true);
    const outcome = await this.scanner.scan(this.onlyQr());
    this.scanning.set(false);

    if (outcome.status === 'ok') {
      this.results.update((list) => [outcome.result, ...list]);
    } else if (outcome.status === 'denied') {
      await this.show('Camera access is off. Enable it in Settings to scan.');
    } else if (outcome.status === 'error') {
      await this.show(outcome.message);
    }
  }

  private async show(message: string) {
    const t = await this.toast.create({ message, duration: 3000 });
    await t.present();
  }
}
<!-- src/app/home/home.page.html -->
<ion-header>
  <ion-toolbar>
    <ion-title>Barcode Scanner</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-list>
    <ion-item>
      <ion-toggle [checked]="onlyQr()" (ionChange)="onlyQr.set($event.detail.checked)">
        QR codes only
      </ion-toggle>
    </ion-item>

    @for (r of results(); track r.scannedAt) {
      <ion-item>
        <ion-label>
          <h2>{{ r.value }}</h2>
          <p>{{ r.format }} · {{ r.scannedAt | date: 'shortTime' }}</p>
        </ion-label>
      </ion-item>
    } @empty {
      <ion-item lines="none">
        <ion-note>No scans yet. Tap the button to scan.</ion-note>
      </ion-item>
    }
  </ion-list>

  <ion-fab slot="fixed" vertical="bottom" horizontal="end">
    <ion-fab-button (click)="scan()" [disabled]="scanning()" aria-label="Scan a barcode">
      <ion-icon name="scan-outline" aria-hidden="true"></ion-icon>
    </ion-fab-button>
  </ion-fab>
</ion-content>

ステップ 6: デバイスで実行する

bun run build
bunx cap sync
bunx cap run android
bunx cap run ios

ウェブ版では、 bun run start localhost ではブラウザがカメラのアクセスを許可するので、ローカルホストでアプリを実行します。LAN IP では HTTPS が必要です。

デバイスでライブリロードを使うと、開発が速くなります。 bunx cap run android --livereload --external 保存するたびにアプリを再読み込みします。

サポートされている形式

形式 Android ZXing Android ML Kit iOS
QR Code, QRコード、Aztec、Data Matrix、PDF417 はい はい はい
EAN-13, EAN-8, UPC-A, UPC-E はい はい はい(UPC-AとEAN-13は同等)
Code 128, Code 39, Code 93, コダバル, ITF はい はい はい
RSS-14, RSS Expanded はい いいえ はい
マキシコード はい いいえ いいえ
UPC/EAN拡張 はい いいえ いいえ

非対応の形式を渡した場合、 hint安全にスキャナードデータを処理する

スキャナードバーコードは信頼できない入力です。 それに応じて行動する前に:

バーコードは信頼できない入力です。 それに応じて行動する前に:

  • URLを検証し、ユーザーにドメインを表示する前に開くことを検証する。
  • スキャンした文字列を実行しないでください。code または HTML にインジェクトしないでください。
  • 製品コードの場合、チェックディジットを検証する前にバックエンドに呼び出してください。
  • ユーザーがスキャンが速くできる場合、バックエンドの検索を制限する。

基本的なスキャナーを超えて

scanBarcode は、一度のフルスクリーン フローです。ほとんどのアプリケーションをカバーします。 他のニーズは、他のツールを呼び出す必要があります:

  • ユーザー UI 内で連続的にスキャンする。 カメラの映像をウェブUIの後ろに流す @capgo/カメラプレビュー頑丈なエンタープライズ デバイス。 captureSample頑丈なエンタープライズ デバイス。 zxing-wasm.
  • 頑丈なエンタープライズ デバイス。 ゼブラのハンドヘルド端末にはハードウェアスキャナーが搭載されています。 @capgo/capacitor-zebra-datawedge DataWedgeプロファイルとスキャントリガーの管理を行っており、カメラよりも速く信頼性が高くなっています。
  • ドキュメントキャプチャ。 レシートや紙のフォームの場合、ドキュメントスキャナープラグインの方がバーコードリーダーに適しています。詳細は プラグインディレクトリ.

Cordovaから来た場合、 古いプラグインと移行パスのカバーしている Cordova バーコードスキャナーガイド

トラブルシューティング

iOS アプリがスキャンを開始すると終了します。 NSCameraUsageDescription iOSアプリがスキャンを開始すると閉じます。 Info.plist.

Android ビルドがマニフェストマージャーまたはminSdkエラーで失敗します。 minSdkVersion は依然として24です。26に設定してください。 android/variables.gradle と同期してください。

codeを読み取ることはできません。 Androidエンジンを別のものに切り替え、照明を改善し、ターチを使用し、期待する形式に制限してください。非常に小さなまたは損傷したコードはカメラを近づけてください。 hint 許可が拒否されます。

ユーザーは以前カメラのアクセスを拒否しました。システム設定で有効にする方法を説明するメッセージを表示してください。OSは再びプロンプトを表示しません。 Web スキャナーが起動しません。

ページはHTTPSまたはlocalhostで提供されていません、または別のタブがカメラを保持しています。 タブレットではオートリオリエーション設定が無視されます。

タブレットではオートレート設定を無視します。 Android アプリが Android SDK 36 をターゲットとしている場合、Android 16 は大型ディスプレイの固定方向を無視します。 ADAPTIVE.

リリース修正をレビュー待たずに送信

スキャナーがオンラインになると、ほとんどの変更、例えば新しい検証ルール、UIの微調整、または異なるバックエンドの検索など、ウェブ code。 Capgo ライブ更新 push これらのアップグレードをインストール済みアプリに数分で適用し、 Info.plist インストール済みアプリに数分以内にプッシュすることができ、プラグインのアップグレードや Capgo ビルド __CAPGO_KEEP_0__ ビルド

Wrap-up

Ionic バーコードスキャナーは Capacitor 8 で、1 つの公式プラグインと 2 つのネイティブの設定変更 (Android) minSdkVersion まとめ scanBarcode Ionic バーコード スキャナーは __CAPGO_KEEP_0__ 8 で、1 つの公式プラグイン、Android

Capacitor アプリ向けの即時更新

When a web-layer bug is live, ship the fix through Capgo instead of waiting days for app store approval. Users get the update in the background while native changes stay in the normal review path.

コンテキスト:ホームページ マーケティング コピー。役割:ウェブサイト コピー文。見られる場所:コンポーネント HumanSupport.astro、コンポーネント pricing/Plans.astro。メッセージ キー `home_hero_human_support` (ホーム ヘロ ヒューマン サポート)。

Capgoは、プロフェッショナルなモバイルアプリを作成するために必要な最良の洞察を提供します。