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 aplicación Forms Engine.
La creación de una aplicación de Android comienza en un lugar conocido: Abra Eclipse y seleccione File > New como se muestra en la Figura 3.
Figura 3. Creación de una nueva aplicación de Android
Este paso inicia el asistente para nuevos proyectos de Eclipse. Seleccione Android Project (el entorno de Java especializado para Android). Asegúrese de darle al proyecto un identificador válido (yo utilicé XMLGUI). Para que la solución coincida con la solución que se describe en este tutorial, debajo de Properties, especifique XML GUI como nombre de la aplicación y com.msi.ibm como nombre del paquete. Seleccione la casilla de verificación Create Activity y especifique XmlGui para el nombre de la actividad como se muestra en la Figura 4.
Figura 4. Configuración 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 versión solo textual de la Figura 5).
Figura 5. Proyecto de Android finalizado directamente desde el asistente para nuevos proyectos
Ahora que hemos creado el proyecto, es una buena práctica comprobar que la aplicación funciona en forma segura y limpia en el emulador Android. Observe que a veces las la aplicación no se desarrolla hasta que edite y guarde el archivo de origen de Java. Esto ocasiona que las herramientas de Android SDK generen automáticamente los archivos en la carpeta gen.
Esto causa que Android SDK generen automáticamente los archivos en la carpeta gen. Puede probar la aplicación si no hay entradas en la pestaña Problems o en el entorno de Eclipse.
Para probar la aplicación, cree una Configuración de ejecución como se muestra en la Figura 6. En la lista Android Application, seleccione XmlGui. Compruebe que los siguientes valores estén presentes: XmlGui en el campo Name, XMLGUI en el campo Project y com.msi.ibm.XmlGui en el campo Launch. Haga clic en Run.
Figura 6. Ejecución de la configuración de ejecución
Ahora que el proyecto está creado, configurado y se inicia correctamente en el emulador de Android, es tiempo de crear la herramienta de recolección de datos impulsada por XML para Android.
Los elementos constitutivos de esta aplicación requieren que presente elementos de entrada para un usuario, recolecte los datos, los valide y a continuación los envíe a una ubicación específica en el servidor. Cabe señalar que esta aplicación está configurada solo para nuevos registros. No existen disposiciones para buscar un registro existente para editarlo o eliminarlo.
Para guiar la aplicación lo suficiente sobre cómo presentar los formularios de entrada de datos, se requiere un conjunto de información (conocido comúnmente como metadatos). Los metadatos son los datos sobre los datos. En términos generales, esta aplicación debe entender los siguientes elementos de datos:
- Nombre de formulario— Nombre del formulario en lectura humana directa
- Identificador de formulario— Identificador único para esta recolección de metadatos
- URL de envío— El lugar al que se deben enviar los datos recolectados
- Uno o más campos— Estos pueden ser de texto, numéricos 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 verificación como un campo de elección por Sí o por No. Puede implementar una selección múltiple como campos de selección múltiple Naturalmente, es posible extender el código que se muestra en este tutorial según lo desee.
Para su aplicación, el escenario de uso es el siguiente: Se encuentra en un evento en el que se puede inscribir para una o más actividades. Puede completar una hoja de papel o puede esperar hasta que llegue a su casa y confíe en que recordará inscribirse en el sitio web de la organización para participar. En este caso, asumirá que el usuario completará un formulario simple en el momento desde su teléfono al utilizar una aplicación dinámica 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 extracción de datos sea fácil que la extracción de elementos secundarios y etiquetas múltiples. El uso de atributos de esta manera también mantiene el tamaño de descarga reducido y contribuye a mantener el tiempo de análisis bajo.
- El atributo
submitTole indica a la aplicación el lugar al que debe enviar los datos una vez que hayan sido recolectados. - Cada elemento
fieldproporciona atributos para el nombre del campo y para la etiqueta. Mientras estos valores estén relacionados, conserve el valor de cada atributonamecomo único en relación con los demás valores denamepara que la aplicación receptora pueda analizarlos y procesarlos correctamente. También debe suministrar un valorlabelinformativo para el usuario como una indicación 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 expresión
regexpara validación o un enlace para obtener más información sobre un campo determinado. - El campo
optionsse utiliza como una lista delimitada para el campochoice.
Ahora que poseemos una familiaridad básica con el modelo de datos, observemos el código responsable para convertir estos datos XML en una aplicación útil.
El análisis de datos es un ejercicio algo mecánico que se muestra más adelante en este tutorial. Antes de examinar el proceso de análisis, la aplicación 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;
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()
{
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.
- Hay cuatro variables de miembro:
formNumber: Este es el único identificador para el mecanismo de distribución del formulario del lado del servidor.formName: Este atributo se convierte en el título del formulario, el cual provee el contexto y la confirmación para el usuario.submitTo: Esta es la URL para la aplicación para enviar los datos que se introdujeron (después de haberlos validado). Este valor también 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 paraXmlGuiFormField.java.- Una serie de
gettersysetterspara cada una de estas variables. - Los métodos
toString()ygetFormattedResults()son los responsables de generar resúmenes para lectura humana directa de la claseXmlGuiForm. - El método
getFormEncodedData()es utilizado al preparar los datos para enviarlos a la URL indicada en el atributosubmitTo. - En lugar de utilizar clases
java.lang.Stringestrictamente concatenadas, el código emplea unStringBuildercomo un medio de memoria más eficiente para construir las cadenas de datos deseadas. - La clase
URLEncoderes 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. - Algunas expansiones potenciales de esta aplicación incluyen:
- Almacenamiento local o en caché de los metadatos para hacer que las tareas repetitivas se ejecuten más rápido.
- Almacenamiento local para registrar los datos durante un período de tiempo antes de enviarlos.
- Registro— de fecha y hora por GPS en cada registro con datos de ubicación.
Ahora observemos la construcción 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");
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:
namecontiene el nombre del campo— este es el nombre del campo del valor de los datos, análogo al nombre del campo de un formulario en HTML o el nombre de columna de base de datos.labelcontiene una descripción del campo o el valor que se muestra al usuario.typeindica el tipo de campo de la interfaz de usuario que se desea construir.textsignifica que este campo se implementa con un campoEditTextpara entradas alfanuméricas. Este es el valor más común.numerictambién es un valorEditText, pero solo está limitado a un valor de entrada numérica.choicehace que el campo sea una lista desplegable.requiredes 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.optionses un valor de cadena utilizado para transmitir la lista de selecciones disponibles para un campo de elección. Este campo está disponible para otros campos para ser utilizado quizás como una expresiónregexpara validación o puede ser sustituido para especificar un valor predeterminado.objrepresenta el widget de la interfaz de usuario. Por ejemplo, esta variable contiene unEditTextpara un campo numérico o de texto. Para un campo de elección, el miembroobjcontiene un widgetspinner. Este abordaje se explica con mayor detalle más adelante en este tutorial.- Como se preveía, estas variables tienen un número de
gettersysetters. - Los métodos
toString()ygetFormattedResult()aprovechan el métodogetData()que se explica a continuación. - En la clase
XmlGuiFormField, es necesario gestionar más de un tipo de datos por lo que el código necesita ser explícito sobre cómo almacenar y acceder a los datos. El métodogetData()examina el tipo de cambio y realiza una conversión de tipo en el campoobjpara interactuar correctamente con el objeto almacenado. Si desea agregar nuevos tipos de campos a esta a infraestructura, puede expandir el métodogetData()para que este sea compatible con el nuevo tipo de campo (vea el comentario cerca del final del Listado 3.
Ahora posee un método para almacenar y gestionar los metadatos. Es tiempo de ver a la aplicación en acción y después comenzar a atar las piezas entre sí.