martes, 8 de mayo de 2012

zXing - Creación de Códigos QR

Este tutorial se ha probado con la rev2099 de zXing, desconozco si funciona con posteriores.

Antes que nada, si eres nuevo en zXing leete estas entradas que le he dedicado:

http://jstyl8.blogspot.com.es/2011/10/zxing-libreria-java-para-procesado-de.html

http://jstyl8.blogspot.com.es/2011/10/como-anadir-libreria-zxing-tu-proyecto.html

Ahora que ya estás puesto al tanto, tienes tu proyecto de zxing configurado en tu eclipse, y tas peleao algo con la libreria, empecemos.

Me surgió la necesidad de generar códigos QR, y he descubierto 2 formas de hacerlo, una usando Intents desde la librería de zXing, y otra usando directamente la clase QRCodeEncoder.

Clase QRCodeEncoder

Esta clase se encuentra en el paquete com.google.zxing.client.android.encode, pero curiosamente tiene permisos package, con lo que no podemos usarla desde nuestro proyecto directamente, pero como tenemos el código fuente, podemos modificarla poniendole el modificarlo public a ella, al constructor, y al método encodeAsBitmap().

Una vez cambiada, nos creamos una clase de prueba, que tenga una activity como propiedad, que se inicialice por ejemplo en el constructor, e importamos estas clases:

import com.google.zxing.WriterException;
import com.google.zxing.client.android.encode.QRCodeEncoder;
import android.view.Display;
import android.view.WindowManager;
import android.content.Context;


El constructor podría ser tan simple como esto:

public Miclase(Activity activity) {
    this.activity = activity;
  }

Además nos creamos este método:

/**
 * Obtiene un Bitmap del qr a partir de un texto
 * 
 * @param text
 *            el texto string a codificar
 * @return el bitmap que representa el text
 */
public Bitmap getQR(String text) {

 // Para establecer tamaño
 WindowManager manager = (WindowManager) this.activity
   .getSystemService(Context.WINDOW_SERVICE);
 Display display = manager.getDefaultDisplay();
 int width = display.getWidth();
 int height = display.getHeight();
 int smallerDimension = width < height ? width : height;
 smallerDimension = smallerDimension * 7 / 8;

  // Para info de encode
 Intent intent = new Intent();
 intent.setAction("com.google.zxing.client.android.ENCODE");
 intent.putExtra("ENCODE_TYPE", "TEXT_TYPE");
 intent.putExtra("ENCODE_DATA", text);

 // Encode
 Bitmap bitmap = null;
 QRCodeEncoder qrCodeEncoder = null;
 try {
  qrCodeEncoder = new QRCodeEncoder(this.activity, intent,
    smallerDimension, false);
  bitmap = qrCodeEncoder.encodeAsBitmap();
 } catch (WriterException e) {
  e.printStackTrace();
  return null;
 }
 return bitmap;
}

Ahora tan simple como crearnos un objeto de la clase que hayamos creado y llamar a este método, y asignarselo a un Bitmap con el que podemos hacer lo que queramos.

Todo el código para calcular smallerDimension (el tamaño del qr) es sacado de zXing.

Mediante Intents

Esta forma es similar a como usabamos la cámara para capturar qrs, podemos crearnos otro método en la misma clase que hemos creado antes, tal que así:
/**
 * Shares the given text by encoding it as a barcode, such that another user
 * can scan the text off the screen of the device.
 * 
 * @param text
 *            the text string to encode as a barcode
 */
public void verQR(String text) {
 Intent intent = new Intent();
 intent.setAction("com.google.zxing.client.android.ENCODE");
 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
 //No necesario por defecto pilla QR_CODE
 //intent.putExtra("ENCODE_FORMAT", BarcodeFormat.QR_CODE.toString());
 intent.putExtra("ENCODE_TYPE", "TEXT_TYPE");
 intent.putExtra("ENCODE_DATA", text);
 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
 this.activity.startActivity(intent);
}

Y modificamos nuestro manifest:

<!-- Activity del zXing para Encode -->
        <activity
            android:name="com.google.zxing.client.android.encode.EncodeActivity"
            android:stateNotNeeded="true" >
            <intent-filter >
                <action android:name="com.google.zxing.client.android.ENCODE" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

Ahora tan solo usar el método verQR() y se te abrirá una activity con el qr en pantalla.

Podemos meterle algunas mejoras, exactamente igual que hacíamos con el lanzamiento de la cámara.

En la clase com.google.zxing.client.android.encode.EncodeActivity, podemos comentar los métodos onCreateOptionsMenu() y onOptionsItemSelected(), para evitar que aparezca el menú de opciones, y también podemos cambiar el Action de lanzamiento, para que no pregunte por que aplicación usar para generar el QR, tal y como hacíamos en el otro tutorial, en este caso es la variable Intents.Encode.ACTION, y los correspondientes intent-filter action de cada manifest.

Nada más, he omitido algunas partes para que quede más compacto, si os surge algún problema dejarme un comentario e intentaré echaros una mano.

Un saludo!

5 comentarios:

  1. hola que tal disculpa podrias subir el codigo unido en el proyecto te agradesco de ante mano

    ResponderEliminar
    Respuestas
    1. En el segundo tutorial que pongo tienes la librería prácticamente configurada, los cambios que menciono en este tutorial consisten en cambiar 4 líneas, no me seáis perros xD.

      Un saludo.

      Eliminar
  2. mediante intents (public void verqr)

    ese codigo en donde va?

    ResponderEliminar
    Respuestas
    1. Sería un método de la clase de utilidad que menciono en la parte anterior.

      Eliminar

Ponte un nombre aunque sea falso, que Anó-nimo queda mu feo :(