Um einen Ionic Barcode-Scanner mit Capacitor zu erstellen, erstellen Sie eine Ionic-App mit der Capacitor-Integration, installieren Sie das offizielle Plugin, die Android- @capacitor/barcode-scanner plugin, erhöhen Androids minSdkVersion zurück 26, fügen Sie die iOS-Kamera-Nutzungsbeschreibung hinzu und rufen Sie CapacitorBarcodeScanner.scanBarcode() aus einem Button. Das Plugin öffnet einen nativen Vollbildscanner auf iOS und Android, einen Browser-Scanner im Web und gibt das entschlüsselte Text und Format zurück.
Diese Anleitung erstellt eine funktionierende Scanner-App in Ionic Angular auf Capacitor 8, behandelt dann die Formatfilterung, Fehlerbehandlung, Android-Scannereinheiten, kontinuierliche Scannung, Unternehmenshardware-Scanner und häufige Fehler.
Was Sie bauen werden
Ein einzelnes Ionic-App mit einem Scannen-Button, der:
- den Kamera-Scanner öffnet
- jedes Ergebnis mit seinem Format anzeigt
- Sie können den gescannten Wert kopieren oder öffnen
- Cancel- und Berechtigungsfehler werden sauber behandelt
Die code verwendet Angular-Standalone-Komponenten. Die Pluginaufrufe sind in React oder Vue identisch, daher ändern sich nur die Template-Syntax.
Voraussetzungen
- Node.js LTS und Bun
- Für Android: Android Studio mit einem SDK und einem Gerät oder einem Emulator mit einer Kamera.
- Für iOS: Ein Mac mit Xcode 26, das App Store Connect seit April 2026 für Uploads benötigt.
- Ein physisches Gerät ist am besten. Emulatoren können mit einer virtuellen Kamera scannen, aber reale Licht und Schärfe sind für Barcodes wichtig.
Schritt 1: Erstellen Sie die Ionic-Anwendung
bunx @ionic/cli start barcode-scanner blank --type=angular-standalone --capacitor
cd barcode-scanner
Die Ionic CLI erstellt die Angular-Anwendung mit @capacitor/core und @capacitor/cli bereits installiert. Überprüfen Sie capacitor.config.ts: appId sollte Ihre umgekehrte Domänen-ID sein, zum Beispiel com.example.scanner, und webDir sollte der Ausgabebau (für Ionic Angular) entsprechen.www für Ionic (Angular).
Bauen Sie einmalig, damit die nativen Plattformen etwas kopieren können:
bun run build
sollte bereits installiert sein.
bun add @capacitor/android @capacitor/ios
bunx cap add android
bunx cap add ios
Capacitor 8 erstellt neue iOS-Projekte mit Swift Package Manager. Wenn Sie stattdessen ein älteres App aktualisieren, folgen Sie der Capacitor 8 Upgrade Guide erste.
Schritt 3: Installieren Sie das Barcode-Scanner-Plugin
bun add @capacitor/barcode-scanner
bunx cap sync
@capacitor/barcode-scanner ist das offizielle Scanner der Capacitor-Team. Die Version 3.x unterstützt Capacitor 8.
Android-Konfiguration
Das Plugin erfordert Android API 26 oder höher. Capacitor 8 wird standardmäßig auf 24 gesetzt, daher bearbeiten Sie android/variables.gradle:
ext {
minSdkVersion = 26
// keep the other values Capacitor generated
}
Auf Android können Sie das Dekodierungsmodul pro Scan auswählen: ZXing (Standard, unterstützt alle Formate, die das Plugin auflistet) oder Google ML Kit (schnell bei schwierigen Codes, unterstützt jedoch keine MaxiCode, RSS-14, RSS Expanded oder UPC/EAN-Erweiterung).
iOS-Konfiguration
Add a camera usage description to ios/App/App/Info.plist:
<key>NSCameraUsageDescription</key>
<string>The camera is used to scan barcodes and QR codes.</string>
Ohne es, wird iOS die App bei der ersten Kamera-Zugriff beenden. Schreiben Sie die Aussage für den Benutzer, da App Review sie auch liest. iOS verwendet Apples Vision-Framework, das alle aufgelisteten Formate außer MaxiCode und UPC/EAN-Erweiterung unterstützt und keine Unterscheidung zwischen UPC-A und EAN-13 macht.
Schritt 4: Schreibe die Scanner-Dienstleistung
Verwenden Sie Aufrufe von Plugins in einem Dienst, um sie leicht wiederzuverwenden und zu testen.
// 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();
}
}
Der Plugin gibt Fehler mit Codes in der Form zurück. OS-PLUG-BARC-XXXXBei iOS bedeutet 0006 die Benutzer haben die Aktion abgebrochen und 0007 die Kamera-Zugriff wurde abgelehnt. Behandeln Sie Abbruch als normales Ergebnis und nicht als Fehler. Loggen Sie die Rohwerte von code auf Android während der Tests, um die gleiche Zuordnung auf Ihren Zielgeräten zu bestätigen.
Der format enthält in der Ergebnisliste eine numerische Enum-Wert. CapacitorBarcodeScannerTypeHint[format] wandelt es zurück in einen Namen wie QR_CODE oder EAN_13.
Die Wahl zwischen
// 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>
Wenn Sie die Webversion verwenden,
bun run build
bunx cap sync
bunx cap run android
bunx cap run ios
Schritt 5: Erstellen Sie die Seite bun run start auf lokalen Hosts lädt die App, wo Browser die Kamerazugriff erlauben. Über ein LAN-IP benötigen Sie HTTPS.
To schneller iterieren, verwenden Sie Live-Reload auf einem Gerät: bunx cap run android --livereload --external das App neu lädt, sobald Sie speichern.
Unterstützte Formate
| Format | Android ZXing | Android ML Kit | iOS |
|---|---|---|---|
| QR Code, Aztec, Data Matrix, PDF417 | Ja | Ja | Ja |
| EAN-13, EAN-8, UPC-A, UPC-E | Ja | Ja | Ja (UPC-A und EAN-13 gleich behandelt) |
| Code 128, Code 39, Code 93, Codabar, ITF | Ja | Ja | Ja |
| RSS-14, RSS Expanded | Ja | Nein | Ja |
| MaxiCode | Ja | Nein | Nein |
| UPC/EAN-Erweiterung | Ja | Nein | Nein |
Wenn Sie eine nicht unterstützte Format als hint, fällt der Plugin auf jede Format zurück.
Sichere Verarbeitung von gescannten Werten
Ein Barcode ist unvertrauenswürdiger Eingabe. Bevor Sie darauf handeln:
- Überprüfen Sie die URLs vor dem Öffnen und zeigen Sie dem Benutzer zunächst den Domainnamen an.
- Führen Sie keine gescannten Zeichenketten als code aus oder injizieren Sie sie in HTML.
- Für Produktcodes überprüfen Sie den Prüfziffer vor der Aufruf Ihres Backends.
- Rate limit Hintergrundabfragen, wenn Benutzer schnell scannen können.
Hinausgehen über die grundlegende Scanner
scanBarcode ist ein einmaliger, vollbildschirmiger Workflow. Dies deckt die meisten Apps ab. Andere Bedürfnisse erfordern andere Werkzeuge:
- Kontinuierliche Scannung in Ihrem eigenen UI. Führen Sie eine Kamera-Übertragung hinter Ihrem Web-UI mit @capgo/Kamera-Vorschau, greifen Sie Frames mit
captureSample, und entschlüsseln Sie sie in JavaScript mit einer Bibliothek wiezxing-wasm. - Robuste Unternehmensgeräte. Zebra-Handhelds verfügen über Hardware-Scanner. @capgo/capacitor-zebra-datawedge verwaltet DataWedge-Profil und Scan-Trigger, was schneller und zuverlässiger ist als die Kamera auf diesen Geräten.
- Dokumentenabbildung. Für Rechnungen und Papierformulare passt ein Dokumentenscanner-Plugin besser als ein Barcode-Reader. Sehen Sie sich das Plugin-Verzeichnis.
Kommen Sie aus Cordova? Unsere Cordova-Barcodescanner-Anleitung beschreibt die alten Plugins und einen Migrationsweg.
Fehlertoleranz
iOS-App schließt sich, wenn das Scannen beginnt. NSCameraUsageDescription is missing from Info.plist.
Android-Build fehlt mit einem Manifest-Merger- oder minSdk-Fehler. minSdkVersion ist immer noch 24. Setze es auf 26 in android/variables.gradle and sync.
Der Scanner öffnet sich, liest aber nie den code. Probieren Sie die andere Android-Motor, verbessern Sie das Licht, verwenden Sie den Blitz und beschränken Sie hint bis zum Format, das Sie erwarten. Sehr kleine oder beschädigte Codes benötigen die Kamera näher.
Zugriff verweigert jedes Mal. The user denied camera access earlier. Show a message that explains how to enable it in system settings. The OS will not show the prompt again.
Der Web-Scanner startet nicht. Die Seite wird nicht über HTTPS oder localhost oder in einem anderen Tab mit der Kamera geladen.
Ausrichtungseinstellung wird auf Tablets ignoriert. Mit Apps, die auf Android SDK 36 abzielen, ignoriert Android 16 fixierte Orientierungen auf großen Bildschirmen. Verwenden Sie ADAPTIVE.
Schiffe ohne Warteschleife auf Review
Sobald der Scanner aktiv ist, werden die meisten Änderungen, wie z.B. neue Validierungsregeln, UI-Anpassungen oder eine andere Backend-Abfrage, über code live aktualisiert. Capgo live Updates pushen Sie diese in Minuten in installierte Apps, während Plugin-Updates und Info.plist Änderungen gehen weiterhin über die Stores. Wenn Sie eine neue native Build benötigen, ohne eine lokale Mac-Einrichtung. Capgo Build erzeugt signierte iOS- und Android-Binärdateien im Cloud.
Wrap-up
Ein Ionic Barcode-Scanner auf Capacitor 8 benötigt einen offiziellen Plugin, zwei native Konfigurationsänderungen (Android) minSdkVersion 26 und die iOS-Kamera-Nutzungszeichenfolge) und eine einzelne scanBarcode call. Restrict formats when you can, treat cancel and permission errors as normal outcomes, validate everything you scan, and reach for a camera preview or DataWedge when the one-shot flow is not enough.