본문으로 바로가기

이온IC 바코드 스캐너를 사용하여 Capacitor을 빌드하는 방법

Ionic 바코드 스캐너를 만들기 위해 Capacitor 8: 앱을 설정하고 @capacitor/barcode-scanner를 추가하여 iOS, Android 및 웹에서 QR 코드 및 바코드를 스캔합니다.

Ionic 바코드 스캐너를 만들기 위해 Capacitor

Ionic 바코드 스캐너를 만들기 위해 Capacitor를 만들려면 Ionic 앱을 Capacitor 통합과 함께 만들고 공식 플러그인을 설치한 다음 안드로이드의 버전을 26으로 올리고 iOS 카메라 사용 설명을 추가한 후 호출합니다. @capacitor/barcode-scanner Android의 버전을 26으로 올리세요 minSdkVersion iOS 카메라 사용 설명을 추가하세요 CapacitorBarcodeScanner.scanBarcode() iOS 및 Android에서 native 풀 스크린 스캐너, 웹에서 브라우저 스캐너를 열고, 반환 된 텍스트 및 형식이 디코딩됩니다.

이 튜토리얼은 Ionic Angular에서 Capacitor 8에서 작동하는 스캐너 앱을 빌드하고, 형식 필터링, 오류 처리, Android 스캐닝 엔진, 연속 스캐닝, 기업 하드웨어 스캐너 및 일반적인 오류를 다룹니다.

제작할 내용

싱글 페이지 Ionic 앱에 스캔 버튼이 있습니다.

  • 카메라 스캐너를 열고
  • 각 결과를 보여주고
  • 스캔 된 값을 복사하거나 열 수 있습니다.
  • 취소 및 권한 오류를 깨끗하게 처리합니다.

code는 Angular 독립 구성 요소를 사용합니다. 플러그인은 React 또는 Vue에서 호출되는 동일한 호출을 사용하므로, 템플릿 구문만 변경됩니다.

필요 조건

  • Node.js LTS 및 Bun
  • Android: Android Studio와 SDK와 함께 장치 또는 에뮬레이터와 카메라가 있는 경우
  • iOS: Mac에서 Xcode 26이 필요하며, App Store Connect는 2026년 4월부터 업로드를 위해 필요합니다.
  • 물리적 장치는 가장 좋습니다. 에뮬레이터는 가상 카메라로 스캔할 수 있지만, 바코드에 대한 실제 조명과 초점은 중요합니다.

1단계: Ionic 앱을 생성하세요

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

The Ionic CLI scaffolds the Angular app with @capacitor/core and @capacitor/cli Ionic은 Angular 앱을 생성합니다. capacitor.config.ts: appId 이미 설치되어 있습니다. com.example.scanner, and webDir , 그리고www 이것은 Ionic Angular의 빌드 출력과 일치해야 합니다.

한 번 빌드하여 네이티브 플랫폼이 복사할 수 있도록 하세요:

bun run build

2단계: Android와 iOS를 추가하세요

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

Capacitor 8 iOS 프로젝트를 Swift Package Manager로 생성합니다. 업그레이드 중인 오래된 앱을 업그레이드하는 경우 Capacitor 8 업그레이드 가이드를 따르세요. 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__ 팀의 공식 스캐너입니다. 버전 3.x는 __CAPGO_KEEP_1__ 8을 지원합니다.

이 플러그인은 안드로이드 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 Expanded, 또는 UPC/EAN 확장 없음).

iOS 구성 ios/App/App/Info.plist:

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

카메라 사용 설명을 추가하세요.

Step 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-XXXXiOS에서 0006 사용자가 취소한 경우 0007 means camera access was denied. Treat cancel as a normal outcome, not an error. Log the raw code on Android during testing to confirm the same mapping on your target devices.

The format 결과의 CapacitorBarcodeScannerTypeHint[format] 숫자 열거형 값입니다. QR_CODE 이 열거형 값을 EAN_13.

또는

// 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>

5단계: 페이지 빌드

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

6단계: 기기에서 실행 bun run start localhost에서 앱을 실행하고, 브라우저가 카메라 접근을 허용하는 경우. LAN IP에서 HTTPS가 필요합니다.

기기에서 실시간 리로드를 사용하여 더 빠르게 반복하세요. bunx cap run android --livereload --external 앱이 저장될 때마다 앱을 다시 로드합니다.

지원하는 형식

형식 안드로이드 ZXing 안드로이드 ML Kit iOS
QR 코드 Code, Aztek, Data Matrix, PDF417 네 네 네
EAN-13, EAN-8, UPC-A, UPC-E Yes Yes Yes (UPC-A 및 EAN-13는 동일하게 처리됨)
Code 128, Code 39, Code 93, 코다바, ITF Yes Yes Yes
RSS-14, RSS Expanded Yes No Yes
MaxiCode Yes 네 네
No Yes 네 네

