You are on page 1of 36

Desarrollo de interfaces dinmicas de usuario con Android y

XML
Recoleccin de datos mediante el motor de formularios de Android

Frank Ableson 25-02-2013


Author

Un nmero de sitios web atienden a organizaciones no lucrativas que proporcionan formularios de fcil
configuracin y que son utilizados para realizar sondeos y recolectar datos. Este tutorial introduce una
arquitectura simple para disear aplicaciones similares para interfaces dinmicas de usuarios de Android
que permiten a quienes no son programadores recolectar datos de usuarios de dispositivos mviles. Con
este tutorial podr crear un ejemplo de un motor de formularios, tanto con un servidor como con un
dispositivo mvil.

Antes de comenzar
Debe sentirse a gusto durante la construccin de aplicaciones de Android con Android SDK para sacar
el mayor provecho de este tutorial. Una vez que haya completado este tutorial, habr aprendido a realizar
comunicaciones de aplicaciones a servidores web con HTTP(S) y cmo analizar XML con el analizador
DOM. En el transcurso, crear interfaces de usuario dinmicas y personalizadas, comunicaciones
multiproceso, manipuladores de mensajes y dilogos de progreso. En menor grado, aprender sobre
AndroidManifest.xml y entornos de scripting de servidores.

Acerca de este tutorial


Acrnimos de uso frecuente
API: Interfaz de programacin de aplicaciones
DOM: Modelo de objetos de documentos
HTML: Lenguaje de marcado de hipertexto
HTTP(S): Protocolo de transferencia de hipertexto seguro
IDE: Entorno de desarrollo integrado
SAX: API simple para XML
SDK: Kit de desarrollo de software
UI: Interfaz de usuario
URL: Localizador universal de recursos
XML: Lenguaje de marcado extensible

Este tutorial introduce una arquitectura para formularios dinmicos para la recoleccin de datos de
dispositivos mviles en dispositivos Android. Comenzar con un nivel de arquitectura y discusin elevados

Copyright IBM Corporation 2013 Marcas


Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 1 de 36
developerWorks ibm.com/developerWorks/ssa/

sobre el lugar en el que tal aplicacin se ajusta en el mayor contexto de recoleccin de datos. Un vistazo
previo del proyecto completo, que incluye cada archivo de origen, que le presenta una hoja de ruta clara
sobre el objetivo de este tutorial. Como si se tratara de una receta, usted construir la aplicacin desde
cero con cada clase de Java presentada correctamente y relacionada con otros aspectos de la aplicacin, en
especial, el modelo de datos sobre el cual se desarrollar este motor de formularios. Para finalizar, guardar
los datos del formulario en un servidor y podr examinar brevemente el lado del servidor de la aplicacin.

Prerrequisitos
La Tabla 1 muestra las herramientas requeridas para este proyecto.

Tabla 1. Herramientas necesarias para este trabajo


Herramienta Comentario

Eclipse y ADT Editor de cdigos primario y complemento de herramientas de desarrollo de


Android

Android SDK Kit de desarrollo de software de Android

Servidor web Cualquier tipo de servidor compatible con PHP. Puede transportar fcilmente
el script a otro entorno de servidor.

Las muestras de cdigo que he creado para este tutorial las he realizado en una MacBook con Eclipse 3.4.2
y Android SDK versin 8, que admite la versin Android 2.2. El cdigo del tutorial no aprovecha ninguna
caracterstica especfica de este SDK y la aplicacin debe ejecutarse bien en las versiones de Android
actuales y anteriores hasta la versin 1.5. Consulte los Recursos para acceder a los enlaces para todas las
herramientas.

Recoleccin de datos
Comencemos con una breve discusin sobre la recoleccin de datos y lo fcil que puede ser implementarla
cuando utilizamos un dispositivo mvil Android.

Una infraestructura Android para la recoleccin de datos


La recoleccin de datos es una tarea que existe desde antes de la era de las computadoras. Las computadoras
se han convertido en un objeto de uso diario y han revolucionado la forma en la que pensamos, buscamos
y consumimos informacin. Las compaas con mercados de capitales con cifras millonarias deben su
existencia a la efectividad de almacenamiento, recuperacin y administracin de enormes cantidades de
informacin que ofrecen estos dispositivos. Las bases de datos utilizadas en la actualidad estn alimentadas
por sistemas de diversas arquitecturas que incluyen las del tipo marco principal, servidor de cliente,
aplicaciones web y, ahora, aplicaciones mviles.

Los inventarios fsicos y las aplicaciones de conteo de ciclos fueron algunas de las primeras aplicaciones
prcticas de la computacin mvil. Estas aplicaciones consistan a menudo en recoleccin de datos por lotes,
para las que el hardware requera una base de acoplamiento para cargar la informacin recolectada.

El mercado para las aplicaciones mviles ha evolucionado mucho desde aquellos primeros tiempos y la
conectividad y los dispositivos inalmbricos son casi omnipresentes en muchas culturas y mercados, y han
invadido virtualmente cada aspecto de nuestras vidas a diario.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 2 de 36


ibm.com/developerWorks/ssa/ developerWorks

Mientras los medios para recolectar datos han pasado a ser ms mviles, el aspecto central de la recopilacin
de datos no ha cambiado significativamente. El usuario debe responder una serie de preguntas y los medios
de respuesta que posee son simples. Este tutorial presenta la construccin de una infraestructura simple para
la recoleccin de datos para telfonos mviles con Android, aprovechando la estructura de metadatos que
permite XML.

Arquitectura de la aplicacin
Antes de sumergirnos en el cdigo, examine la configuracin de la aplicacin para que esta sea de un muy
alto nivel.

Vista rpida de la aplicacin Forms Engine


Examine todos los aspectos de la aplicacin Forms Engine. La Figura 1 presenta la relacin de la aplicacin
con uno o ms servidores que proveen formularios de entrada de datos de diverso contenido.

Figura 1. Arquitectura de la aplicacin

En la Figura 1, Form 1 proporciona la inscripcin para la competicin de Robotics y Form 2 solicita


al usuario informacin sobre sus hbitos de automantenimiento. A travs del protocolo HTTP(S), los
formularios y la aplicacin de Android se comunican para:

Descargar los datos de los formularios.


Presentar los datos de los formularios al usuario y recolectar datos especficos del dispositivo
opcionales tales como imgenes tomadas con cmaras, grabaciones de sonido, localizacin con GPS o
lecturas de brjulas.
Recolectar datos suministrados por el usuario.
Enviar datos al servidor apropiado.

El lado del servidor de este tutorial se implementa como un par de archivos: un documento XML que
describe el formulario y un documento PHP que es el responsable de registrar el envo del formulario. La
aplicacin de Android es una aplicacin nativa escrita en cdigo Java para la cual se utiliza Android SDK y
se codifica en Eclipse.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 3 de 36


developerWorks ibm.com/developerWorks/ssa/

La Tabla 2 muestra los archivos de origen de la aplicacin para la aplicacin completa. Puede descargar el
archivo comprimido que contiene todos estos archivos de origen (vea las Descargas). Examinaremos cada
uno de estos archivos detalladamente en este tutorial.

Tabla 2. Los archivos de origen requeridos para la aplicacin


Nombre de archivo Comentario

XmlGui.java Punto de entrada para las actividades en Android

XmlGuiForm.java Modelo y mtodo de datos de alto nivel para un formulario

XmlGuiFormField.java Representa un campo de formulario y contiene los metadatos para cada campo
de un formulario

