Integrar Barcode Scanner en nuestra aplicación Android

19
49628

Integrar Barcode Scanner en nuestra aplicación Android

0. Índice de contenidos.

1. Introducción

En este tutorial, vamos a ver como podemos leer códigos qr desde nuestra aplicación de Android.

Para quien no conozca qué son los códigos QR, comentaré de forma reducida que, son códigos de barra en los que
cabe bastante más información que en los códigos de barra tradicionales. Seguramente os sonará la siguiente imagen.

Para realizar la lectura de los códigos, vamos a utilizar una aplicación que problablemente ya conoceréis: Barcode Scanner, que para mi gusto y con permiso de Goggles (aunque ésta es capaz de reconocer objetos), es la mejor aplicación para leer códigos de este tipo.

2. Entorno

  • Hardware
    • Mackbook Pro
      • Intel Core i7 2Ghz
      • 8GB RAM
      • 500GB HD
      • Sistema Operativo: Mac OS X (10.8.2)
    • Galaxy Nexus
      • Android 4.1.1 (Jelly Bean).
  • Software
    • IntelliJ 11 Ultimate

3. Desarrollo de la aplicación.

Manos a la obra:

El primer detalle es que no tenemos que indicar ningún permiso en el fichero AndroidManifest.xml de la aplicación, ya que nuestra aplicación no va a acceder a ningún recurso, sólo lanzaremos un intent que hará el trabajo por nosotros. Nota: Si vuestra aplicación necesita acceder a la cámara o a internet, tendréis que añadir igualmente los permisos en el AndroidManifest.xml.

El segundo paso es agregar un par de clases a nuestro proyecto. Estas dos clases son:

Y ahora os voy a poner ya el código, para que veáis de qué forma tan sencilla podemos leer un código qr :).

Empezamos por el código de la vista:

  
             //oculto para facilitar la lectura  
  
      
  
      
        //oculto para facilitar la lectura  
  
      
  
      
        //oculto para facilitar la lectura  
      
  
 

Si os fijáis en el layout, tenemos un botón (ImageButton) y dos TextView. El botón lo usaremos para iniciar el intent que lanzará la aplicación encargada de leer el qr-code. Los dos TextViews los usaremos para mostrar la lectura.

Y terminos con el código que ejecuta la acción. Aquí esta toda la clase del Activity (excepto los imports).

public class QrReaderActity extends Activity {  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        configureButtonReader();  
    }  
  
    private void configureButtonReader() {  
        final ImageButton buttonReader = (ImageButton)findViewById(R.id.btReader);  
        buttonReader.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View view) {  
                new IntentIntegrator(QrReaderActity.this).initiateScan();  
            }  
        });  
    }  
  
    @Override  
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {  
        final IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);  
        handleResult(scanResult);  
    }  
  
    private void handleResult(IntentResult scanResult) {  
        if (scanResult != null) {  
            updateUITextViews(scanResult.getContents(), scanResult.getFormatName());  
        } else {  
            Toast.makeText(this, "No se ha leído nada :(", Toast.LENGTH_SHORT).show();  
        }  
    }  
  
    private void updateUITextViews(String scan_result, String scan_result_format) {  
        ((TextView)findViewById(R.id.tvFormat)).setText(scan_result_format);  
        final TextView tvResult = (TextView)findViewById(R.id.tvResult);  
        tvResult.setText(scan_result);  
        Linkify.addLinks(tvResult, Linkify.ALL);  
    }  
} 

Lo que hay que destacar de este código están en las líneas:

  • 15: Lo que hace es inicializar el Intent que las propiedades que necesita para que se ejecute Barcode Scanner. Al no pasar parámetros, intentará leer todos los tipos diferentes de códigos de barra que es capaz. Además es importante que especifiquemos nuestro activity, para que luego podamos gestionar el resultado de la lectura.
  • 20 a 24: Cuando llamamos a initiateScan(), lo que hace es empezar un Activity con startActivityForResult. Entonces si redefinimos el método onActivityResult, podemos gestionar el resultado. En este caso instanciamos un IntentResult parseando el intent que hemos recibido. Esta clase nos ayuda a extraer el resultado del intent.
  • 28: Extraemos el resultado del IntentResult con scanResult.getContents() y scanResult.getFormatName() y lo pintamos en la pantalla.

