viernes, 17 de febrero de 2017

ZXing.Net.Mobile for Forms, una librería para escanear códigos de barras, QRs y más

¡Hola! En la entrada de esta semana te hablaré acerca de ZXing.Net.Mobile for Forms, el cual es una librería basada en otra librería de código abierto para escanear códigos de barras llamada ZXing (Zebra Crossing) y que hace uso del ZXing.Net.Port.

Esta librería funciona para diversos proyectos .NET, incluyendo por supuesto, Xamarin (Forms, Android, iOS, Windows Phone, UWP...) y reduce el esfuerzo para implementar un scanner de códigos de barras, QRs y más en nuestros proyectos multiplataforma.

¡A continuación te explico qué fácil es utilizar esta librería!

Paso 1. Crea un proyecto de tipo Xamarin.Forms Portable. Para este caso, he puesto el nombre ScannerZXing.


Paso 2. Da clic derecho en la solución y elige Administrar Paquetes Nuget para la Solución




Paso 3. Busca el paquete ZXing.Net.Mobile.Forms y agrégalo a todos los proyectos de tu solución que vayas a manejar.


Paso 4. Debes inicializar el renderer de plataforma específica en cada proyecto donde hayas agregado el paquete. Siempre será después del Init de Xamarin.Forms y la instrucción a colocar es ZXing.Net.Mobile.Forms.Plataforma.Platform.Init(); donde Plataforma es reemplazado por Android o iOS, según el caso.

Por ejemplo, para Android debes agregar dicha instrucción en el MainActivity; en el caso de iOS, es en AppDelegate:


Nota. En el caso de Android, además debes sobreescribir método OnRequestPermissionsResult debido a la actualización del manejo de permisos desde Android Marshmallow:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
    global::ZXing.Net.Mobile.Forms.Android.PermissionsHandler.OnRequestPermissionsResult (requestCode, permissions, grantResults);           
}

Para UWP y Windows Phone, busca el archivo App.xaml.cs de cada plataforma específica y agrega la instrucción ZXing.Net.Mobile.Forms.Plataforma.ZXingScannerViewRenderer.Init(); para inicializar los renderers, donde Plataforma es reemplazada por WindowsUniversal y WindowsPhone, respectivamente:


Paso 5. En el proyecto Portable crea una carpeta llamada Paginas, dentro de la cual agregarás un Forms Xaml Page. En este caso, le he puesto el nombre PaginaMenu:


Paso 6. El código XAML de esta página es muy sencillo, pues simplemente consta de un StackLayout con 3 elementos: Un botón y 2 labels. A continuación te presento el código:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ScannerZXing.Paginas.PaginaMenu">
  <StackLayout BackgroundColor="White">
    <Button Text="Escanear código" HorizontalOptions="CenterAndExpand" 
            TextColor="White" FontSize="20" BackgroundColor="Black" x:Name="btnEscanear" Clicked="btnEscanear_Clicked" />
    <Label Text="Resultado" HorizontalOptions="StartAndExpand" 
           TextColor="Black" FontSize="20" />
    <Label Text="N/A" HorizontalOptions="StartAndExpand" 
           TextColor="Blue" x:Name="lblResultado" FontSize="24" />
  </StackLayout>
</ContentPage>

La idea es que cuando el usuario presione el botón, se lance el scanner llamando a la aplicación de cámara que viene integrado en tu dispositivo.

Paso 7. Ahora veamos el code-behind, es decir, el código de C# requerido para que la aplicación funcione como esperamos:

using System;
using Xamarin.Forms;
using ZXing.Net.Mobile.Forms;

namespace ScannerZXing.Paginas
{
    public partial class PaginaMenu : ContentPage
    {
        async void btnEscanear_Clicked(object sender, EventArgs e)
        {
            var pagina = new ZXingScannerPage();
            await Navigation.PushAsync(pagina);
            
            pagina.OnScanResult += (resultado) =>
            {
                pagina.IsScanning = false;

                Device.BeginInvokeOnMainThread(async () =>
                {
                    await Navigation.PopAsync();
                    lblResultado.Text = resultado.Text;
                });
            };
        }

        public PaginaMenu()
        {
            InitializeComponent();
        }
    }
}

En el momento en que el usuario dé clic, se crea una página ZXingScannerPage y se muestra en el dispositivo (esto sucede al hacer Push al Stack de Navegación). Entonces, aparecerá una vista con la cámara a manera de scanner que tratará de leer un código de barras y en el momento en que la lectura sea exitosa, retornará a la página que llamó al scanner (PaginaMenu en este caso) y gracias a que manejamos el evento OnScanResult, podremos obtener el valor leído (a veces será una serie de números y letras, otras veces una URL o más información).

