Quantcast

QR Scanner Ionic con Capacitor, se hace así

Aitor Sánchez - Blog - Oct. 27, 2023, 8:50 a.m.

¿Pensando en incluir un escaner de códigos QR en tu aplicación Ionic? O, quizás, lo que quieres es conocer alguno de los campos o funciones de qr-ionic porque ya sabes cómo funciona pero te falta algo para tu app ¿verdad?

Mi nombre es Aitor Sánchez, soy desarrollador de apps desde 2014, y con la información de este artículo, leer códigos QR desde tu app será una tarea igual de sencilla que programar una variable.

Pero antes de continuar, esta es la Flutter Mafia. Es mi newsletter donde aprenderás desarrollo de apps móviles, aso y monetización junto con otros genietes que ya están dentro. Y si te suscribes te regalo mi ebook "Duplica los ingreso de tus apps en 5 minutos" No es broma, quizás te interese.

Y ahora, vamos con el artículo ¡Let´s go!

 

Cómo instalar QR Scanner en nuestra aplicación Ionic

Bueno, pues cómo conocerás ya, en Ionic cuando tratamos de utilizar un módulo externo tenemos que instalarlo. Para ello vamos a utilizar las siguientes dos líneas de consola.

 

Sin capacitor:

ionic cordova plugin add cordova-plugin-qrscanner
npm install @ionic-native/qr-scanner

La primera instalará el plugin de Codova que nos permitirá la comunicación nativa con el sistema para poder escanear los barcode.

La segunda, en este caso, instalará el código TS que hará de puente entre nuestro código se puede comunicar con el plugin de Cordova.

 

Con capacitor:

npm install @capacitor-mlkit/barcode-scanning
npx ionic cap sync

 

Por otro lado, necesitamos hacer lo siguiente:

Android, agregar la manifest.xml dentro de la etiqueta "application":

<meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="barcode_ui"/>

 

Y en los permisos:

<!-- To get access to the camera. -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- To get access to the flashlight. -->
<uses-permission android:name="android.permission.FLASHLIGHT"/>

 

 

En iOS al info.plist:

<key>NSCameraUsageDescription</key>
<string>The app enables the scanning of various barcodes.</string>

 

 

List, ya está instalado, continuemos.

 

Configuración del módulo

Antes de continuar con este punto, tienes que saber que no es necesario incluir el componente en los providers padre de la aplicación. En el archivo “AppModule”. Podemos poner en el “Module” que nosotros queramos que esté asociado a un componente.

Así ganamos rendimiento en nuestra app al no tener que instanciarlo al principio. No se notará mucho, pero algo hará.

El código, ya sea en un lado o en otro, quedaría de la siguiente manera:

 

providers: [
… ,
QRScanner ,
…
]

 

Donde providers, cómo he comentado en el párrafo anterior, puede ser de cualquier módulo de la app, no necesariamente del “AppModule”. Lo repito para que quede bien claro.

 

Plataformas disponibles para QR Scanner

Ahora veamos en que dispositivos podemos usar el módulo y escanear los qr code.

  • Android
  • iOS
  • Windows
  • Browser

Vale, son las especificaciones que nos da la web principal. Pero yo no he probado cómo usará el QR Scanner el browser o la plataforma Windows. Imagino que lo harán sobre la webcam, no habría otra manera sencilla.

 

Cómo se usa QR Scanner en mi app

Perfecto, ya sabiendo lo anterior estamos a disposición de usar el módulo dentro de una de nuestras aplicaciones. Vamos a ver un ejemplo y comentamos después sobre el example de código.

 

Sin capacitor:

import { QRScanner, QRScannerStatus } from '@ionic-native/qr-scanner/ngx';

constructor(private qrScanner: QRScanner) { }

...