Como diría un profesor que tuve de la carrera: Facilote, facilote!! 😛

Para que veáis que no os engaño, os muestro unas capturas del proceso 🙂



4. Detalles a tener en cuenta.

La implementación que hemos hecho, nos obliga a tener instalado Barcode Scanner en el dispositivo. Si intentamos ejecutar nuestra aplicación, nos saldrá un alert indicando que no lo tenemos instalado y preguntándonos si lo queremos instalar. ¿Que ocurre si tenemos otras aplicaciones que son capaces de leer códigos qr y no queremos instalar otra más?

El comportamiento de la aplicación que acabamos de hacer se debe a la clase que hemos utilizado. Si lo que queremos es que el teléfono nos muestre una lista de las aplicaciones disponibles, tendremos que hacerlo de la siguiente manera.

private void configureButtonReader() {  
    final ImageButton buttonReader = (ImageButton)findViewById(R.id.btReader);  
    buttonReader.setOnClickListener(new View.OnClickListener() {  
        @Override  
        public void onClick(View view) {  
            try {  
                //new IntentIntegrator(QrReaderActity.this).initiateScan();  
                Intent intent = new Intent("com.google.zxing.client.android.SCAN");  
                intent.putExtra("SCAN_MODE", "QR_CODE_MODE");  
                startActivityForResult(intent, 0);  
            } catch (ActivityNotFoundException exception) {  
                Toast.makeText(viewGroup.getContext(), "Error", Toast.LENGTH_SHORT).show();  
            }  
        }  
    });  
} 

y

@Override  
public void onActivityResult(int requestCode, int resultCode, Intent data) {  
    super.onActivityResult(requestCode, resultCode, data);  
    if((requestCode == 0) && (resultCode == -1)) {  
        updateUITextViews(data.getStringExtra("SCAN_RESULT"), data.getStringExtra("SCAN_RESULT_FORMAT"));  
    } else {  
        Toast.makeText(viewGroup.getContext(), "Error", Toast.LENGTH_SHORT).show();  
    }  
}

Lo que hemos hecho es comentar la clase que usábamos para lanzar el intent y hemos creado el nuestro. El problema de esto es que tenemos que gestionar nosotros que ocurre en caso de qué no haya ninguna aplicación disponible y parsear nosotros el intent devuelto por la aplicación.

Os muestro una captura para que veáis lo que mostraría en mi caso

5. Conclusiones.

Si la aplicación que estamos desarrollando, necesita recibir datos del exterior, quizás sea una opción el que los recoja de códigos qr, ya que hemos visto que con muy poco esfuerzo, nuestra aplicación será totalmente capaz de leer estos códigos.

Para cualquier comentario, duda o sugerencia, tenéis el formulario que aparece a continuación.

Un saludo.

