La base del tutorial la he sacado de aquí, aunque me surgieron algunos problemas más que no están comentados en ese, así que me he animado a hacer este.
Lo que se explica aquí esta probado para la revisión 2099 e inferiores del proyecto zXing, para versiones posteriores desconozco si funciona.
Obtener zXing
Puedes bájarte directamente (password zxing) el proyecto configurado (revisión del repositorio 2099 y el SDK con android 4.0).
Este proyecto tiene las mejoras de cambiar tamaño rectángulo cámara (simular cuadrado para QR), eliminar botón de menús y eliminar texto de estado para modo portrait, no elimina la pregunta de que aplicación usar. Bajalo desde la siguiente dirección, tendrás que importarlo desde eclipse creando un nuevo proyecto android desde un existing source.
Link alternativo
Y ve directamente a la sección de enlazar zXing con tu aplicación.
O sigue las siguientes instrucciones:
Como dice el tutorial anterior, lo primero es obtener el /core y /android del proyecto zXing, que son los que nos harán falta para usarlos en nuestra aplicación, para ello los descargamos desde el repositorio de svn de google code, tal y como explique en el anterior tutorial sobre la configuración de la librería.
Configuración como librería
Ahora bien, la cosa está en que necesitamos meter la parte de /android como un proyecto dentro de nuestro eclipse, y de la manera que explicamos antes no ocurre eso, sino que lo tenemos to ahí apegotonao en un proyecto llamado svn, pero podemos aprovecharlo! ¿Cómo? Muy fácil, copiando el proyecto de /android desde el explorador de Windows a otra carpeta, para tenerlo separado.
Una vez hecho eso, nos vamos al eclipse y elegimos crear un nuevo proyecto de android, escribimos en el nombre zXing por ejemplo, y elegimos la opción de crearlo desde un existing source y finish.
La cruz roja no os debería salir xD |
Ahora con el proyecto creado pinchamos con botón derecho y elegimos team>disconnect y yes, para que nos limpie todo el tema de svn, que no nos interesa tenerlo molestando. Si no os da la opción de disconnect mejor, no teneis que hacer este paso xD.
Aparcamos nuestro proyecto eclipse recién creado y nos vamos a compilar el /core, para ello podemos hacer lo mismo que expliqué en el manual anterior de configuración, navegamos hasta la ruta del core y ant clean build-no-debug, o ant build export para versiones recientes y así tendremos nuestro core.jar.
A continuación nos vamos a configurar el build-path (pincha encima del proyecto con botón derecho>build path>configure build path)y le damos a añadir external jars y metemos el core.jar que acabamos de compilar.
Ahora pinchamos con botón derecho en el proyecto>propiedades>android y marcamos el checkbox de abajo que pone Is library. Porque vamos a usar nuestro proyecto como una librería.
Tras este paso, si no os da estos problemas, sois afortunados, porque a mi si que me los dio!
Solución algunos problemas
Solución algunos problemas
Primero, una opción en el manifest del proyecto, la de android:xlargeScreens="true", no sé porque me petaba el proyecto (por algo del SDK 2.2), así que coméntala si es necesario para que no de por culo.
Ahí no acaba la cosa, ahora tendrás un error al haber convertido el proyecto en librería, los cases de los switchs te darán error, ¿Por qué? Por esto, para arreglarlo situa el ratón encima de cada switch (thx zoack xd), y pulsa control+1, y elige la opción de convertir los switchs en ifs, y esto estará listo.
Añado un aporte que Juan Carlos hizo en los comentarios, si tras esto algunos @overrides te dan errores, prueba a bajar la versión de JDK a la 1.6.
Añado un aporte que Juan Carlos hizo en los comentarios, si tras esto algunos @overrides te dan errores, prueba a bajar la versión de JDK a la 1.6.
Si te sigue dando algún error, elige Project>clean para que regenere el R.java y ya debería funcionar!
Enlazar zXing con tu proyecto
Hemos acabado de configurar la librería, ahora nos vamos a configurar nuestro proyecto de aplicación, asi que botón derecho>propiedades>android y abajo del todo elegimos la opción de add y debería aparecer nuestra librería zXing recién creada, la añadimos.
Además también tenemos que añadir el core.jar al build-path, como hicimos con el proyecto de la librería zXing.
(Si has saltado a este paso directamente y estas usando mi proyecto subido, asegúrate de que en el proyecto de la librería zXing está el core.jar en el build-path y que en la sección de android esta marcado como Is Library )
(Si has saltado a este paso directamente y estas usando mi proyecto subido, asegúrate de que en el proyecto de la librería zXing está el core.jar en el build-path y que en la sección de android esta marcado como Is Library )
Ahora en tu aplicación, que tu botón lance esto:
Intent intent = new Intent("com.google.zxing.client.android.SCAN"); intent.putExtra("SCAN_MODE", "QR_CODE_MODE"); startActivityForResult(intent, 0);
Y el siguiente método para obtener los resultados desde la misma activity:
public void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == 0) { if (resultCode == RESULT_OK) { String contents = intent.getStringExtra("SCAN_RESULT"); String format = intent.getStringExtra("SCAN_RESULT_FORMAT"); // Handle successful scan } else if (resultCode == RESULT_CANCELED) { // Handle cancel } } }
Por ultimo tenemos que añadir en el manifest de tu aplicación la información sobre el SCAN de zXing, asi que pega esto:
<activity android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:configChanges="orientation|keyboardHidden" android:name="com.google.zxing.client.android.CaptureActivity" android:screenOrientation="landscape" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:windowSoftInputMode="stateAlwaysHidden" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <intent-filter > <action android:name="com.google.zxing.client.android.SCAN" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
Por último dale permisos a tu aplicación para usar la cámara con esto:
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
Prueba a añadir también lo siguiente si la cámara te da problemas, no se abre, se cierra con error, etc, las primeras veces que lo use no me resulto necesario, pero la última vez que lo probé, con esto se me arreglaron los problemas.
<uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" /> <uses-feature android:name="android.hardware.touchscreen" android:required="false" /> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" />
Bien, con esto ya lo tendrás funcionando pero hay 3 cosas que aún se pueden mejorar.
Mejoras extra
Primero, cuando pulses el botón de menú dentro del scanner, te aparece un menú de opciones, el cual si pulsas alguna opción petará, además el nombre de la aplicación del scanner sobreescribirá el tuyo, y por último cada vez que pulses el botón se te dará la opción de que aplicación usar para escanear el código, resultando un tanto molesto ¿Como arreglar estos problemas?
Para lo del menú, tan fácil como irnos al CaptureActivity.java del paquete com.google.zxing.cient.android y comentar 3 métodos, el onCreateOptionsMenu(Menu menu), el onPrepareOptionsMenu(Menu menu) y el onOptionsItemSelected(MenuItem item), con eso eliminaremos la función de menú.
Para lo del nombre, nos vamos a res/values/ y para los strings.xml cambiamos el string app_name por el de nuestra aplicación, eso deberíamos hacerlo para todas las carpetas values-xx, o borralas todas y dejar solo la de values..., según la gana que tengas xD.
Edito:
En principio la idea de tener varias values-xx, es para personalizar los distintos strings.xml en función del idioma del dispositivo, pero si solo quieres el nombre de tu aplicación o no te interesa traducir los textos a distintos idiomas, basta con tener tu values/strings.xml.
En la librería zXing sí usan este sistema de traducción, así que si quieres mantener tu nombre de aplicación para un dispositivo en español por ejemplo, tendrías que modificar el strings.xml de la values por defecto, y la de la values-es, pero si el dispositivo esta en inglés te seguiría saliendo lo de Barcode Scanner, por que pillaría el values-en/strings.xml.
Conclusión, si quieres que se mantenga para todas tienes 2 opciones, o borras todas las values-xx, como mencionó arriba, o modificas individualmente cada app_name de cada xml.
La ventaja de la primera, más rapidez, pero si usas algo más de librería zXing que pille un string del strings.xml, solo saldrá el que tengas (que por defecto es inglés), así que tu decides.
En la librería zXing sí usan este sistema de traducción, así que si quieres mantener tu nombre de aplicación para un dispositivo en español por ejemplo, tendrías que modificar el strings.xml de la values por defecto, y la de la values-es, pero si el dispositivo esta en inglés te seguiría saliendo lo de Barcode Scanner, por que pillaría el values-en/strings.xml.
Conclusión, si quieres que se mantenga para todas tienes 2 opciones, o borras todas las values-xx, como mencionó arriba, o modificas individualmente cada app_name de cada xml.
La ventaja de la primera, más rapidez, pero si usas algo más de librería zXing que pille un string del strings.xml, solo saldrá el que tengas (que por defecto es inglés), así que tu decides.
Para lo tercero tenemos que modificar 3 archivos, primero el Intents.java de com.google.zxing.client.android, cambiando el String ACTION de Scan com.google.zxing.client.android.SCAN a la de tu proyecto, por ejemplo, si tu proyecto esta en com.pepino.prueba, tendrás que ponerlo como com.pepino.prueba.SCAN, este mismo cambio hay que hacerlo en el nombre del intent-filter ACTION del manifest.xml de la librería de zXing y también en el de tu proyecto, NO CAMBIAR el nombre de la actividad asociada en el android:name. Y por supuesto ahora cuando llames al Intent de scaneo debes hacerlo con tu nuevo ACTION, es decir, com.pepino.prueba.SCAN.
Por cierto, si vais a leer códigos qr, quizás os interese modificar en com.google.zxing.client.android.camera la actividad CameraManager.java, el método getFramingRect(), la línea de:
int width = screenResolution.x * 3 / 4;
cambiando el 3 por un 2, así conseguiremos que el rectángulo que se forma para reconocer los códigos parezca más un cuadrado xD, un tanto cutre pero funciona.
Otra mejora interesante para los QRadictos, por defecto el layout de la cámara del zXing está hecho para que se use en modo landscape, pero si queremos por ejemplo leer solo códigos QR (como es mi caso), puede que nos interese ponerlo en modo portrait.
Tras investigar por la librería no encontré una manera rápida de hacer esto (por lo que tuve viendo requeriría bastante curro, si alguien encuentra una forma fácil que lo comente!), así que se me ocurrió a probar a leer un código directamente poniendo el móvil en forma portrait, aunque el layout sigue siendo landscape y... funciona igual!
Así que el único problema que tenía era el texto de estado que aparece a la izquierda, pero por suerte android tiene un setVisibility(), así que tan fácil como irnos al CaptureActivity.java, al método onCreate(Bundle icicle) y añadir justo debajo de la línea:
statusView = (TextView) findViewById(R.id.status_view);
la siguiente:
statusView.setVisibility(View.INVISIBLE);
Para la revisión 2099 y probablemente posteriores, esta línea hay que añadirla modificando el método resetStatusView(), donde pone a Visible el statusView, ponerlo a INVISIBLE, y listo.
En el método onCreate comenta la línea siguiente para evitar que lance la ayuda.
showHelpOnFirstLaunch();
Si queréis cambiarle el sonido al "obturador" de la cámara, para ello nos vamos al BeepManager.java al método buildMediaPlayer(Context activity) a la línea de :
AssetFileDescriptor file = activity.getResources().openRawResourceFd(R.raw.beep);//beep original
Y cambiamos el R.raw.beep por nuestro sonido, que tenemos que haber puesto previamente en el directorio raw, y accedemos a él con R.raw.nombre, así de fácil tendremos nuestro sonido custom!
Errores Comunes
E/AndroidRuntime(848): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.google.zxing.client.android.SCAN
Estas lanzando el Intent del scanner con un nombre de ACTION incorrecto, que no se corresponde con el que aparece en el manifest de tu proyecto, en el de la librería zXing o en el de la clase Intents.java . Dicho ACTION debe ser igual en todos los sitios. Por defecto es "com.google.zxing.client.android.SCAN"
E/AndroidRuntime(946): java.lang.VerifyError: com.google.zxing.client.android.CaptureActivity
El core.jar que has importado al proyecto de tu aplicación no se corresponde con la versión de la librería zXing.
E/AndroidRuntime(1214): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.android.prueba/LINEAMODIFICADA.CaptureActivity}: java.lang.ClassNotFoundException: LINEAMODIFACADA.CaptureActivity in loader dalvik.system.PathClassLoader[/data/app/com.android.prueba-1.apk]
La línea del manifest de tu proyecto que indica que clase esta asociada al intent action que lanzas no esta bien configurada, debe ser esta: android:name="com.google.zxing.client.android.CaptureActivity". En el ejemplo de arriba el error sería LINEAMODIFICADA.
class-not-found-when-using-zxingz
Usando la tercera solución de este link, el compañero Rafa consiguió arreglarlo:
http://stackoverflow.com/questions/11959091/class-not-found-when-using-zxing
Explicación en ingles:
Your jar is not in the /libs folder. This happens when you have added the jar to the build path, but newer versions of ADT need it to be in /libs. Put it there and re-add it to the build path.
Un saludo!