Interpretación JSONObject

5 Mar

La Base de Datos MongoDB se comunica con la app de Android mediante Strings con un formato en concreto.

Una vez tenemos ese string, hay que pasarlo a JSONObject para después poder recorrerlo y sacar los datos que nos interesen.

Dado el siguiente string de ejemplo:

string ej = {“eventos”: [

     {

          “nombre” : “Concierto ACDC”,

          “lugar” : “Valladolid”,

          “precio” : “40”,

          “personas” : “30”,

          “aforo” : “200”,

          “info” : “Concierto de ACDC en Valladolid a las 22:00”

    },

… // resto de eventos

]

}

sacaremos el JSONObject mediante la siguiente instrucción:

JSONObject jObject = new JSONObject(ej);

Una vez tenemos el Objeto JSONObject lo recorremos y sacamos los datos que nos interesen (en nuestro caso los eventos):

Pasos a seguir:

  1. Sacamos el array (de objetos json)  de los datos (en nuestro caso eventos)  para poder recorrerlo.
  2. Con “getJSONObject(i)” sacamos el objeto en cuestión de una posición del array en concreto.
  3. Como los datos de los eventos son simples (string, int, boolean …) se puede acceder fácilmente a ellos mediante “getString”, “getInt”… De lo contrario si alguno de los datos estuviese compuesto por más datos habría que sacar de nuevo el array (paso 1 otra vez con el nuevo dato)

Un ejemplo práctico sería éste código, en éste caso vamos a ir recorriendo todos los eventos e imprimiendo por pantalla el nombre de cada uno de ellos:

/* siendo bd el string de la cadena que representa el .json */

JSONObject jObject = new JSONObject(bd);

JSONArray eventosArray = jObject.getJSONArray(“eventos”);

JSONObject  eventoObject ;

for (int i = 0; i < eventosArray.length(); i++){

          eventoObject = eventosArray.getJSONObject(i);

          System.out.println(eventoObject.getString(“nombre”).toString());

}

Librería QR web

5 Mar

La librería que vamos a usar para generar códigos QR se llama node-qrcode.  Su código lo podemos encontrar en los servidores de github siguiendo este enlace.

Si leemos el readme encontramos la información básica de su funcionamiento.

La licencia de esta librería es de tipo MIT lo que nos permite usarla, modificarla, etc… a nuestro antojo, ya que esta licencia nos permite que sea software libre o software no libre.

Usos básicos de la librería

Esta librería se puede usar para crear scripts e integrarlos en el código jade que nos permitan la generación de códigos QR en la página , esto seria para el lado del cliente.
La librería también puede ser usada por el lado del servidor, para generar códigos QR y almacenarlos en el servidor como archivos png.
Aparte esta librería se puede instalarse en el terminal para poder usarla por línea de comandos. Así se pueden hacer diversas pruebas como la generación de un código QR y que te lo guarde o que directamente te aparezca por la pantalla del terminal el QR.

Instalación de la librería
Como dijimos la librería se puede integrar en el terminal o añadirla a nuestro proyecto de node. Las instrucciones originales se pueden encontrar aquí. Aun así explicaremos brevemente como hacerlo.

Instalación en el terminal

Instalación para Ubuntu:

  1. Abrimos un terminal.
  2. Necesitamos instalar el siguiente paquete si no lo tenemos:  sudo apt-get install libpixman-1-dev libcairo2-dev
  3. Instalamos la librería para que nos funcione con el siguiente comando: sudo npm install -g qrcode

Instalación en Node:

Instalación para Ubuntu:

  1. Para integrar la librería tendremos que desplazarnos hasta nuestro proyecto usando cd hasta la raíz. En nuestro proyecto será …../Biljet
  2. Una vez ahí ejecutamos el siguiente comando: npm install qrcode
  3. Cuando termine deberíamos tener en node_modules una nueva carpeta llamada qrcode.
  4. Luego tendremos que hacer una copia del archivo qrcode.js, que se encuentra en …/node_modules/qrcode/build. Este archivo lo tendremos que colocar en punto en el que sea visible para nuestra página, ya que sino nuestros scripts no funcionaran. En nuestro caso será …/Biljet/public
  1. Abrimos un terminal