XmlGuiEditBox.java Implementa un elemento de interfaz de usuario del tipo recuadro de texto

XmlGuiPickOne.java Implementa un elemento de interfaz de usuario del tipo lista desplegable

RunForm.java Procesa un formulario mediante la utilizacin de las clases mencionadas arriba

main.xml Pgina de inicio de la interfaz de usuario de la aplicacin

AndroidManifest.xml Descriptor de despliegue para la aplicacin de Android

xmlgui1.xml Formulario de muestra para recolectar registros de competicin de Robotics

xmlgui1-post.php Script PHP para procesar los envos de formularios

xmlgui2.xml Formulario de muestra para realizar una encuesta sobre los hbitos de
mantenimiento automotriz.

La Figura 2 muestra la estructura del proyecto en Eclipse para la aplicacin completa y cmo se ver al final
de este tutorial. (Vea una versin solo textual de la Figura 2).

Figura 2. Proyecto en Eclipse

Si no posee un entorno de trabajo para el desarrollo de Android, este es un buen momento para instalar las
herramientas de Android. Para obtener ms informacin sobre cmo configurar un entorno de desarrollo de

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 4 de 36


ibm.com/developerWorks/ssa/ developerWorks

Android, consulte los Recursos para obtener enlaces para las dos herramientas requeridas y algunos artculos
introductorios sobre cmo desarrollar aplicaciones para Android. Estar familiarizado con Android es de gran
utilidad para comprender este tutorial.

Ahora que posee una visin general de la arquitectura y de la aplicacin, puede comenzar!

El proyecto y el modelo de datos


Ahora estamos listos para empezar el proyecto de Android en Eclipse, crear el modelo de datos y la clase
que le permitir almacenar y gestionar los metadatos para la aplicacin Forms Engine.

Creacin del proyecto


La creacin de una aplicacin de Android comienza en un lugar conocido: Abra Eclipse y seleccione File >
New como se muestra en la Figura 3.

Figura 3. Creacin de una nueva aplicacin de Android

Este paso inicia el asistente para nuevos proyectos de Eclipse. Seleccione Android Project (el entorno
de Java especializado para Android). Asegrese de darle al proyecto un identificador vlido (yo utilic
XMLGUI). Para que la solucin coincida con la solucin que se describe en este tutorial, debajo de
Properties, especifique XML GUI como nombre de la aplicacin y com.msi.ibm como nombre del
paquete. Seleccione la casilla de verificacin Create Activity y especifique XmlGui para el nombre de la
actividad como se muestra en la Figura 4.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 5 de 36


developerWorks ibm.com/developerWorks/ssa/

Figura 4. Configuracin de un nuevo proyecto

Una vez que haya creado el proyecto, este debe verse similar a la imagen que se muestra en la Figura 5. (Vea
una versin solo textual de la Figura 5).

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 6 de 36


ibm.com/developerWorks/ssa/ developerWorks

Figura 5. Proyecto de Android finalizado directamente desde el asistente para nuevos


proyectos

Ahora que hemos creado el proyecto, es una buena prctica comprobar que la aplicacin funciona en forma
segura y limpia en el emulador Android. Observe que a veces las la aplicacin no se desarrolla hasta que
edite y guarde el archivo de origen de Java. Esto ocasiona que las herramientas de Android SDK generen
automticamente los archivos en la carpeta gen. Esto causa que Android SDK generen automticamente
los archivos en la carpeta gen. Puede probar la aplicacin si no hay entradas en la pestaa Problems o en el
entorno de Eclipse.

Para probar la aplicacin, cree una Configuracin de ejecucin como se muestra en la Figura 6. En la lista
Android Application, seleccione XmlGui. Compruebe que los siguientes valores estn presentes: XmlGui
en el campo Name, XMLGUI en el campo Project y com.msi.ibm.XmlGui en el campo Launch. Haga
clic en Run.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 7 de 36


developerWorks ibm.com/developerWorks/ssa/

Figura 6. Ejecucin de la configuracin de ejecucin

Ahora que el proyecto est creado, configurado y se inicia correctamente en el emulador de Android, es
tiempo de crear la herramienta de recoleccin de datos impulsada por XML para Android.

El modelo de datos
Los elementos constitutivos de esta aplicacin requieren que presente elementos de entrada para un usuario,
recolecte los datos, los valide y a continuacin los enve a una ubicacin especfica en el servidor. Cabe
sealar que esta aplicacin est configurada solo para nuevos registros. No existen disposiciones para buscar
un registro existente para editarlo o eliminarlo.

Para guiar la aplicacin lo suficiente sobre cmo presentar los formularios de entrada de datos, se requiere
un conjunto de informacin (conocido comnmente como metadatos). Los metadatos son los datos sobre los
datos. En trminos generales, esta aplicacin debe entender los siguientes elementos de datos:

Nombre de formulario Nombre del formulario en lectura humana directa


Identificador de formulario Identificador nico para esta recoleccin de metadatos
URL de envo El lugar al que se deben enviar los datos recolectados
Uno o ms campos Estos pueden ser de texto, numricos o se pueden seleccionar de una lista de
campos
Virtualmente, todos los tipos de preguntas conducen a unos de estos tres tipos de elementos de interfaz de
usuario. Por ejemplo, puede implementar una casilla de verificacin como un campo de eleccin por S o por
No. Puede implementar una seleccin mltiple como campos de seleccin mltiple Naturalmente, es posible
extender el cdigo que se muestra en este tutorial segn lo desee.

Para su aplicacin, el escenario de uso es el siguiente: Se encuentra en un evento en el que se puede inscribir
para una o ms actividades. Puede completar una hoja de papel o puede esperar hasta que llegue a su

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 8 de 36


ibm.com/developerWorks/ssa/ developerWorks

casa y confe en que recordar inscribirse en el sitio web de la organizacin para participar. En este caso,
asumir que el usuario completar un formulario simple en el momento desde su telfono al utilizar una
aplicacin dinmica en un dispositivo Android, en la que proporcionar el nombre, apellido, sexo y edad del
participante.

El Listado 1 muestra los contenidos de xmlgui1.xml, que representa el formulario de registro para un evento
de club de Robotics.

Listado 1. xmlgui1.xml
<?xml version="1.0" encoding="utf-8"?>
<xmlgui>
<form id="1" name="Robotics Club Registration"
submitTo="http://serverurl/xmlgui1-post.php" >
<field name="fname" label="First Name" type="text" required="Y" options=""/>
<field name="lname" label="Last Name" type="text" required="Y" options=""/>
<field name="gender" label="Gender" type="choice" required="Y" options="Male|Female"/>
<field name="age" label="Age on 15 Oct. 2010" type="numeric" required="N" options=""/>
</form>
</xmlgui>

Observe los siguientes aspectos sobre este documento XML:

El XML es muy simple de analizar gracias a su uso extensivo de atributos de elementos. Este abordaje
es utilizado ya que permite que la extraccin de datos sea fcil que la extraccin de elementos
secundarios y etiquetas mltiples. El uso de atributos de esta manera tambin mantiene el tamao de
descarga reducido y contribuye a mantener el tiempo de anlisis bajo.
El atributo submitTo le indica a la aplicacin el lugar al que debe enviar los datos una vez que hayan
sido recolectados.
Cada elemento field proporciona atributos para el nombre del campo y para la etiqueta. Mientras estos
valores estn relacionados, conserve el valor de cada atributo name como nico en relacin con los
dems valores de name para que la aplicacin receptora pueda analizarlos y procesarlos correctamente.
Tambin debe suministrar un valor label informativo para el usuario como una indicacin sobre qu
clase de datos debe ir en ese campo en particular.
Puede aumentar el alcance de este abordaje para incluir los valores predeterminados de campo, una
expresin regex para validacin o un enlace para obtener ms informacin sobre un campo determinado.
El campo options se utiliza como una lista delimitada para el campo choice.
Ahora que poseemos una familiaridad bsica con el modelo de datos, observemos el cdigo responsable para
convertir estos datos XML en una aplicacin til.

Representacin de datos
El anlisis de datos es un ejercicio algo mecnico que se muestra ms adelante en este tutorial. Antes de
examinar el proceso de anlisis, la aplicacin necesita lugar para almacenar y gestionar los metadatos en la
memoria. Para este fin, existen dos clases de Java a su alcance, una para el formulario y otra para representar
el campo del formulario. Comience observando XmlGuiForm.java en el Listado 2.

Listado 2. XmlGuiForm.java
package com.msi.ibm;
import java.util.Vector;
import java.util.ListIterator;

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 9 de 36


developerWorks ibm.com/developerWorks/ssa/

import java.net.URLEncoder;

public class XmlGuiForm {

private String formNumber;


private String formName;
private String submitTo;
public Vector<XmlGuiFormField> fields;

public XmlGuiForm()
{
this.fields = new Vector<XmlGuiFormField>();
formNumber = "";
formName = "";
submitTo = "loopback"; // do nothing but display the results
}
// getters & setters
public String getFormNumber() {
return formNumber;
}

public void setFormNumber(String formNumber) {


this.formNumber = formNumber;
}

public String getFormName() {


return formName;
}
public void setFormName(String formName) {
this.formName = formName;
}

public String getSubmitTo() {


return submitTo;
}

public void setSubmitTo(String submitTo) {


this.submitTo = submitTo;
}

public Vector<XmlGuiFormField> getFields() {


return fields;
}

public void setFields(Vector<XmlGuiFormField> fields) {


this.fields = fields;
}

public String toString()


{
StringBuilder sb = new StringBuilder();
sb.append("XmlGuiForm:\n");
sb.append("Form Number: " + this.formNumber + "\n");
sb.append("Form Name: " + this.formName + "\n");
sb.append("Submit To: " + this.submitTo + "\n");
if (this.fields == null) return sb.toString();
ListIterator<XmlGuiFormField> li = this.fields.listIterator();
while (li.hasNext()) {
sb.append(li.next().toString());
}

return sb.toString();
}

public String getFormattedResults()

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 10 de 36


ibm.com/developerWorks/ssa/ developerWorks

{
StringBuilder sb = new StringBuilder();
sb.append("Results:\n");
if (this.fields == null) return sb.toString();
ListIterator<XmlGuiFormField> li = this.fields.listIterator();
while (li.hasNext()) {
sb.append(li.next().getFormattedResult() + "\n");
}

return sb.toString();
}

public String getFormEncodedData()


{
try {
int i = 0;
StringBuilder sb = new StringBuilder();
sb.append("Results:\n");
if (this.fields == null) return sb.toString();
ListIterator<XmlGuiFormField> li = this.fields.listIterator();
while (li.hasNext()) {
if (i != 0) sb.append("&");
XmlGuiFormField thisField = li.next();
sb.append(thisField.name + "=");
String encstring = new String();
URLEncoder.encode((String) thisField.getData(),encstring);
sb.append(encstring);
}

return sb.toString();
}
catch (Exception e) {
return "ErrorEncoding";
}
}
}

Aqu hay unos elementos importantes que observar sobre la clase XmlGuiForm.

1. Hay cuatro variables de miembro:


formNumber: Este es el nico identificador para el mecanismo de distribucin del formulario del
lado del servidor.
formName: Este atributo se convierte en el ttulo del formulario, el cual provee el contexto y la
confirmacin para el usuario.
submitTo: Esta es la URL para la aplicacin para enviar los datos que se introdujeron (despus
de haberlos validado). Este valor tambin puede ser un valor de retorno. En el caso de un bucle
de retorno, los datos se muestran al usuario en lugar de ser enviados al servidor. Esto es de gran
utilidad para fines de prueba.
fields: Este es una clase de vector en plantilla para mantener los datos del campo del formulario. El
Listado 3 muestra los detalles para XmlGuiFormField.java.
2. Una serie de getters y setters para cada una de estas variables.
3. Los mtodos toString() y getFormattedResults() son los responsables de generar resmenes para lectura
humana directa de la clase XmlGuiForm.
4. El mtodo getFormEncodedData() es utilizado al preparar los datos para enviarlos a la URL indicada en el
atributo submitTo.
5. En lugar de utilizar clases java.lang.String estrictamente concatenadas, el cdigo emplea un StringBuilder
como un medio de memoria ms eficiente para construir las cadenas de datos deseadas.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 11 de 36


developerWorks ibm.com/developerWorks/ssa/

6. La clase URLEncoder es aprovechada para preparar los datos para enviarlos al servidor. Esto hace que los
datos se vean como se crearon realmente mediante un formulario HTML tradicional.
7. Algunas expansiones potenciales de esta aplicacin incluyen:
Almacenamiento local o en cach de los metadatos para hacer que las tareas repetitivas se
ejecuten ms rpido.
Almacenamiento local para registrar los datos durante un perodo de tiempo antes de enviarlos.
Registro de fecha y hora por GPS en cada registro con datos de ubicacin.
Ahora observemos la construccin de la clase XmlGuiFormField en el Listado 3.

