Aller directement au contenu principal

Comment créer un scanner de code-barres Ionic avec Capacitor

Construirez un scanner de code-barres Ionic avec Capacitor 8 : configurez l'application, ajoutez @capacitor/barcode-scanner, scannez les codes QR et les codes-barres sur iOS, Android et web.

Crédits de l'article

Martin Donadieu

Auteur

Valeria

Réviseur

Jordan

Éditeur

Comment construire un scanner de code-barres Ionic avec Capacitor

Pour créer un scanner de code-barres Ionic avec Capacitor, créez une application Ionic avec l'intégration Capacitor, installez l'extension officielle @capacitor/barcode-scanner Raising Android's minSdkVersion ajouter à 26, la description d'utilisation de la caméra iOS, et appeler CapacitorBarcodeScanner.scanBarcode() à partir d'un bouton. Le plugin ouvre un scanner à écran plein natif sur iOS et Android, un scanner de navigateur sur le web, et retourne le texte décodé et le format.

Cette étape de tutoriel construit une application de scanner fonctionnelle en Ionic Angular sur Capacitor 8, puis couvre le filtrage des formats, la gestion des erreurs, les moteurs de scan Android, la scan continue, les scanners d'équipement d'entreprise et les erreurs courantes.

Ce que vous allez construire

Une application d'Ionic unique avec un bouton de scan qui :

  • ouvre le scanner de caméra
  • affiche chaque résultat avec son format
  • vous permet de copier ou d'ouvrir la valeur scannée
  • gère les erreurs d'annulation et de permissions de manière propre

L'code utilise des composants Angular standalone. Les appels du plugin sont identiques dans React ou Vue, donc seule la syntaxe de template change.

Prerequisites

  • Node.js LTS et Bun.
  • Pour Android : Android Studio avec un SDK et un appareil ou un émulateur avec une caméra.
  • Pour iOS : un Mac avec Xcode 26, qui App Store Connect exige pour les téléchargements depuis avril 2026.
  • Un appareil physique est préférable. Les émulateurs peuvent scanner avec une caméra virtuelle, mais la lumière et l'accent réels comptent pour les codes-barres.

Étape 1 : Créez l'application Ionic

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

L’Ionic CLI configure l'application Angular avec @capacitor/core and @capacitor/cli déjà installé. Vérifiez capacitor.config.ts: appId devrait être votre ID de domaine inversé, par exemple com.example.scanner, and webDir devrait correspondre à la sortie de build (www pour Ionic Angular).

Construis une fois pour que les plateformes natives aient quelque chose à copier :

bun run build

Étape 2 : Ajoutez Android et iOS

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

Capacitor 8 crée de nouveaux projets iOS avec le gestionnaire de packages Swift. Si vous mettez à jour une ancienne application, suivez les. Si vous mettez à niveau une ancienne application au lieu de créer une nouvelle, suivez le guide de mise à niveau Capacitor 8. Premièrement.

Étape 3 : Installez le plugin de lecture de code-barres

bun add @capacitor/barcode-scanner
bunx cap sync

@capacitor/barcode-scanner Le plugin Capacitor est l'official scanner de l'équipe Capacitor 8.

Configuration Android

Le plugin nécessite Android API 26 ou supérieur. Capacitor 8 utilise par défaut 24, vous devez donc éditer android/variables.gradle:

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

Sur Android, vous pouvez choisir l'engin de décodage par scan : ZXing (par défaut, supporte tous les formats listés par le plugin) ou Google ML Kit (rapide sur les codes difficiles, mais sans MaxiCode, RSS-14, RSS étendu ou UPC/EAN).

Configuration iOS

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>

Sans cela, iOS arrête l'application lors de la première accès à la caméra. Écrivez la phrase pour l'utilisateur, car App Review la lit également. iOS utilise le framework Vision d'Apple, qui supporte tous les formats listés, excepté MaxiCode et UPC/EAN extension, et ne distingue pas UPC-A de EAN-13.

Étape 4 : Écrire le service de scanner

Maintenir les appels de plugin dans un service les rend facilement réutilisables et testables.

// 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();
  }
}

Le plugin renvoie des erreurs avec des codes sous la forme OS-PLUG-BARC-XXXX. Sur iOS, 0006 signifie que l'utilisateur a annulé et 0007 signifie que l'accès à la caméra a été refusé. Considérez l'annulation comme un résultat normal et non comme une erreur. Enregistrez le code brut sur Android pendant les tests pour confirmer la même correspondance sur vos appareils cibles.