Aparte también vamos a necesitar instalará dos librerías adicionales si no las tenemos, que son canvas y canvasutil. La instalación se hará igual que la de qrcode siguiendo únicamente los 3 primeros paso anteriormente descritos.

 

API de funciones importantes

Estas son las funciones que vamos a necesitar de la libreria:

  • La constructora  QRCodeLib.QRCodeDraw()
  • Para pintar un QR en la página se usa variable.draw(el sitio donde ponerlo, mensaje, función para el error)
  • Para guardar un qr variable.save(ruta de guardado, mensaje,función para el error)

Aparte la librería tiene más funciones que podrían llegar a ser de utilidad para ello consultar el api de la librería.

Ejemplos de uso de la librería
La librería cuenta con una serie de ejemplos que viene en test pero para verlos funcionar usar los que esta en la carpeta “ejemplos de los QR están en test” , ya que tenían alguna errata y ahí están corregidos. Si queréis ejecutarlos seguramente os diga que le faltan algunos módulos usar el npm install de los módulos que falten.

Los dos ejemplos importantes para nosotros serian el clientesideserver que genera un QR en un canvas y puedes cambiar el qr dinámicamente escribiendo el texto en text area.

Y el otro ejemplo sería el save que guarda un QR en la ruta dada por la variable path.

Objetos parcelable

5 Mar

Forma de pasar objetos entre distintas actividades en Android. Una opción sería implementar el objeto con la interfaz Serializable, pero es muy lento para objetos grandes y complejos.

En la práctica los tipos Parcelable son como escribir los tipos en un Bundle y recuperarlos después.

Lo primero es crearnos una clase que implemente la interfaz Parcelable.

Es recomendable añadir un constructor al objeto que reciba un parcel para recrearlo a partir de ahí y un método ReadFromParcel(Parcel in) para rellenar los campos del objeto.

Guardamos el objeto parcel implementando el método writeToParcel(Parcel dest, int flags).

El objeto Parcel nos ofrece unos métodos para guardar los objetos según su tipo (NO EXISTE UN METODO PARA BOOLEANOS,la solución que se nos ofrece es un array de booleanos con un solo valor)

(Para atributos que son objetos de clases que hemos creado, debemos hacer esa clase Parcelable también y utilizar la función WriteParcelable())
{
dest.writeParcelable(fecha, flags);
.
.
.
fecha=in.readParcelable(Fecha.class.getClassLoader());

Fecha.java implementaría también Parcelable( y así recursivamente…)
}

Para recuperar el objeto implementamos el método readFromParcel(Parcel in). Nuevamente el objeto Parcel nos ofrece métodos para leer diferentes tipos.

Para leer listas tipadas es necesario un objeto Parcelable.CREATOR

ej:public static final Parcelable.Creator<Estudiante> CREATOR
   = new Parcelable.Creator<Estudiante>() {
       public Estudiante createFromParcel(Parcel in) {
           return new Estudiante(in);
       }
       public Estudiante[] newArray(int size) {
           return new Estudiante[size];
       }
   };

NOTA: cuando leemos del Parcel hay que leerlo en el mismo orden en que lo escribimos.

Podéis encontrar el tutorial completo en la siguiente dirección:
http://androcode.es/2012/12/trabajando-con-parcelables/

Librería zXing para lectura de códigos QR en Android

4 Mar

La librería zXing es un proyecto open-source (libre de derechos de autor para uso y modificación) que ofrece soporte para la lectura y decodificación para la gran mayoría de códigos de barras, códigos BIDI o QR en múltiples plataformas. En este documento nos centraremos en su versión para Android.

El código se puede descargar desde el siguiente repositorio SVN de Google Code: Libreria zXing

Instalación de la librería:

Nota: Para los ejemplos de este documento, se está usando la versión API 10 del SDK de Android y Eclipse versión Indigo para Windows. En caso de estar utilizando una versión diferente como Helios o Juno, tan solo hay que sustituir las apariciones de un nombre por el de la otra versión

  • Pasos previos:  Para descargar un proyecto SVN en Eclipse, es necesario tener instalado el plug-in Subversive. Si ya dispone de él, puede omitir este paso y el siguiente.
  1. En la ventana principal de Eclipse, pulsar en: Help>Install New Software
  2. En el cuadro que pone Work with elegir:
  3. Expandir el nodo de Collaboration.
  4. Buscar y marcar la casilla de Subversive Team Provider (incubation) y pulsar siguiente
  5. Pulsar Next de nuevo, aceptar la licencia y click Finish. Subversive se descargará y se instalará.
  6. Reiniciar Eclipse para que los cambios surtan efecto.