Listado 3. XmlGuiFormField.java
package com.msi.ibm;
// class to handle each individual form
public class XmlGuiFormField {
String name;
String label;
String type;
boolean required;
String options;
Object obj; // holds the ui implementation
// or the EditText for example

// getters & setters


public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public boolean isRequired() {
return required;
}
public void setRequired(boolean required) {
this.required = required;
}
public String getOptions() {
return options;
}
public void setOptions(String options) {
this.options = options;
}

public String toString()


{
StringBuilder sb = new StringBuilder();
sb.append("Field Name: " + this.name + "\n");
sb.append("Field Label: " + this.label + "\n");
sb.append("Field Type: " + this.type + "\n");
sb.append("Required? : " + this.required + "\n");
sb.append("Options : " + this.options + "\n");

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 12 de 36


ibm.com/developerWorks/ssa/ developerWorks

sb.append("Value : " + (String) this.getData() + "\n");

return sb.toString();
}
public String getFormattedResult()
{
return this.name + "= [" + (String) this.getData() + "]";

public Object getData()


{
if (type.equals("text") || type.equals("numeric"))
{
if (obj != null) {
XmlGuiEditBox b = (XmlGuiEditBox) obj;
return b.getValue();
}
}
if (type.equals("choice")) {
if (obj != null) {
XmlGuiPickOne po = (XmlGuiPickOne) obj;
return po.getValue();
}
}

// You could add logic for other UI elements here


return null;
}

Observe con mayor detenimiento la clase XmlGuiFormField.

Hay seis miembros de nivel de clase:


1. name contiene el nombre del campo este es el nombre del campo del valor de los datos, anlogo
al nombre del campo de un formulario en HTML o el nombre de columna de base de datos.
2. label contiene una descripcin del campo o el valor que se muestra al usuario.
3. type indica el tipo de campo de la interfaz de usuario que se desea construir.
text significa que este campo se implementa con un campo EditText para entradas
alfanumricas. Este es el valor ms comn.
numeric tambin es un valor EditText, pero solo est limitado a un valor de entrada numrica.
choice hace que el campo sea una lista desplegable.
4. required es un valor booleano que marca el campo como requerido o no. Si el campo se requiere
pero no se completa, se muestra un mensaje de error al usuario cuando este intenta enviar el
formulario.
5. options es un valor de cadena utilizado para transmitir la lista de selecciones disponibles para
un campo de eleccin. Este campo est disponible para otros campos para ser utilizado quizs
como una expresin regex para validacin o puede ser sustituido para especificar un valor
predeterminado.
6. obj representa el widget de la interfaz de usuario. Por ejemplo, esta variable contiene un EditText
para un campo numrico o de texto. Para un campo de eleccin, el miembro obj contiene un
widget spinner. Este abordaje se explica con mayor detalle ms adelante en este tutorial.
Como se prevea, estas variables tienen un nmero de getters y setters.
Los mtodos toString() y getFormattedResult() aprovechan el mtodo getData() que se explica a continuacin.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 13 de 36


developerWorks ibm.com/developerWorks/ssa/

En la clase XmlGuiFormField, es necesario gestionar ms de un tipo de datos por lo que el cdigo necesita
ser explcito sobre cmo almacenar y acceder a los datos. El mtodo getData() examina el tipo de
cambio y realiza una conversin de tipo en el campo obj para interactuar correctamente con el objeto
almacenado. Si desea agregar nuevos tipos de campos a esta a infraestructura, puede expandir el
mtodo getData() para que este sea compatible con el nuevo tipo de campo (vea el comentario cerca del
final del Listado 3.

Ahora posee un mtodo para almacenar y gestionar los metadatos. Es tiempo de ver a la aplicacin en accin
y despus comenzar a atar las piezas entre s.

Ensamblado de una interfaz de usuario


Comience por crear un formulario para que un usuario mvil introduzca los datos.

Obtencin de los datos desde los niveles ms altos


El punto de entrada de la aplicacin reside en XmlGui.java, como se muestra en el Listado 4.

Listado 4. El punto de entrada de la aplicacin: XmlGui


package com.msi.ibm;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Button;
import android.widget.TextView;
import android.content.Intent;
import android.util.Log;
public class XmlGui extends Activity {
final String tag = XmlGui.class.getName();
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Button btnRunForm = (Button) this.findViewById(R.id.btnRunForm);


btnRunForm.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
EditText formNumber = (EditText) findViewById(R.id.formNumber);
Log.i(tag,"Attempting to process Form #
[" + formNumber.getText().toString() + "]");
Intent newFormInfo = new Intent(XmlGui.this,RunForm.class);
newFormInfo.putExtra("formNumber",
formNumber.getText().toString());
startActivity(newFormInfo);
}
});
}
}

La interfaz de usuario para Activity principal es muy simple; consiste solo en:

Una etiqueta (TextView)

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 14 de 36


ibm.com/developerWorks/ssa/ developerWorks

Un cuadro de entrada (EditText)


Un botn (Button)

La naturaleza del cdigo para XmlGui Activity es estndar. Debe inflar un layout creado durante el momento de
diseo y luego definir y crear un manejador de botones para implementar la funcionalidad deseada (esta se
explica ms adelante).

La interfaz de usuario la define en el archivo main.xml (que se encuentra en la subcarpeta de diseo en la


carpeta res). El Listado 5 muestra el archivo main.xml.

Listado 5. main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/Title"
/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>

<EditText
android:layout_width="100px"
android:layout_height="wrap_content"
android:text="1"
android:id="@+id/formNumber"
android:numeric="integer"/>
<Button android:text="Run Form" android:id="@+id/btnRunForm"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
</LinearLayout>

</LinearLayout>

Como recordatorio, puede editar directamente el XML para modificar los diseos o utilizar la herramienta
Layout en las herramientas de desarrollo de Android como se muestra en la Figura 7.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 15 de 36


developerWorks ibm.com/developerWorks/ssa/

Figura 7. Herramienta Layout

Para ejecutar la aplicacin, haga clic en el icono de la pantalla de inicio que inicia XmlGui Activity que se
muestra en la Figura 8.

Figura 8. Aplicacin en accin

Cuando el usuario introduce un nmero de formulario y hace clic en el botn Run Form, estas acciones
inician una serie de eventos. Examinemos el mtodo onClick() lnea por lnea. Recuerde que el mtodo
onClick() est en la clase XmlGui en el Listado 4.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 16 de 36


ibm.com/developerWorks/ssa/ developerWorks

Obtiene una referencia para el campo EditText denominado formNumber. La enumeracin R.id.formNumber es
generada automticamente por las herramientas de compilacin de Android siempre que se guarde el archivo
main.xml:

EditText formNumber = (EditText) findViewById(R.id.formNumber);

A continuacin, coloque una lnea en el registro. Puede observar la salida de este registro en la herramienta
DDMS (Dalvik Debug Monitor Service) en Eclipse incluida en el plug-in de herramientas de desarrollo de
Android:

Log.i(tag,"Attempting to process Form # [" + formNumber.getText().toString() + "]");

La clase RunForm proporciona la implementacin real de Form Engine, que extiende la clase Activity. Para
iniciar Activity, cree un Intent que identifique explcitamente la clase RunForm class:

Intent newFormInfo = new Intent(XmlGui.this,RunForm.class);

No solo desear iniciar la actividad RunForm Activity, tambin desear especificar qu formulario presentar.
Para hacer esto, agregue el nmero de formulario a Intent a travs del mtodo putExtra:

newFormInfo.putExtra("formNumber", formNumber.getText().toString());

Este valor es extrado por la clase RunForm, que se muestra ms adelante.

Una vez configurado Intent, inicie Activity con una llamada a startActivity:

startActivity(newFormInfo);

Con su aplicacin, el usuario introducir el nmero de formulario y har clic en el botn Run Form. Esto
desencadenar la serie de eventos descrita anteriormente, lo que causar que la clase RunForm procese la
solicitud. La introduccin de un nmero de formulario es realmente solo una herramienta de prueba para los
objetivos de este tutorial. Existen otros medios por los cuales este evento desencadenador puede tener lugar.
Ejemplos ms prcticos incluyen enlaces personalizados desde una pgina web, un mensaje enviado a travs
del servicio de mensajes cortos (SMS), un desencadenador basado en la ubicacin segn la proximidad o
incluso un cdigo QR escaneado (cdigo de respuesta rpida).

Ejecucin del formulario


La clase RunForm es la encargada de dirigir la aplicacin. Esta clase se ejecuta con un nmero de formulario
para procesar. Ahora examinemos el mtodo SubmitForm() en el Listado 6.

Listado 6. El mtodo onCreate()


public class RunForm extends Activity {
/** Called when the activity is first created. */
String tag = RunForm.class.getName();
XmlGuiForm theForm;
ProgressDialog progressDialog;
Handler progressHandler;

@Override

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 17 de 36


developerWorks ibm.com/developerWorks/ssa/

public void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);
String formNumber = "";
Intent startingIntent = getIntent();
if(startingIntent == null) {
Log.e(tag,"No Intent? We're not supposed to be here...");
finish();
return;
}
formNumber = startingIntent.getStringExtra("formNumber");
Log.i(tag,"Running Form [" + formNumber + "]");
if (GetFormData(formNumber)) {
DisplayForm();
}
else
{
Log.e(tag,"Couldn't parse the Form.");
AlertDialog.Builder bd = new AlertDialog.Builder(this);
AlertDialog ad = bd.create();
ad.setTitle("Error");
ad.setMessage("Could not parse the Form data");
ad.show();

}
}
// other methods omitted and shown later
}