// Opcionalmente solicitamos los permisos antes de hacer nada
this.qrScanner.prepare()
  .then((status: QRScannerStatus) => 
     if (status.authorized) {
       // Los permisos están concedidos

       // Comenzamos a escanear
       let scanSub = this.qrScanner.scan().subscribe((text: string) => {
         console.log('Scanned something', text);
         this.qrScanner.hide(); // Ocultamos el preview
         scanSub.unsubscribe(); // Dejamos de Scannear
       });

     } else if (status.denied) {

       // Los permisos de la cámara están denegados permanentemente
       // Para poder volver a usar la cámara, el usaurio tendrá que abrir los ajustes de persmisos
       // Y dar permisos desde allí con la función "openSettings"

     } else {

       // Los permisos han sido denegados, pero no permanentemente. Si los solicitas otra vez volverá a aparecer la solicitud.

     }
  })
  .catch((e: any) => console.log('Error is', e));

 

En primer lugar, importamos QRScanner y QRScannerStatus en nuestro archivo. La primera será la encargada de realizar el trabajo duro, y la segunda será la que nos de la confirmación para poder seguir trabajando con el componente.

Después, inyectamos una instancia de QRScanner en el constructor de la clase para que lo podamos utilizar en nuestro código.

 

Con capacitor:

import { Component, OnInit } from '@angular/core';
import { Barcode, BarcodeScanner } from '@capacitor-mlkit/barcode-scanning';
import { AlertController } from '@ionic/angular';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
  isSupported = false;
  barcodes: Barcode[] = [];

  constructor(private alertController: AlertController) {}

  ngOnInit() {
    BarcodeScanner.isSupported().then((result) => {
      this.isSupported = result.supported;
    });
  }

  async scan(): Promise<void> {
    const granted = await this.requestPermissions();
    if (!granted) {
      this.presentAlert();
      return;
    }
    const { barcodes } = await BarcodeScanner.scan();
    this.barcodes.push(...barcodes);
  }

  async requestPermissions(): Promise<boolean> {
    const { camera } = await BarcodeScanner.requestPermissions();
    return camera === 'granted' || camera === 'limited';
  }

  async presentAlert(): Promise<void> {
    const alert = await this.alertController.create({
      header: 'Permission denied',
      message: 'Please grant camera permission to use the barcode scanner.',
      buttons: ['OK'],
    });
    await alert.present();
  }
}

 

Y antes de seguir, un ejemplo prácitco del HTML aplicado sobre el código del párrafo anterio:

<ion-header>
  <ion-toolbar>
    <ion-title>Escaner de códigos QR y de barras</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-list>
    <ion-item *ngFor="let barcode of barcodes">
      <ion-label position="stacked">{{ barcode.format }}</ion-label>
      <ion-input type="text" [value]="barcode.rawValue"></ion-input>
    </ion-item>
  </ion-list>
  <ion-fab slot="fixed" vertical="bottom" horizontal="end">
    <ion-fab-button (click)="scan()" [disabled]="!isSupported">
      <ion-icon name="scan"></ion-icon>
    </ion-fab-button>
  </ion-fab>
</ion-content>

 

 

 

Preparación y permisos

Cómo comprenderás, tenemos que pedir permisos para poder utilizar la cámara del dispositivo. Para esto usaremos la función “prepare” que se encargará de todo por nosotros. Lanzará el modal de solicitud y nos avisará, mediante una instancia de “QRScannerStatus” de si tenemos permisos o no.

A partir de ahí podemos actuar cómo queramos. Posteriormente veremos los valores que nos llegan, ahora ciñámonos al ejemplo.

 

Cómo escanear un código con QR Scanner

Comprobamos con el campo “authorized” si se han concedido los premisos. Y de ser así ya estamos en posición de escanear con el qr reader.

Posteriormente llamamos al método “scan” y nos suscribiremos a él. Se nos notificará cuando el usuario haya terminado el escaneo. Así que en la cadena que nos llega en la suscripción vendrá el texto que hay codificado en el QR. Así de sencillo.

Llamamos al método “hide” para esconder la cámara y a “unsuscribe” para cerrar la suscripción y que no chupe memoria el módulo QR Scanner.

El resto de los casos los podemos ver en los comentarios del código.

Bueno, pues este es un ejemplo totalmente funcional de app. Pruébalo si quieres y seguimos cuando hayas terminado. Yo no me moveré de aquí: P

 

Métodos de clase

Veamos ahora cómo podemos utilizar esta instancia, y que funciones pones a nuestra disposición la clase QRScanner.

 

prepare()