Instalación subversive SVN Connectors

Además del plug-in son necesarios los SVN Connectors para conectar con el servidor.

  1. En la ventana principal de Eclipse, pulsar en: Help>Install New Software

  2. En el cuadro que pone Work with escribir:  http://community.polarion.com/projects/subversive/download/eclipse/2.0/indigo-site/

  1. Expandir los Subversive SVN Connectors, elige la casilla de Subversive SVN Connectors y de los opcionales, la última versión disponible del SVNKit y pulsar Next

  2. Pulsar Next de nuevo, aceptar la licencia y click Finish. Subversive se descargará y se instalará.

  3. Reiniciar Eclipse para que los cambios surtan efecto.

Con esto ya tenemos todo lo necesario para descargar cualquier proyecto desde un repositorio SVN como el de la librería zXing

 Adquirir y compilar la librería zXing

1.- Descarga la librería desde el repositorio

En este paso obtendremos el código fuente para la creación de la librería desde el repositorio SVN de Google Code en Eclipse

  1. Si no está activa la vista de repositorios (en la parte inferior de la pantalla, en la misma zona que aparece la consola) pulsa en:

  • Window > Show View > Other > SVN > SVN Repositories.
  1. Crear un nuevo repositorio a través de la vista de repositorios: Pulsar en el cilindro con el + verde y añadir a siguiente  URL: http://zxing.googlecode.com/svn/

  2. Cuando aparezca el repositorio en la vista de repositorios, pulsar con el botón derecho en él y pulsar en Check out. Con esto descargaremos todo el código en un nuevo proyecto que se llamará svn.

2.- Obtener Proguard y Ant

Para compilar el código en Android, son necesarias 2 utilidades: Proguard y Ant. Ambas se usan desde la línea de comandos. Proguard sirve para hacer más eficiente el código y la Ant para compilar proyectos java. La ventaja de usar Ant como herramienta para scripts de compilación es que es multiplataforma, con lo que no tenemos que tener distintos archivos de compilación según el SO estemos usando.

  1. Descargamos ambas utilidades desde los enlaces: Proguard y Ant y descomprimimos su contenido.

  2. Vamos a Eclipse y en la carpeta svn que se ha creado con el proyecto descargado, nos dirigimos al subdirectorio trunk.

  3. Buscar el archivo build.properties y modificarlo de la siguiente manera:

    1. Añadir la línea: proguard-jar=X. Donde X es la ruta donde descomprimimos el proguard: e.g.: C:\\proguard4.6\\bin\\proguard.jar)

    2. Añadir la línea: android-home=X. Donde X es la ruta donde se encuentra el SDK de Android: e.g.: C:\\Android\\android-sdk-windows)

  1. Necesitamos añadir y modificar algunas variables de entorno del sistema. Para ello: Botón derecho sobre Equipo > Propiedades > Configuración Avanzada del Sistema > Variables de entorno…

  2. Añadir la variable JAVA_HOME  y como valor añadimos la ruta donde se encuentre instalado el JDK (e.g: C:\Program Files\Java\jdk1.6.0_21)

  3. Añadir la variable ANT_HOME y como valor añadimos la ruta donde se encuentre descomprimido el Ant (e.g.:C:\apache-ant-1.8.2)

  4. Añadir la variable CLASSPATH y como valor escribimos “;” sin las comillas

  5. Modificamos la variable Path añadiendo las 2 rutas de la carpeta bin del JDK y del Ant, separadas por “;”.

       (e.g: C:\Program Files\Java\jdk1.6.0_21\bin;C:\apache-ant-1.8.2\bin)

 3.- Compilar el código de la librería