UPC/EAN 확장 hint지원하지 않는 형식으로 값을 전달하면

안전하게 스캔된 값을 처리하는 방법

바코드는 신뢰할 수 없는 입력입니다. 그에 따라서:

  • URL을 열기 전에 URL을 검증하고 사용자에게 도메인을 먼저 보여주세요.
  • 스캔된 문자열을 code으로 실행하지 말고 HTML에 주입하지 마세요.
  • 상품 코드의 경우 체크 디지트를 검증하기 전에 백엔드에 호출하세요.
  • 사용자가 빠르게 스캔할 수 있는 경우 백엔드 조회를 제한하세요.

기본 스캐너 이외의 기능

scanBarcode 한 번에 스캔하는, 전체 화면의 흐름입니다. 대부분의 앱을 커버합니다. 다른 요구 사항은 다른 도구를 사용합니다:

  • 자체 UI에서 지속적인 스캔 카메라 피드의 뒤에 웹 UI를 실행하세요. @__CAPGO_KEEP_0__/camera-preview @capgo/카메라 미리보기, JavaScript에서 라이브러리를 사용하여 디코딩하세요. captureSample강력한 기업 장비. zxing-wasm.
  • 강력한 기업 장치. 자바에스피(Zebra) 휴대용 장치에는 하드웨어 스캐너가 있습니다. @capgo/capacitor-zebra-datawedge __CAPGO_KEEP_0__/__CAPGO_KEEP_1__는 DataWedge 프로파일과 스캔 트리거를 관리하며, 이 장치의 카메라보다 빠르고 신뢰할 수 있는 방법입니다.
  • 문서 캡처 영수증과 종이 양식에 대한 경우, 문서 스캐너 플러그인이 바코드 리더보다 더 적합합니다. 자세한 내용은 플러그인 디렉토리.

Cordova에서 오는 경우, Cordova 바코드 스캐너 가이드 은 옛 플러그인과 마이그레이션 경로를 포함한 구체적인 정보를 제공합니다.

문제 해결

역할: 섹션 또는 페이지 제목 NSCameraUsageDescription iOS 앱이 스캔을 시작할 때 종료됩니다. Info.plist.

Android 빌드가 매니페스트 머지 오류 또는 minSdk 오류로 실패합니다. minSdkVersion 현재 버전은 24입니다. 26으로 설정하세요. android/variables.gradle 실시간 동기화.

스캐너가 열리지만 code를 읽지 못합니다. 다른 Android 엔진을 사용하세요, 조명이 개선되세요, 토치를 사용하세요, 그리고 기대하는 형식으로 제한하세요. 매우 작은 또는 손상된 코드는 카메라가 더 가까운 곳에 있어야 합니다. hint 권한이 거부됩니다.

사용자가 이전에 카메라 접근을 거부했습니다. 시스템 설정에서 허용하는 방법을 설명하는 메시지를 표시하세요. OS는 다시 프롬프트를 표시하지 않습니다. 웹 스캐너가 시작되지 않습니다.

페이지가 HTTPS나 로컬 호스트 또는 다른 탭에서 제공되지 않거나, 다른 탭에서 카메라가 사용 중일 때. 태블릿에서 방향 설정이 무시됩니다.

태블릿에서 방향 설정이 무시됩니다. Android SDK 36 버전부터 앱을 대상으로 시작하는 경우, Android 16은 대형 화면에서 고정된 방향을 무시합니다. 대형 화면에서 고정된 방향을 사용하려면 ADAPTIVE.

수정 사항을 리뷰 기다리지 않고 배포하세요.

스캐너가 활성화되면 대부분의 변경 사항, 예를 들어 새로운 유효성 검사 규칙, UI 조정 또는 다른 백엔드 조회와 같은 변경 사항은 웹 code에서 발생합니다. Capgo 라이브 업데이트 __CAPGO_KEEP_0__ 빌드 Info.plist __CAPGO_KEEP_0__에서 signed iOS 및 Android 바이너리를 cloud에서 생성합니다. Capgo 빌드 구름에서 iOS 및 Android 바이너리를 서명합니다.

Article credits

Ionic 바코드 스캐너는 Capacitor 8 에서 하나의 공식 플러그인, 두 개의 네이티브 구성 변경 (안드로이드 minSdkVersion 26과 iOS 카메라 사용 문자열), 그리고 단일 scanBarcode __CAPGO_KEEP_0__ 라이브 업데이트

Capacitor 앱에 대한 즉시 업데이트

웹-layer 버그가 활성화되면 Capgo을 통해 수정 사항을 배포하고 앱 스토어 승인 대기 없이 사용자에게 배포합니다. 사용자는 배경에서 업데이트를 받으며 네이티브 변경 사항은 일반 리뷰 경로에 남아 있습니다.

최신 블로그

Capgo은 전문적인 모바일 앱을 만들기 위해 필요한 최고의洞察력을 제공합니다.