Como se puede observar en el Listado 6, primero debe extraer formNumber de Intent que desencaden Activity.
Sin un nmero de formulario para procesar, Activity no tiene ninguna accin para realizar.

Una vez que haya extrado el valor, el siguiente requisito es establecer una conexin con el servidor para
descargar las especificaciones del formulario. (Observe que una mejora para este enfoque puede ser una
observacin de los metadatos en la memoria cach local antes de capturar los datos.) El Listado 7 muestra el
mtodo GetFormData().

Listado 7. El mtodo GetFormData()


private boolean GetFormData(String formNumber) {
try {
Log.i(tag,"ProcessForm");
URL url = new URL("http://www.example.com/xmlgui" + formNumber + ".xml");
Log.i(tag,url.toString());
InputStream is = url.openConnection().getInputStream();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
Document dom = db.parse(is);
Element root = dom.getDocumentElement();
NodeList forms = root.getElementsByTagName("form");
if (forms.getLength() < 1) {
// nothing here??
Log.e(tag,"No form, let's bail");
return false;
}
Node form = forms.item(0);
theForm = new XmlGuiForm();

// process form level


NamedNodeMap map = form.getAttributes();
theForm.setFormNumber(map.getNamedItem("id").getNodeValue());
theForm.setFormName(map.getNamedItem("name").getNodeValue());
if (map.getNamedItem("submitTo") != null)
theForm.setSubmitTo(map.getNamedItem("submitTo").getNodeValue());

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 18 de 36


ibm.com/developerWorks/ssa/ developerWorks

else
theForm.setSubmitTo("loopback");

// now process the fields


NodeList fields = root.getElementsByTagName("field");
for (int i=0;i<fields.getLength();i++) {
Node fieldNode = fields.item(i);
NamedNodeMap attr = fieldNode.getAttributes();
XmlGuiFormField tempField = new XmlGuiFormField();
tempField.setName(attr.getNamedItem("name").getNodeValue());
tempField.setLabel(attr.getNamedItem("label").getNodeValue());
tempField.setType(attr.getNamedItem("type").getNodeValue());
if (attr.getNamedItem("required").getNodeValue().equals("Y"))
tempField.setRequired(true);
else
tempField.setRequired(false);
tempField.setOptions(attr.getNamedItem("options").getNodeValue());
theForm.getFields().add(tempField);
}

Log.i(tag,theForm.toString());
return true;
} catch (Exception e) {
Log.e(tag,"Error occurred in ProcessForm:" + e.getMessage());
e.printStackTrace();
return false;
}
}

Este cdigo es responsable de obtener datos de un repositorio de metadatos, en este caso mediante la
descarga de un archivo XML de un servidor web:

URL url = new URL("http://10.211.55.2/~fableson/xmlgui" + formNumber + ".xml");

Manipule los datos del archivo XML a travs de un analizador DOM, para extraer el formulario y
los elementos del campo y los atributos para almacenarlos en instancias de las clases XmlGuiForm y
XmlGuiFormField respectivamente. La mayor parte de este mtodo est dedicado al anlisis y rellenado de
tareas.

Dos enfoques para el anlisis de archivos XML son DOM y SAX. El funcionamiento del analizador DOM
est basado en analizar un documento dentro de la memoria para que despus la aplicacin recorra un
rbol de modelo de objetos de documento para acceder a diversos elementos de los datos contenidos en el
archivo XML. Tambin puede utilizar aqu el modelo del analizador SAX ya que usted genera su propia
representacin del documento al completar las dos clases.

La ventaja del enfoque DOM para la aplicacin es que esta contiene varios procedimientos y es fcil seguir
el cdigo mientras que el enfoque SAX requiere funciones de devolucin de llamadas en las que solo se
almacenan los datos deseados. En algunas instancias, la complejidad del cdigo escrito por el desarrollador
para implementar las funciones de devolucin de llamadas de SAX pueden ser notablemente ms elevadas
que el enfoque DOM. Debido a que los datos del archivo XML son analizados completamente en el enfoque
DOM, este requiere una actividad ms intensiva para la memoria. Para los objetivos en esta aplicacin, la
simplicidad y facilidad de DOM fue un impulsor ms grande que la gestin de memoria ya que el formulario
de metadatos es bastante pequeo.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 19 de 36


developerWorks ibm.com/developerWorks/ssa/

Consulte los Recursos para obtener una excelente referencia sobre cmo codificar analizadores XML en
Android.

Hemos transformado los formularios de metadatos del archivo XML en instancias de la clase Java. Ahora es
momento de presentar el formulario para reunir datos del usuario.

Recoleccin de datos del usuario


Ahora que ha creado el diseo principal de pantalla Activity, puede crear los formularios de la interfaz de
usuario para recolectar los datos. Aqu crearemos un formulario de inscripcin del Club Robotics y un
formulario de encuesta sobre automantenimiento.

Uso de los metadatos


Esta aplicacin se articula en la habilidad de los programadores de Android para manipular dinmicamente
la interfaz de usuario. A comienzos de este tutorial, hemos examinado el archivo main.xml, el archivo
que define el diseo de pantalla de la clase XmlGui (el elemento Activity principal). Esta aplicacin sera
virtualmente imposible en su forma actual si tuviera que definir siempre los elementos de la interfaz de
usuario durante el tiempo de diseo o de compilacin.

Afortunadamente, no tenemos estos lmites para condicionarnos. El mtodo DisplayForm() es responsable


de convertir los metadatos en elementos de la interfaz de usuario para los fines de recoleccin de datos.
El cdigo est dividido bsicamente en dos reas funcionales principales: el diseo de los elementos de la
interfaz de usuario y la manipulacin del botn de envo.

Examinemos en primer lugar la lgica de diseo: Este es el cdigo que convierte el objeto XmlGuiForm en un
formulario real en la pantalla. El Listado 8 muestra este cdigo.

Listado 8. La lgica de diseo