Solicita los permisos al usuario para poder usar la cámara. Es recomendable usarlo siembre y hacer todo lo que necesitemos desde la promesa que devuelve. Así no tendremos que estar preguntando siempre si hay permisos o no, salvo contadas excepciones.

  • Retorno -> Una promesa que lleva una instancia de “QRScannerStatus” dentro.

 

scan()

Pone el sistema en modo de escaneo para que reconozca cualquier código que pase delante de la cámara.

Si queremos ver lo que está en la cámara a tiempo real, tenemos que llamar posteriormente al método “show”.

  • Retorno -> Un observable que notificará cuando se haya escaneado algo y lleva dentro un string con los datos del código QR.

 

show()

Nos permite visualizar el previo de la cámara para poder ver lo que estamos viendo por ella. La forma de la que lo hace es, ajustando el color de fondo del WebView a transparente. Así deja ver lo que hay abajo.

  • Retorno -> Una promesa que lleva una instancia QRScannerStatus dentro.

 

hide()

El opuesto al método anterior. En caso de que la cámara se esté visualizando, cambiará el color de fondo del WebView a opaco y su contenido para que volvamos a ver las cosas de nuestra aplicación.

  • Retorno -> Una promesa que lleva una instancia de QRScannerStatus dentro.

 

enableLight()

Fuerza a que el dispositivo encienda el flash para utilizarlo cómo linterna.

  • Retorno -> Una promesa que lleva una instancia de QRScannerStatus dentro.

 

destroy()

Al tratarse de un componente nativo, es recomendable, y en ocasiones necesario, de que este tipo de instancias se eliminen de la memoria en manera de lo posible. Este método tiene ese fin. Pero debemos tener cuidado de no usar la instancia después de haberlo llamado.

  • Retorno -> Una promesa que lleva una instancia de QRScannerStatus dentro.

 

disableLight()

Lo opuesto al método “enableLight”. Este apaga el flash la luz.

  • Retorno -> Una promesa que lleva una instancia de QRScannerStatus dentro.

 

useFrontCamera()

Cómo su propio nombre indica, fuerza al sistema a utilizar la cámara frontal en lugar de la trasera.

  • Retorno -> Una promesa que lleva una instancia de QRScannerStatus dentro.

 

useBackCamera()

Lo opuesto al método anterior, fuerza al sistema a usar la cámara trasera.

  • Retorno -> Una promesa que lleva una instancia de QRScannerStatus dentro.

 

useCamera(camera: number)

Nos permite definir la cámara a usar de manera dinámica. Siendo “0” la cámara trasera y “1” la cámara frontal.

  • Retorno -> Una promesa que lleva una instancia de QRScannerStatus dentro.

 

puasePreview()

Nos permite poner en pausa la previsualización de la cámara por pantalla. Pudiendo así, por ejemplo, tomar una captura o ver mejor algo de lo que haya quedado enfocado.

  • Retorno -> Una promesa que lleva una instancia de QRScannerStatus dentro.

 

resumePreview()

Lo opuesto al método anterior, nos permite quitar la pausa a la previsualización.

  • Retorno -> Una promesa que lleva una instancia de QRScannerStatus dentro.

 

getStatus()

En caso de que tengamos que consultar los permisos de la cámara, aquí está la función.

  • Retorno -> Una promesa que lleva una instancia de QRScannerStatus dentro.

 

openSettings()

Esta función abre una pantalla con para editar los permisos de la aplicación. Para, por ejemplo, si el usuario ha dicho que no quiere que usemos la cámara y luego cambia de opinión, esta será la opción que debemos de utilizar.

  • Retorno -> Una promesa que lleva una instancia de QRScannerStatus dentro.

 

Bueno, pues hasta aquí llegan las funciones que tenemos disponibles para usar y lo que podemos hacer con ellas de manera resumida.

Ahora vamos a pasar a ver los campos que tenemos disponibles en la clase “QRScannerStatus” que has estado viendo durante todo el tutorial.

 

Campos y propiedades de QRScannerStatus