Le format est une valeur numérique de type enum. CapacitorBarcodeScannerTypeHint[format] tourne cela en un nom tel que QR_CODE or EAN_13.

Étape 5 : Construisez la page

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

Étape 6 : Exécution sur appareils

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

Étape 5 : Construire la page bun run start héberge l'application sur localhost, où les navigateurs autorisent l'accès à la caméra. Sur un IP LAN, vous avez besoin d'HTTPS.

Toiter plus vite, utilisez la rechargement en direct sur un appareil : bunx cap run android --livereload --external Rafraîchit l'application à chaque sauvegarde.

Formats pris en charge

Format ZXing Android Android ML Kit iOS
QR Code, Aztec, Matrice de données, PDF417 Oui Oui Oui
EAN-13, EAN-8, UPC-A, UPC-E Oui Oui Oui (UPC-A et EAN-13 traités de la même manière)
Code 128, Code 39, Code 93, Codabar, ITF Oui Oui Oui
RSS-14, RSS Élargi Oui Non Oui
MaxiCode Oui Non Non
Extension UPC/EAN Oui Non Non

Si vous passez un format non pris en charge hint, le plugin revient à l'analyse de tout format.

Gestion des valeurs scannées de manière sécurisée

Un code-barre est une entrée non fiable. Avant d'y agir :

  • Vérifiez les URL avant de les ouvrir et montrez le domaine à l'utilisateur en premier.
  • N'injectez pas les chaînes scannées en tant que code ou dans le code HTML.
  • Pour les codes de produits, validez le chiffre de contrôl’avant d'appeler votre backend.
  • Rate limit backend lookups if users can scan quickly.

Allez au-delà du scanner de base

scanBarcode est un flux d'une seule passe, plein écran. Cela couvre la plupart des applications. D'autres besoins nécessitent d'autres outils :

  • Balayage continu dans votre interface utilisateur. Run a camera feed behind your web UI with @capgo/prévisualisation de la caméracapturer des images avec captureSampleet décodez-les en JavaScript avec une bibliothèque comme zxing-wasm.
  • Appareils robustes pour les entreprises. Zebra handhelds have hardware scanners. @capgo/capacitor-zebra-datawedge gère les profils DataWedge et les déclencheurs de scan, ce qui est plus rapide et plus fiable que la caméra de ces appareils.
  • Capture de document. Pour les reçus et les formulaires papier, un plugin de scanner de documents convient mieux qu'un lecteur de code-barres. Voir le Répertoire des plugins.

En provenance de Cordova ? Notre Guide du lecteur de code-barres Cordova couvre les anciens plugins et un chemin de migration.

Troubleshooting

L'application iOS se ferme lorsque le scan commence. NSCameraUsageDescription est manquant de Info.plist.

La construction Android échoue avec une erreur de fusion de manifeste ou minSdk. minSdkVersion La version est toujours 24. Définissez-la sur 26 dans android/variables.gradle et synchronisez.

Le lecteur ouvre mais ne lit jamais le code. Essayez l'autre moteur Android, améliorez l'éclairage, utilisez la torche et restreignez hint à la forme que vous attendez. Les codes très petits ou endommagés nécessitent la caméra plus proche.

Accès refusé chaque fois. L'utilisateur a refusé l'accès à la caméra plus tôt. Affichez un message qui explique comment l'activer dans les paramètres du système. L'OS ne montrera plus le prompt.

Le lecteur de code Web ne démarre pas. La page n'est pas servie sur HTTPS ou localhost, ou une autre fenêtre détient la caméra.

Paramètre d'orientation ignoré sur les tablettes. En commençant avec des applications ciblant Android SDK 36, Android 16 ignore les orientations fixes sur les écrans grands. Utilisez ADAPTIVE.

Envoyez des correctifs sans attendre la revue

Once the scanner is live, most changes, such as new validation rules, UI tweaks, or a different backend lookup, are web code. Capgo mises à jour en direct Poussez-les vers les applications installées en quelques minutes, tout en mettant à jour les plugins. Info.plist Les modifications sont toujours soumises aux magasins. Lorsque vous avez besoin d'une nouvelle build native sans un Mac local. Capgo Construction produit des binaires iOS et Android signés dans le cloud.

Wrap-up

Une scanner de code-barres Ionic sur Capacitor 8 nécessite un plugin officiel unique, deux modifications de configuration natives (Android minSdkVersion 26 and the iOS camera usage string), and a single 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.

Mises à jour instantanées pour les applications 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.

Dernières actualités

Capgo vous offre les meilleures informations nécessaires pour créer une application mobile véritablement professionnelle.