private boolean DisplayForm()
{

try
{
ScrollView sv = new ScrollView(this);

final LinearLayout ll = new LinearLayout(this);


sv.addView(ll);
ll.setOrientation(android.widget.LinearLayout.VERTICAL);

// walk through the form elements and dynamically create them,


// leveraging the mini library of tools.
int i;
for (i=0;i<theForm.fields.size();i++) {
if (theForm.fields.elementAt(i).getType().equals("text")) {
theForm.fields.elementAt(i).obj = new
XmlGuiEditBox(this,(theForm.fields.elementAt(i).isRequired()
? "*" : "") + theForm.fields.elementAt(i).getLabel(),"");
ll.addView((View) theForm.fields.elementAt(i).obj);
}
if (theForm.fields.elementAt(i).getType().equals("numeric")) {
theForm.fields.elementAt(i).obj = new
XmlGuiEditBox(this,(theForm.fields.elementAt(i).isRequired()
? "*" : "") + theForm.fields.elementAt(i).getLabel(),"");
((XmlGuiEditBox)theForm.fields.elementAt(i).obj).makeNumeric();
ll.addView((View) theForm.fields.elementAt(i).obj);

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 20 de 36


ibm.com/developerWorks/ssa/ developerWorks

}
if (theForm.fields.elementAt(i).getType().equals("choice")) {
theForm.fields.elementAt(i).obj = new
XmlGuiPickOne(this,(theForm.fields.elementAt(i).isRequired()
? "*" : "") + theForm.fields.elementAt(i).getLabel(),
theForm.fields.elementAt(i).getOptions());
ll.addView((View) theForm.fields.elementAt(i).obj);
}
}

Button btn = new Button(this);


btn.setLayoutParams(new LayoutParams
(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.
WRAP_CONTENT));

ll.addView(btn);

btn.setText("Submit");
btn.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
// check if this form is Valid
if (!CheckForm())
{
AlertDialog.Builder bd = new AlertDialog.Builder(ll.getContext());
AlertDialog ad = bd.create();
ad.setTitle("Error");
ad.setMessage("Please enter all required (*) fields");
ad.show();
return;

}
if (theForm.getSubmitTo().equals("loopback")) {
// just display the results to the screen
String formResults = theForm.getFormattedResults();
Log.i(tag,formResults);
AlertDialog.Builder bd = new AlertDialog.Builder(ll.getContext());
AlertDialog ad = bd.create();
ad.setTitle("Results");
ad.setMessage(formResults);
ad.show();
return;

} else {
if (!SubmitForm()) {
AlertDialog.Builder bd = new AlertDialog.Builder(ll.getContext());
AlertDialog ad = bd.create();
ad.setTitle("Error");
ad.setMessage("Error submitting form");
ad.show();
return;
}
}

}
} );

setContentView(sv);
setTitle(theForm.getFormName());

return true;

} catch (Exception e) {
Log.e(tag,"Error Displaying Form");
return false;
}
}

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 21 de 36


developerWorks ibm.com/developerWorks/ssa/

Debe anticipar la disponibilidad de ms campos que puedan ajustarse a una sola pantalla; utilice ScrollView
como una vista primaria o contenedora. Con este ScrollView, utiliza un diseo LinearLayout para organizar los
diversos widgets de la interfaz de usuario en una columna vertical.

Este enfoque es bastante sencillo:

A travs de la lista de XmlGuiFormField, enumera los objetos contenidos dentro del miembro fields de la
instancia XmlGuiForm.
Segn el tipo de campo solicitado, un elemento diferente de la interfaz de usuario se instancia y se
agrega a LinearLayout. Examinaremos los diferentes widgets de la interfaz de usuario por un momento.
Una vez que haya creado y agregado los elementos de la interfaz de usuario al diseo lineal, asigne la
instancia ScrollView completa al contenido de esta pantalla y el nombre del formulario como el ttulo de
la pantalla. La Figura 9 muestra la pantalla de inscripcin del Club Robotics lista para que el usuario
introduzca la informacin. Este formulario es el resultado del proceso de los datos del archivo XML que se
encuentran en el Listado 1.

Figura 9. Formulario de inscripcin de Robotics en accin

Veamos los diferentes widgets personalizados de la interfaz de usuario creados para esta aplicacin.

Recuerde que esta aplicacin tiene definidos tres tipos de campos de entrada de datos: Estos tres tipos de
campo se implementan mediante dos widgets personalizados diferentes: XmlGuiEditBox y XmlGuiPickOne.

Los valores numricos y de texto presentan grandes similitudes y puede aprovechar el mismo enfoque de
EditView para ambos pero con diferentes filtros de entrada para alternar entre valores alfanumricos o solo
valores numricos. El Listado 9 muestra el cdigo para la clase XmlGuiEditBox.

Listado 9. La clase XmlGuiEditBox


package com.msi.ibm;

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 22 de 36


ibm.com/developerWorks/ssa/ developerWorks

import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.EditText;
import android.text.method.DigitsKeyListener;

public class XmlGuiEditBox extends LinearLayout {


TextView label;
EditText txtBox;

public XmlGuiEditBox(Context context,String labelText,String initialText) {


super(context);
label = new TextView(context);
label.setText(labelText);
txtBox = new EditText(context);
txtBox.setText(initialText);
txtBox.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams
.FILL_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT));
this.addView(label);
this.addView(txtBox);
}

public XmlGuiEditBox(Context context, AttributeSet attrs) {


super(context, attrs);
// TODO Auto-generated constructor stub
}

public void makeNumeric()


{
DigitsKeyListener dkl = new DigitsKeyListener(true,true);
txtBox.setKeyListener(dkl);
}
public String getValue()
{
return txtBox.getText().toString();
}
public void setValue(String v)
{
txtBox.setText(v);
}
}

La clase XmlGuiEditBox extiende la clase LinearLayout y contiene una etiqueta textual para describir la entrada
solicitada y un elemento EditText para recolectar los datos introducidos. Toda la inicializacin de los objetos
se realiza en el constructor. Esta puede considerarse como una mala prctica pero este es un ejercicio que
puede realizar si no est a gusto con ese enfoque.

Existen otros tres mtodos para analizar. Los mtodos getValue() y setValue() que realizan las actividades que
tiene en mente. Estos son getter y setter para interactuar con el campo EditText.

makeNumeric() es el tercer mtodo y solo se recurre a este al configurar un campo de formulario numrico.
Se emplea una instancia de DigitsKeyListener para filtrar todas las claves que no sean numricas. Por otra
parte, otro componente que recibir gratuitamente es un teclado apropiado que se muestra segn el tipo de
XmlGuiEditBox que est en uso con o sin la configuracin numrica.

La Figura 10 muestra el formulario en accin con un teclado alfabtico ya que el campo Apellido est
configurado para entradas alfabticas, en otras palabras text.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 23 de 36


developerWorks ibm.com/developerWorks/ssa/

Figura 10. Entrada de clave alfanumrica

La Figura 11 muestra el teclado numrico en uso ya que el campo edad est configurado para datos del tipo
numeric.

Figura 11. Teclado numrico

El campo de seleccin, implementado en la interfaz de usuario a travs de la clase XmlGuiPickOne presenta


algunas diferencias. El campo de seleccin es implementado como un widget Spinner de Android. Esta
interfaz de usuario es similar a un cuadro de lista desplegable en otros entornos de programacin, en donde
el usuario debe seleccionar una de las opciones de seleccin existentes. La Figura 12 muestra tres instancias
del widget XmlGuiPickOne.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 24 de 36


ibm.com/developerWorks/ssa/ developerWorks

Figura 12. Encuesta de automantenimiento con tres instancias XmlGuiPickOne

En este ejemplo, los datos recolectados se utilizarn para fines estadsticos por lo que la normalizacin de las
entradas posibles hace que el procesamiento de los datos sea ms limpio que tratar con campos de entrada
de texto libre. Por supuesto, puede definir el campo Estado como un campo de eleccin si desea limitar la
encuesta a una regin geogrfica particular.

El Listado 10 muestra el cdigo para la clase XmlGuiPickOne.

Listado 10. La clase XmlGuiPickOne


package com.msi.ibm;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Spinner;
import android.widget.ArrayAdapter;