Para obtener la librería, primero es necesario compilar el core:

  1. Abrimos una consola (Símbolo del Sistema de Windows)

  2. Navegamos (con el comando cd) hasta la ruta del proyecto svn en Eclipse

  3. Accedemos a la carpeta core, donde aparezca el archivo build.xml (Si no aparece, usar el comando dir para verlo). Este archivo lo usa Ant para compilar, por lo que asegurarse de que estamos en la ruta correcta ya que de lo contrario no se compilará correctamente. Cada carpeta posee su propio build.xml.

  4. Ejecutar el comando: ant build export

Así compilamos sin información de debug para que no existan problemas de incompatibilidad con Android

Con estos pasos hechos, si vamos a la carpeta core encontraremos el archivo core.jar que es la librería compilada que después incluiremos en nuestro proyecto.

Incrustar la librería sobre nuestro proyecto

1.- Configuración de la librería

Anteriormente, hemos descargado un repositorio SVN. Este contiene el soporte para varios lenguajes, pero como a nosotros solo nos interesa la parte de Android, vamos a seleccionar que archivos queremos mantener y cuales no interesan

  1. En una ventana del Explorador de Windows, navegar hasta la carpeta que contenga el workspace donde descargamos el repositorio. Accedemos a él (carpeta svn) y después a la carpeta trunk.
  2. Copiamos la carpeta android a nuestro workspace.

  3. Copiar el core.jar compilado en el apartado anterior en:

    1. En la carpeta libs del proyecto BiljetApp y

    2. En la carpeta libs del proyecto copiado en el paso anterior (CaptureActivity)

    • Con este paso, Eclipse debería reconocer el .jar como una librería del proyecto automáticamente. En caso de que no, habría que importarlo manualmente:
    • 1: Botón derecho sobre el proyecto > Build Path > Configure Build Path
    • 2: En la pestaña Libraries, pulsar en Add External JARs… y seleccionar el core.jar
  1. Una vez ubicada la carpeta, volvemos a Eclipse y sobre la vista de proyectos, pulsamos File > Import… > General > Existing projects into a Workspace

  2. En root directory seleccionar la ruta que contiene el workspace actual

  3. Cuando haya cargado la lista de proyectos disponibles que contiene el workspace, pulsa en Deselect All, buscar el proyecto CaptureActivity,  y marcarlo (solo se necesita ese)

  4. Una vez se tenga el proyecto importado, se puede desconectar del SVN: Sobre el proyecto svn y CaptureActivity, pulsar en Team > Disconnect  y después en Yes. Si no aparece, es que ya estaba desconectado.

  5. Ahora que tenemos la parte que nos interesa, ya se puede eliminar el proyecto  svn  del workspace e incluso del disco duro.

  6. Sobre el proyecto CaptureActivity, pulsar Botón derecho > Properties > Android y marcar la casilla IsLibrary. Este proyecto (CaptureActivity) es el que vamos a usar como librería para el nuestro (BiljetApp)

Con estos pasos la librería ya se encuentra configurada para usarla. A continuación se enumeran algunos problemas que pueden surgir

  • Al convertir el proyecto en librería, los case de los switch dan error. ¿Por qué?

Solucion:

Sitúa el ratón en cada switch que esté marcado con error y pulsar CTRL+1 y a

continuación elige la opción de Convert switch to if-then-else

  • Al convertir el proyecto en librería, algunos @override dan error.

Solución:

Prueba a bajar la versión del JDK usado para compilar a la 1.6

Si se siguen encontrando errores, pulsar en Project > Clean… para volver a generar el R.java

2.- Enlazar el proyecto zXing con el nuestro

Ya tenemos la librería configurada para ser usada. Vamos a enlazarla en el proyecto concreto en el que la vamos a usar (BiljetApp)

  1. Sobre el proyecto BiljetApp pulsar Botón derecho > Properties > Android y en el apartado Libraries pulsar sobre Add…. Seleccionamos la librería creada en el paso anterior.

  2. Añadir el siguiente código al botón u objeto que lanzará el escáner de códigos:

  • Intent intent = new Intent(“com.google.zxing.client.android.SCAN”);
  • intent.putExtra(“SCAN_MODE”, “QR_CODE_MODE”);
  • startActivityForResult(intent, 0);
  1. En la misma actividad que incluimos el botón con el intent para lanzar el escáner, situar este método para recoger los resultados:

  • 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
  •      }
  •   }
  • }
  1. Registrar el intent en el android.manifest del proyecto. Añadir:

  • <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>
  1. Añadir también en el manifest  permisos para poder utilizar la cámara del terminal.

  • <uses-permission android:name=”android.permission.CAMERA”></uses-permission>