QRScannerStatus es la clase que nos permitirá conocer los datos y detalles del estado del sistema. Por esta razón, en cada una de las funciones que llamamos nos devuelve una instancia de esta, pero es la misma instancia.

  • authorized
    • Booleano
    • En Android 6.0 y en adelante, y en iOS, el acceso a la cámara se hace en tiempo de ejecución. Al usuario le aparecerá un dialogo que tendrá que confirmar si nos da acceso a usar la cámara. Esta propiedad es verdadera cuando el usuario ha aceptado los premisos.
      • Nota: En versiones de Android inferiores a 6.0 y Windows Phone, el permiso se pide en tiempo de instalación, o antes, así que esta propiedad será siempre verdadera.
  • denied
    • Booleano
    • Esta propiedad será verdadera si el usuario ha denegado el acceso al uso de la cámara. La única manera de cambiarlo es desde la pantalla de permisos de la app y lo puedes solicitar con la función “openSettings”.
  • restricted
    • Booleano
    • Esta propiedad será verdadera cuando, por ejemplo, el teléfono esté bajo protección parental, seguridad de organización, configuración de perfiles o cosas similares.
  • prepared
    • Booleano
    • Nos indica si el dispositivo está listo para poder comenzar a trabajar con él.
  • showing
    • Booleano
    • Nos indica si la cámara se está visualizando en el momento de la llamada a la función.
  • scanning
    • Booleano
    • Similar al anterior, pero ahora evalúa si el sistema está en estado de escaneo.
  • previewing
    • Booleano
    • Esta propiedad será verdadera cuando la cámara se esté pre visualizando en la pantalla.
  • lightEnable
    • Booleano
    • Nos permite saber si la luz / flash están encendidos en la llamada a esta función.
  • canOpenSettings
    • Booleano
    • Esta propiedad nos permite conocer si podemos hacer uso de la función “openSettings” dependiendo de la disponibilidad del sistema operativo.
  • canEnableLight
    • Booleano
    • Con esta propiedad podemos saber si la cámara seccionada tiene luz y si podemos utilizarla.
  • canChangeCamera
    • Booleano
    • Accediendo a este campo podemos saber si podemos cambiar la cámara que tenemos seccionada como escáner en el momento de la llamada a la función.
  • currentCamera
    • Number
    • Con esta variable podremos saber qué cámara estamos usando en este momento.

 

Y cómo en todos los artículo, el tutorial en vídeo para los más ganduletes...

 

 

Bueno lector, pues hasta aquí hemos llegado. Antes de despedirme decirte que te pases por el círculo, si es que no lo has hecho ya, en este enlace. Se trata de una comunidad online que estoy montando alrededor de esta genial disciplina que es la programación.

Y por lo demás, no mucho más que contar. Me despido hasta el siguiente artículo y hasta entonces, que vaya bien :)

 

Otros artículos que te pueden interesar

Call Directory Ionic - ¡Qué es y cómo se usa!

¿Necesitas que tu usuario acceda a su directorio de llamadas y contactos desde tu aplicaci...

Ionic Keyboard | Con ejemplos claros y sencillos

¿Necesitas recoger información del usuario, la lógica del teclado natural no...

Firebase en Ionic - Qué es y cómo puedes utiliz...

¿Pensando en integrar Firebase dentro de tu app hecha en Ionic? O, quizás, ya lo ha...

Ionic Loading | Muestra el progreso de los que ...

¿Quieres mostrar un cuadro de dialogo a tus usuarios cúando, por ejemplo, hagas pet...

Ionic Email Composer | Aprende cómo usarlo aquí

¿Pensando en incluir funcionalidades de envío y composición de emails con Io...

FCM Ionic | Aquí te enseño a usarlo cómo un PRO

¿Quieres enviar notificaciones Push en tu aplicación Ionic mediante FCM Ionic c&oac...

Ionic Bluetooth | Qué es y cómo tu puedes utili...

¿Quieres envair y recibir información con otro dispositivo desde tu app hecha en Io...

OneSignal Ionic | La guía más completa disponib...

¿Interesado en incluir notificaciones push en tu app hecha en Ionic? O, quizás, lo ...

Ionic Slider con ejemplos claros y prácticos

¿Quieres hacer un step by step, o montar un carrousel de imágenes en tu app? O, tal...