public class XmlGuiPickOne extends LinearLayout {


String tag = XmlGuiPickOne.class.getName();
TextView label;
ArrayAdapter<String> aa;
Spinner spinner;

public XmlGuiPickOne(Context context,String labelText,String options) {


super(context);
label = new TextView(context);
label.setText(labelText);
spinner = new Spinner(context);
String []opts = options.split("\\|");
aa = new ArrayAdapter<String>( context,
android.R.layout.simple_spinner_item,opts);
spinner.setAdapter(aa);
this.addView(label);
this.addView(spinner);
}

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 25 de 36


developerWorks ibm.com/developerWorks/ssa/

public XmlGuiPickOne(Context context, AttributeSet attrs) {


super(context, attrs);
// TODO Auto-generated constructor stub
}

public String getValue()


{
return (String) spinner.getSelectedItem().toString();
}

Esta clase es muy similar a la clase XmlGuiEditBox. La diferencia principal es que se emplea un control Spinner
en lugar de un control EditText. Adems, observe que esta clase solo implementa el mtodo getValue(). Una
mejora evidente para esta clase es permitir al usuario especificar un valor predeterminado.

Observe el uso del miembro options para rellenar la lista de selecciones. En este cdigo, la cadena que
contiene las opciones disponibles se divide en un conjunto mediante el uso de la expresin regex y luego
pasa a una instancia de un ArrayAdapter. La constante android.R.layout.simple_spinner_item est integrada para
Android. Esta no se suministraba en el cdigo de la aplicacin del tutorial. Una vez que el adaptador haya
sido configurado, asgnelo al elemento Spinner. La Figura 13 presenta la lista de selecciones que se muestra
en la pantalla, que le indican al usuario la cantidad de millas entre un cambio de aceite y otro.

Figura 13. XmlGuiPickOne preguntando por los cambios de aceite

Ahora que el usuario puede introducir datos en el formulario, es momento de validar y enviar los datos.

Guardado y envo de datos


Ahora debe crear un recurso para que el usuario pueda guardar los datos para validarlos y enviarlos a un
servidor.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 26 de 36


ibm.com/developerWorks/ssa/ developerWorks

Guardado de los datos


Es hora de volver al mtodo DisplayForm() de la clase RunForm. Recuerde que la primera opcin de este
mtodo es la encargada de traer el formulario. A continuacin, examinar el manejador onClick() del botn de
envo, en el Listado 11.

Listado 11. El manejador onClick()


btn.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
// check if this form is Valid
if (!CheckForm())
{
AlertDialog.Builder bd = new AlertDialog.Builder(ll.getContext());
AlertDialog ad = bd.create();
ad.setTitle("Error");
ad.setMessage("Please enter all required (*) fields");
ad.show();
return;
}
if (theForm.getSubmitTo().equals("loopback")) {
// just display the results to the screen
String formResults = theForm.getFormattedResults();
Log.i(tag,formResults);
AlertDialog.Builder bd = new AlertDialog.Builder(ll.getContext());
AlertDialog ad = bd.create();
ad.setTitle("Results");
ad.setMessage(formResults);
ad.show();
return;
} else {
if (!SubmitForm()) {
AlertDialog.Builder bd = new AlertDialog.Builder(ll.getContext());
AlertDialog ad = bd.create();
ad.setTitle("Error");
ad.setMessage("Error submitting form");
ad.show();
return;
}
}
}
} );

Cuando el usuario selecciona el botn de envo, las entradas del formulario son verificadas para comprobar
que todos los campos requeridos hayan sido completados. De lo contrario, un AlertDialog le recordar al
usuario que debe completar todos los campos. En el caso supuesto de que los datos hayan sido introducidos
de manera satisfactoria, es momento de enviarlos.

El proceso de envo de los datos consta en uno de dos campos para la aplicacin de este tutorial. Si el campo
submitTo del formulario ha sido configurado para el bucle de retorno, los valores se reproducen simplemente
en la pantalla. Esto es de gran utilidad para fines de prueba. Una vez que la herramienta del formulario
recolecte los datos correctamente y usted est conforme, es momento de apuntar a una pgina de servidor
para registrar las entradas.

El Listado 12 muestra el mtodo CheckForm(). Este cdigo es bastante directo y conciso. Cada campo es
verificado para comprobar si este es requerido. Si el campo es requerido pero el usuario no proporcion la
informacin, se establece una bandera. Puede mejorar esto para proveer un comentario ms especfico al
usuario.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 27 de 36


developerWorks ibm.com/developerWorks/ssa/

Listado 12. El mtodo CheckForm()


private boolean CheckForm()
{
try {
int i;
boolean good = true;

for (i=0;i<theForm.fields.size();i++) {
String fieldValue = (String)
theForm.fields.elementAt(i).getData();
Log.i(tag,theForm.fields.elementAt(i)
.getName() + " is [" + fieldValue + "]");
if (theForm.fields.elementAt(i).isRequired()) {
if (fieldValue == null) {
good = false;
} else {
if (fieldValue.trim().length() == 0) {
good = false;
}
}

}
}
return good;
} catch(Exception e) {
Log.e(tag,"Error in CheckForm()::" + e.getMessage());
e.printStackTrace();
return false;
}
}

Ahora, es tiempo de enviar los datos recolectados al servidor. Examine el mtodo SubmitForm() en el Listado
13.

Listado 13. El mtodo SubmitForm()