Con estos pasos la librería ya se encuentra incrustada completamente en el proyecto. A continuación se enumeran algunos problemas que puedan surgir y mejoras que son aplicables:

Problemas:

Al usar la cámara se obtienen errores, problemas o la aplicación se cierra inesperadamente

Solución:

Añadir las siguientes líneas de código al manifest:

  • <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=”10″
  •        android:targetSdkVersion=”10″ />

Al pulsar la tecla de menú o ··· del terminal y una de sus opciones, la aplicación se cierra inesperadamente

Solución:

En el paquete com.google.zxing.cient.android, ir a CaptureActivity.java y comentar los siguientes métodos:

  • onCreateOptionsMenu(Menu menu)

  • onOptionsItemSelected(MenuItem item)

  • onPrepareOptionsMenu(Menu menu) (Solo si aparece)

El nombre de tu aplicación se ve sobrescrito por Barcode Scanner

Solución:

Dentro del proyecto, navegamos a res > values > strings.xml.  Cambiamos el string app_name por el de nuestra aplicación. Este paso se debería repetir para cada carpeta values-xx que exista. Si no queremos dar soporte multilenguaje, eliminar todas esas carpetas y dejar únicamente la carpeta values

Mejoras:

Al pulsar el botón que lanza el escáner, aparece un menú preguntando qué aplicación se desea usar para llevar a cabo el escaneo.

Solución:

Hay que modificar 3 archivos para evitar que aparezca el menú:

  • En el paquete com.google.zxing.client.android, en el archivo Intents.java cambiar:

    • String ACTION de Scan (com.google.zxing.client.android.SCAN) por la de nuestro proyecto (com.biljet.app.SCAN):  public static final String ACTION = “com.biljet.app.SCAN”;

  • En el android.manifest (tanto del CaptureActivity, como del BiljetApp), en el intent-filter > action realizar el mismo cambio de nombre. NO modificar el nombre de la actividad asociada en el android:name  en el apartado <activity>. Ej:

    • <activity android:name=”.CaptureActivity”

    • <intent-filter>

    • <action android:name=”com.biljet.app.SCAN”/>
  • En la actividad en la que esté el botón u objeto que lance el escaneador (la que contiene el intent)

    • Intent intent = new Intent(“com.biljet.app.SCAN”);

Hacer que la máscara del escáner tenga forma cuadrada (para códigos QR) en lugar de rectangular (para todo tipo de códigos como los de barras)

Solución:

En el paquete com.google.zxing.client.camera, en el archivo CameraManager.java, en el método getFramingRect(), cambiar la línea:

  • int width = screenResolution.x * 3 / 4;

Si cambiamos el 3 / 4 por 1 / 2, conseguiremos que la máscara se vuelva un cuadrado

Eliminar el texto en vertical (debido a que está en modo landscape por defecto)

Solución:

En el paquete com.google.zxing.client.android, en el archivo CaptureActivity.java, en el metodo resetStatusView() , cambiar la línea:

  • statusView.setVisibility(View.VISIBLE);

Por la siguiente:

  • statusView.setVisibility(View.INVISIBLE);

Eliminar que muestre la ayuda:

Solución:

En el paquete com.google.zxing.client.android, en el archivo CaptureActivity.java, en el método onCreate(Bundle icicle), comentar la línea:

  • showHelpOnFirstLaunch();

Errores Comunes:

E/AndroidRuntime(848): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.google.zxing.client.android.SCAN

Solución:

Verificar que cuando se cambió los nombres de los intents, se realizó en TODOS los archivos que se citó arriba

E/AndroidRuntime(946): java.lang.VerifyError: com.google.zxing.client.android.CaptureActivity

Solución:

La versión del proyecto y de la librería core.jar no se corresponden. Verificar que hay concordancia

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]

Solución:

La línea del manifest de proyecto propio (BiljetApp) que indica que clase está 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.