19 COMENTARIOS

  1. Buen tutorial Francisco.

    Un par de apuntes en el método onActivityResult:

    a) la comprobación podría mejorarse con las constantes estáticas de Activity:

    if (resultCode == Activity.RESULT_CANCELED) {

    } else if (resultCode == Activity.RESULT_OK) {

    }

    b) De cara a futuras modificaciones, se debe verificar que el requestCode es igual al que lanzo la actividad (en el ejemplo el 0 startActivityForResult(intent, 0))

    Un saludo

  2. Hola Carlos.

    Gracias por los apuntes, tienes toda la razón.

    Lo añadí por intentar completar un poco el tutorial y no le presté demasiada atención.

    Un saludo.

  3. Hola tengo problemas con las clases
    IntentIntegrator
    IntentResult
    Me las marca en rojo el Eclipse se descargan de algun lugar o son porque no tengo instalado una aplicacion que lee codigos QR?? y otra pregunta se puede probar desde el emulador ??
    de antemano gracias y gran tutorial (Y)

  4. Hola Zod_Eren

    Gracias por el comentario.

    Esas dos clases que te marca eclipse en rojo es porque no las has agregado al proyecto. Los enlaces que hay en el punto 3 ya no son válidos porque el autor de la librería a migrado el proyecto a github. El enlace en donde se encuentra es:
    https://github.com/zxing/zxing/tree/master/android-integration/src/main/java/com/google/zxing/integration/android

    Tienes que bajarlas y agregarlas a tu proyecto.

    Desde Eclipse en principio no vas a poder probarlo al menos de forma completa. Vas a poder probar que dandole al botón se abra la aplicación para escanear pero no vas a poder hacer mucho más. Se supone que puedes configurar la webcam de tu ordena para que se use como cámara en el emulador, pero es algo que a mí nunca me ha funcionado. Si te funciona tu webcam como cámara para el emulador, podrás probarlo, si no, solo verás un recuadro gris.

  5. Muchas gracias por la respuesta :
    fjarroyo

    si no fuera mucha molestia una pregunta mas :
    el nombre que le das en el proyecto a tu MainActivity es QrReaderActity??? osea en la linea 15 en lugar de poner new IntentIntegrator(QrReaderActity.this).initiateScan();
    pongo new IntentIntegrator(EL_NOMBRE_DE_MI_ACTIVITY.this).initiateScan();
    que en este caso seria MainActivity.this etc ….
    de antemano muchas gracias por tu ayuda y por responder 🙂

  6. estoy iniciando en android y encuentro muy interesante este tutorial, para mis inicios, me gustaria conocer como salvar esta información en una hoja de excel o un archivo de texto. muchas gracias nuevamente por el tutorial

  7. Hola,
    Muy interesante este tutorial. Pero si necesito escanear no sólo códigos qr si no tb documentos como tendría que hacerlo? Y escaneando un documento podría reconocer lo que está escrito en el.
    Espero puedas contestar a estas preguntas y de toda forma gracias por adelantado.
    Hasta pronto

  8. Hola Buenos Días.
    Estoy probando la aplicación, pero me da los siguientes errores, soy un poco novato y no encuentro la solución, podrías ayudarme??? Gracias

    Lo estoy probando con un movil Vodafone Smart Prime con android 5

    E/chromium: [ERROR:browser_gpu_channel_host_factory.cc(258)] Failed to init browser shader disk E/libEGL: validate_display:255 error 3008 (EGL_BAD_DISPLAY)

  9. Hola Muy buen tutorial pero tengo una pregunta.
    ¿ se puede o que posibilidades hay de que en vez de escanear un codigo QR me escanee otra imagen y me muestre lo que yo quiero?

  10. Muchas gracias por este aporte.
    Tengo la misma pregunta que Linner Salinas Grados:

    el nombre que le das en el proyecto a tu MainActivity es QrReaderActity??? osea en la linea 15 en lugar de poner new IntentIntegrator(QrReaderActity.this).initiateScan();
    pongo new IntentIntegrator(EL_NOMBRE_DE_MI_ACTIVITY.this).initiateScan();
    que en este caso seria MainActivity.this etc ….

    Porque hay una linea donde apunta a un layout «main»

    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    configureButtonReader();
    }
    y de esta manera genera error.

    lo correcto no es…?:

    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_qr_reader_actity);
    configureButtonReader();
    }

    o hay más de un layout?
    Gracias!!!

  11. hola muy buen tutorial, tengo la siguiente consulta, si quiero recoger lo que me entrega el codigo qr a un textfield como podria hacerlo

  12. Hola, estoy intentando hacer un lector personalizado, osea con mi propio logo etc etc, pero lo que veo de este tutorial (es cual es muy bueno) es que es necesario instalar el barcode el mismo play store, habra alguna forma que no sea necesario hacer eso? osea que la app ya tenga integrado el barcode para no tener que descargarlo

  13. Hola. Muy buen trabajo, me gustó y ayudo mucho. Lo realicé y salió a la perfección. Ahora mi duda es: Cómo poner los datos separados de mi resultado del escáner.?
    Mi resultado sale en una linea y es algo asi como: nombre : Dario, Apellido: Flores, edad: 34.
    Esos datos quiero que salgan separados.
    ¿Hay alguna forma?

  14. Hola, soy novato en App, y comence con la IDE oficial de Google Android studio 2.2 no puedo distingir cual es el archivo principal xml..gracias

  15. excelente tutorial, tengo una observacion como puedes hacer que sea mas rapido la lectura en telefonos y tablet que no tengo flash ?

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad