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!
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.
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.
Ahora veamos en que dispositivos podemos usar el módulo y escanear los qr code.
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.
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>
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.
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
Veamos ahora cómo podemos utilizar esta instancia, y que funciones pones a nuestra disposición la clase QRScanner.
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.
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”.
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.
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.
Fuerza a que el dispositivo encienda el flash para utilizarlo cómo linterna.
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.
Lo opuesto al método “enableLight”. Este apaga el flash la luz.
Cómo su propio nombre indica, fuerza al sistema a utilizar la cámara frontal en lugar de la trasera.
Lo opuesto al método anterior, fuerza al sistema a usar la cámara trasera.
Nos permite definir la cámara a usar de manera dinámica. Siendo “0” la cámara trasera y “1” la cámara frontal.
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.
Lo opuesto al método anterior, nos permite quitar la pausa a la previsualización.
En caso de que tengamos que consultar los permisos de la cámara, aquí está la función.
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.
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.
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.
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 :)