Paso 8. En tu archivo App.cs del proyecto portable de Xamarin.Forms indica que PaginaMenu será la página inicial:

public App()
{
     MainPage = new NavigationPage(new Paginas.PaginaMenu());
}

Paso 9. Si vas a hacer tu prueba con el proyecto de Android, tienes que agregar 2 permisos en el AndroidManifest: Camera y Flashlight. Desde Visual Studio, accede a las propiedades del proyecto de Android para habilitar ambos permisos:



Paso 10. ¿Eres de los pocos (pero orgullosos, como yo) poseedores de un dispositivo Windows 8.1/10 (jeje) para hacer tus pruebas? Entonces habilita la Capability Webcam en el Package Manifest (dentro de Properties en el proyecto de UWP o WP) para que la aplicación funcione correctamente:


Paso 11. ¡Listo! Es hora de probar nuestra aplicación. A continuación va un ejemplo de su implementación en una tablet con Android y en un teléfono con Windows 10 (el iPhone, pendiente):

Ejemplo 1: Esta es la pantalla inicial


Si presionamos el botón Escanear código, aparecerá una pantalla con la cámara habilitada y lista para escanear algún código de barras, como en este caso. Alinea la línea roja aproximadamente al centro de tu codigo de barras:


¡Genial! ¡El código de barras respectivo ha sido leido y mostrado en nuestra etiqueta de texto!


Ejemplo 2: Ahora vamos a escanear un código QR de un boleto que tengo.


El código ha sido leido exitosamente y su valor, retornado:


Ejemplo 3: Prueba en Windows 10. Primero, la pantalla inicial.


Cuando damos clic en Escanear código, aparece la cámara lista para buscar algo qué leer.


En este caso, nuevamente leimos un código QR, que devuelve una página web como su valor:


Ejemplo 4: Ahora leeremos otro código de un boleto más, en este caso, uno de tren.

El resultado es un poco extraño, pero válido. Supongo que la información está encriptada precisamente para seguridad y que no haya forma de generar boletos falsos.


Ejemplo 5. Finalmente, escaneamos un ticket del metro de Praga (como no tenía uno a la mano, uso uno de Internet).


Y este es el resultado.


¿Qué tal? Fácil, ¿no? Ahora te toca aplicarla en tus proyectos :)

Por supuesto, puedes descargar el código fuente de mi GitHub dando clic aquí.

Espero que esta entrada haya sido de tu interés. Si te agradó, compártela con tus amigos y espero te sea útil. Si tienes alguna duda, con gusto la puedo atender por este medio.

¡Saludos!

5 comentarios:

  1. Hola Luis
    muchas gracias por la informacion, descargue tu proyecto pero tengo el siguiente error al intentar instalar el paquete nuget de Zxing

    No se pudo instalar el paquete 'ZXing.Net.Mobile 2.1.47'. Está intentando instalar este paquete en un proyecto que tiene '.NETPortable,Version=v4.5,Profile=Profile259' como destino, pero el paquete no contiene referencias de ensamblado o archivos de contenido compatibles con dicho marco. Para obtener más información, póngase en contacto con el autor del paquete. 0


    ¿Sabrias decirme que puedo hacer para instalarlo correctamente?

    Gracias

    ResponderEliminar
    Respuestas
    1. Hola Raúl, tienes que ajustar el profile en las propiedades del proyecto PCL. Revisa si puedes seleccionar las siguientes opciones: https://scontent-amt2-1.xx.fbcdn.net/v/t1.0-9/17265114_1351996688191310_570050424750283778_n.jpg?oh=01611cee76935e8a9470c17c72fe320f&oe=595328D2 No hagas caso a las de iOS/Mac si no lo estás ejecutando desde una Mac, chécalo y me comentas. Disculpa la tardanza de mi respuesta

      Eliminar
  2. Hola!! puedes actualizar el link de la imagen?

    Te lo agradecería mucho, me sale exacto el mismo error

    Gracias!!

    ResponderEliminar
  3. Hola Luis, Gracias por la entrada! sabrías si hay forma con Xamarin de insertar una imagen en el centro de QR? Se que hay quienes lo hacen, pero no solo incrustando una imagen porque no siempre funciona porque "machaca" zona del QR donde hay información, lo he probado y llevo días haciendo pruebas.

    Muchas gracias!

    ResponderEliminar
  4. Hola Luis disculpa pero tienes algo en el proyecto potable para insertar ese código resuelto en sql server

    ResponderEliminar