private boolean SubmitForm()
{
try {
boolean ok = true;
this.progressDialog = ProgressDialog.show(this,
theForm.getFormName(), "Saving Form Data", true,false);
this.progressHandler = new Handler() {

@Override
public void handleMessage(Message msg) {
// process incoming messages here
switch (msg.what) {
case 0:
// update progress bar
progressDialog.setMessage("" + (String) msg.obj);
break;
case 1:
progressDialog.cancel();
finish();
break;
case 2:
progressDialog.cancel();
break;
}
super.handleMessage(msg);
}

};

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 28 de 36


ibm.com/developerWorks/ssa/ developerWorks

Thread workthread = new Thread(new TransmitFormData(theForm));

workthread.start();

return ok;
} catch (Exception e) {
Log.e(tag,"Error in SubmitForm()::" + e.getMessage());
e.printStackTrace();
// tell user that the submission failed....
Message msg = new Message();
msg.what = 1;
this.progressHandler.sendMessage(msg);

return false;
}

En primer lugar, debe configurar una instancia de la clase android.os.Handler. La clase Handler es de gran
utilidad cuando la aplicacin necesita compartir datos con diferentes subprocesos. Otro aspecto importante
para observar en el mtodo SubmitForm() es el uso de un ProgressDialog. Observe que ProgressDialog y Handler
estn definidos como variables de nivel de clase en el Listado 14.

Listado 14. El ProgressDialog y el manejador


public class RunForm extends Activity {
/** Called when the activity is first created. */
String tag = RunForm.class.getName();
XmlGuiForm theForm;
ProgressDialog progressDialog;
Handler progressHandler;
...
}

No desea bloquear innecesariamente la aplicacin mientras establece la comunicacin con el servidor; para
ello, utiliza un subproceso de segundo plano para la comunicacin, pero confa en el manejador para recibir
notificaciones del subproceso de comunicaciones para proporcionar respuestas al usuario. Observe que se
supone que solo el subproceso principal debe interactuar con la interfaz de usuario. Una alternativa para el
enfoque de procesos separado es la clase AsyncTask que se encuentra en el paquete del sistema operativo de
Android.

A medida que la aplicacin se conecta al servidor para transferir los datos, esta tiene la oportunidad de
informar al usuario el estado de la operacin, lo que por supuesto, es una buena prctica. La Figura 14
muestra la variable ProgressDialog en accin.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 29 de 36


developerWorks ibm.com/developerWorks/ssa/

Figura 14. El ProgressDialog

El cdigo real de comunicaciones del servidor se encuentra en el Listado 15, en la clase TransmitFormData(),
que implementa la interfaz Runnable.

Listado 15. La clase TransmitFormData


private class TransmitFormData implements Runnable
{
XmlGuiForm _form;
Message msg;
TransmitFormData(XmlGuiForm form) {
this._form = form;
}

public void run() {

try {
msg = new Message();
msg.what = 0;
msg.obj = ("Connecting to Server");
progressHandler.sendMessage(msg);

URL url = new URL(_form.getSubmitTo());


URLConnection conn = url.openConnection();
conn.setDoOutput(true);
BufferedOutputStream wr = new BufferedOutputStream
(conn.getOutputStream());
String data = _form.getFormEncodedData();
wr.write(data.getBytes());
wr.flush();
wr.close();

msg = new Message();


msg.what = 0;
msg.obj = ("Data Sent");
progressHandler.sendMessage(msg);

// Get the response

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 30 de 36


ibm.com/developerWorks/ssa/ developerWorks

BufferedReader rd = new BufferedReader(new


InputStreamReader(conn.getInputStream()));
String line = "";
Boolean bSuccess = false;
while ((line = rd.readLine()) != null) {
if (line.indexOf("SUCCESS") != -1) {
bSuccess = true;
}
// Process line...
Log.v(tag, line);
}
wr.close();
rd.close();

if (bSuccess) {
msg = new Message();
msg.what = 0;
msg.obj = ("Form Submitted Successfully");
progressHandler.sendMessage(msg);

msg = new Message();


msg.what = 1;
progressHandler.sendMessage(msg);
return;

}
} catch (Exception e) {
Log.d(tag, "Failed to send form data: " + e.getMessage());
msg = new Message();
msg.what = 0;
msg.obj = ("Error Sending Form Data");
progressHandler.sendMessage(msg);
}
msg = new Message();
msg.what = 2;
progressHandler.sendMessage(msg);
}

La clase TransmitFormData es responsable de la conexin al servidor indicada en el miembro submitTo de


la instancia XmlGuiForm (como se obtuvo de los metadatos). Esta actualiza peridicamente el subproceso
principal de la aplicacin al enviar una instancia de la clase Message al manipulador a travs del mtodo
sendMessage(). Dos miembros se completan en la clase Message:

El valor what acta como un mecanismo de conmutacin de alto nivel que informa al manipulador qu
accin debe realizar con ese mensaje.
El valor obj especifica un objeto java.lang.Object opcional. En este caso, se aprueba y utiliza una instancia
java.lang.String para mostrarla en el dilogo de progreso.

El esquema utilizado por cualquier aplicacin determinada es arbitrario. Esta aplicacin utiliza los valores en
la Tabla 3.

Tabla 3. Los valores de la aplicacin permitidos para what


Valor Comentario

0 Obj contiene una cadena de texto para mostrar al usuario.

1 Finalizacin satisfactoria de la transmisin, ha terminado!

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 31 de 36


developerWorks ibm.com/developerWorks/ssa/

2 Se produjo un error. Informe al usuario que algo est mal y no elimine los
datos.

La Figura 15 muestra el mensaje final en ProgressDialog despus de una transmisin correcta de datos del
formulario.

Figura 15. Presentacin del formulario

Una vez que el formulario haya sido enviado correctamente, la aplicacin regresa a la pgina principal. Para
una aplicacin preparada para produccin, lo que suceda a continuacin depende en buena medida de los
motivos de la organizacin para reunir los datos. La pantalla se puede restablecer simplemente para tomar
otra entrada, como en una aplicacin de inventario fsico. O quizs pueda dirigir al usuario a otra pantalla.

Para que la aplicacin se ejecute correctamente, el archivo AndroidManifest.xml debe contener referencias
sobre todas las clases utilizadas de Activity y debe incluir el permiso de usuario para acceder a Internet. El
Listado 16 muestra el archivo AndroidManifest.xml para la aplicacin del tutorial.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 32 de 36


ibm.com/developerWorks/ssa/ developerWorks

Listado 16. El archivo AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.msi.ibm"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".XmlGui"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".RunForm">
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

</manifest>

Antes de finalizar, examine brevemente el script del lado del servidor.

Proporcione un script del lado del servidor


Para los fines de este tutorial, utilizar un script PHP para reunir los datos requeridos y agregarlos a un
archivo de texto.

En el servidor
Lo que sucede exactamente en el servidor depende de la organizacin que rene los datos. Un enfoque
comn para la recoleccin de datos es almacenar los datos de los formularios en una base de datos relacional
tal como DB2, MySQL, SQL Server, Oracle, etc. Una vez que los datos estn almacenados en la base de
datos, estos se pueden tomar en parte o en conjunto y analizarlos.

Para este tutorial, los datos son recolectados por un script PHP y son agregados a un archivo de texto. El
Listado 17 muestra el formulario PHP asociado con el formulario de registro de Robotics.

Listado 17. El formulario PHP de Robotics


<?php
// xmlgui form # 1
// this page is expecting
// fname
// lname
// gender
// age

$filename = "/pathtowritablefile/datafile.txt";

$f = fopen($filename,"a");
fprintf($f,"Data received @ ".date(DATE_RFC822));
fprintf($f,"\n");
fprintf($f,'First Name:['.$_POST['fname'].']');
fprintf($f,"\n");

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 33 de 36


developerWorks ibm.com/developerWorks/ssa/

fprintf($f,'Last Name:['.$_POST['lname'].']');
fprintf($f,"\n");
fprintf($f,'Gender:['.$_POST['gender'].']');
fprintf($f,"\n");
fprintf($f,'Age:['.$_POST['age'].']');
fprintf($f,"\n");
fclose($f);
print "SUCCESS";
?>

Si el script devuelve la cadena SUCCESS, la clase RunForm se restablecer. Cualquier otro valor generar un
mensaje de error que recibir el usuario y le permitir corregir las entradas o, de lo contrario, obtener ayuda
mediante el envo del formulario.

Conclusin
Este tutorial present una infraestructura para servir preguntas dinmicas para un usuario de Android
basado en un enfoque de una aplicacin nativa que utiliza Android SDK. Ya hemos visto la presentacin
de formularios dinmicos, tcnicas de validacin y procesamiento y comunicaciones de la aplicacin con el
servidor web.

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 34 de 36


ibm.com/developerWorks/ssa/ developerWorks

Descargas
Descripcin Nombre tamao
Forms engine source code formsengine.zip 78KB

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 35 de 36


developerWorks ibm.com/developerWorks/ssa/

Sobre el autor
Frank Ableson

Despus de que terminara su carrera basquetbolista colegial sin un contrato multianual para
jugar para los Lakers de Los ngeles, Frank Ableson cambi su enfoque hacia el diseo
de software informtico. Disfruta solucionando problemas complejos, particularmente en
las reas de comunicaciones e interfaces de hardware. Cuando no est trabajando, est
pasando el tiempo con su esposa Nikki y sus hijos. Es posible contactar a Frank escribiendo a
frank@cfgsolutions.com.

Copyright IBM Corporation 2013


(www.ibm.com/legal/copytrade.shtml)
Marcas
(www.ibm.com/developerworks/ssa/ibm/trademarks/)

Desarrollo de interfaces dinmicas de usuario con Android y XML Pagina 36 de 36

You might also like