aplicación móvil para proporcionar información sensible...

160

Upload: trinhkhue

Post on 28-Sep-2018

220 views

Category:

Documents


0 download

TRANSCRIPT

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página 2

Contenido Resumen ....................................................................................................................................... 6

Introducción ................................................................................................................................ 7

¿Qué es Android? ..................................................................................................................... 7

Entorno de desarrollo Android ............................................................................................... 7

1. Descargar la biblioteca JDK de Java ................................................................................. 7

2. Descargar el programa Android SDK .............................................................................. 8

3. Actualización de las APIs con SDK Manager .................................................................. 9

4. Configurar la dirección de la carpeta SDK en Eclipse ................................................... 10

5. Configurar un dispositivo virtual de Android ................................................................ 12

Estructura de un proyecto Android ....................................................................................... 15

Carpeta /src/ ........................................................................................................................ 16

Carpeta /res/ ........................................................................................................................ 16

Carpeta /gen/ ...................................................................................................................... 17

Carpeta /assets/ ................................................................................................................... 18

Fichero AndroidManifest.xml ............................................................................................ 19

Componentes de una aplicación Android ............................................................................. 19

Activity ................................................................................................................................ 19

View ..................................................................................................................................... 19

Service ................................................................................................................................. 20

Content Provider ................................................................................................................ 20

Broadcast Receiver ............................................................................................................. 20

Widget ................................................................................................................................ 20

Intent .................................................................................................................................. 20

Desarrollo de una aplicación sencilla.................................................................................... 20

Bases de datos ......................................................................................................................... 31

Bases de datos según la variabilidad de los datos almacenados ....................................... 31

Bases de datos según el contenido ..................................................................................... 32

Manejador de base de datos SQLite ................................................................................... 32

Instalación del entorno de desarrollo SQLite ................................................................ 33

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página 3

Ejemplo de desarrollo de bases de datos con SQLite ....................................................34

SQLite en Android ..................................................................................................................36

Mantenimiento de base de datos en SQLite ..................................................................... 42

Consultas y recuperación de registros en SQLite ................................................................. 44

Código QR .............................................................................................................................. 46

ZXing ("Zebra Crossing") ................................................................................................... 47

Uso de Zxing en una aplicación Android .......................................................................... 48

Desarrollo ................................................................................................................................... 62

Planeación .............................................................................................................................. 62

Diseño......................................................................................................................................63

Implementación ..................................................................................................................... 67

Prerrequisitos (archivos necesarios) ................................................................................. 67

uamdb.db ........................................................................................................................ 68

Generación de la aplicación ............................................................................................... 76

Inserción de las imágenes .................................................................................................. 76

Decodificador QR ................................................................................................................ 77

Inserción de la base de datos .............................................................................................. 77

Utilidades ........................................................................................................................... 78

Layouts (Interfaces de la aplicación) ................................................................................. 79

main.xml ......................................................................................................................... 79

qr.xml .............................................................................................................................. 80

schedule.xml .................................................................................................................... 81

building.xml ....................................................................................................................83

floor.xml ..........................................................................................................................83

room.xml ........................................................................................................................ 84

sala.xml ........................................................................................................................... 86

cubículo.xml ................................................................................................................... 88

laboratorio.xml ............................................................................................................... 89

profesor.xml .................................................................................................................... 92

teacher.xml ..................................................................................................................... 93

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página 4

grupos.xml ...................................................................................................................... 94

uea.xml ........................................................................................................................... 96

Recursos para los layouts ................................................................................................... 97

custom_row_horario.xml ............................................................................................... 97

custom_row_grupo.xml ................................................................................................. 98

Clases abstractas para los registros de la base de datos ................................................... 98

Edificio.java .................................................................................................................... 99

Piso.java .......................................................................................................................... 99

Sala.java ......................................................................................................................... 100

TipoSala.java ................................................................................................................... 101

Profesor.java .................................................................................................................. 102

SalaProfesor.java ........................................................................................................... 103

UEA.java ........................................................................................................................ 104

Grupo.java...................................................................................................................... 105

Horario.java ................................................................................................................... 105

Estudiante.java .............................................................................................................. 107

GrupoLista.java .............................................................................................................. 108

Utilidades de las clases ...................................................................................................... 110

GrupoAdapter.java ......................................................................................................... 110

HorarioAdapter.java ....................................................................................................... 113

HorarioSalaAdapter.java ................................................................................................ 115

Bases de datos .................................................................................................................... 117

DBHelper.java................................................................................................................. 117

Intents................................................................................................................................ 136

Main.java ....................................................................................................................... 136

FrmBuilding.java ........................................................................................................... 140

FrmFloor.java ................................................................................................................ 142

FrmRoomList.java ......................................................................................................... 144

FrmRoom.java ............................................................................................................... 146

FrmProfesor.java ........................................................................................................... 149

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página 5

FrmTeacherList.java ....................................................................................................... 151

FrmUEA.java ................................................................................................................... 153

FrmGrupos.java ............................................................................................................. 154

FrmSchedule.java .......................................................................................................... 155

FrmQR.java .................................................................................................................... 156

Permisos (AndroidManifest.xml) ..................................................................................... 156

Resultados ............................................................................................................................. 158

Discusión ................................................................................................................................... 159

Conclusiones ............................................................................................................................. 159

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página 6

Resumen En este documento se da a conocer la realización de una aplicación móvil sobre la plataforma Android, el cuál manejará información en una base de datos referente a la

localización, cubículos, laboratorios, salas, profesores y algunas Unidades de Enseñanza - Aprendizaje que se imparten en la carrera de Licenciatura en Computación en la

Universidad Autónoma Metropolitana Unidad Iztapalapa (UAM-I).

Mediante la aplicación lo que logra es dar información sensible a la ubicación para los usuarios, mediante la lectura de un código especial QR, implementados en lugares previamente estudiados. Esta información se encuentra almacenado en el dispositivo móvil

en una base de datos propia de la aplicación.

En el diseño e implementación de la aplicación, se involucraron varias pruebas, las cuales

fueron:

• Pruebas de integración de distintas ventanas en Android

• Generación e integración de una base de datos

• Consultas en la base de datos interna por medio de la aplicación

• Consulta de información almacenada en un código QR por medio de una aplicación

• Integración de la lectura de códigos QR para ejecutar eventos de consulta de la base de datos de la aplicación final.

• Realización de una presentación del producto prototipo a los usuarios finales, los cuales opinaron sobre la usabilidad de la aplicación.

Dichas pruebas fueron realizadas tomando en cuenta la información referente al Área de

Redes y Telecomunicaciones de la Universidad.

Como primer versión de la aplicación, se desarrolló la base de información con un programa

externo, para luego incorporarlo a la aplicación para su consulta.

Debido a factores no controlables al desarrollo, se omitió la manipulación de la base de datos directamente en la aplicación, teniendo que actualizar la información con un sistema

externo, para después incorporarlo manualmente por medio del entorno de desarrollo de la

aplicación.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página 7

Introducción

¿Qué es Android?

Android es un sistema operativo basado en Linux, diseñado principalmente para móviles

con pantalla táctil como teléfonos inteligentes o tabletas, inicialmente desarrollados por

Android, Inc., que Google respaldó económicamente y más tarde compró en 2005. Android fue desvelado en 2007 junto la fundación del Open Handset Alliance: un consorcio de

compañías de hardware, software y telecomunicaciones para avanzar en los estándares

abiertos de los dispositivos móviles.

Tiene una gran comunidad de desarrolladores escribiendo aplicaciones para extender la funcionalidad de los dispositivos. A la fecha, se han sobrepasado las 700.000 aplicaciones (de

las cuales, dos tercios son gratuitas) disponibles para la tienda de aplicaciones oficial de Android: Google Play, sin tener en cuenta aplicaciones de otras tiendas no oficiales para Android, como pueden ser la App Store de Amazon o la tienda de aplicaciones Samsung Apps de Samsung. Google Play es la tienda de aplicaciones en línea administrada por

Google, aunque existe la posibilidad de obtener software externamente. Los programas están escritos en el lenguaje de programación Java. No obstante, no es un sistema operativo libre

de malware, aunque la mayoría de ello es descargado de sitios de terceros.

Entorno de desarrollo Android

Para poder realizar una aplicación en Android, requerimos describir los pasos básicos para disponer en nuestra computadora, el entorno y herramientas necesarias. A continuación

enumeraremos los pasos necesarios de instalación y configuración, además de proporcionar los enlaces requeridos de las herramientas.

1. Descargar la biblioteca JDK de Java

Para empezar a desarrollar aplicaciones en Android, requerimos del JDK de Java, con la

versión 6 o superior. Esto es necesario pues parte de la programación de las aplicaciones se realizan en lenguaje Java, y el entorno de desarrollo lo requiere.

El enlace para descargar el JDK para Windows es el siguiente:

http://www.oracle.com/technetwork/es/java/javase/downloads/index.html

En nuestro caso, descargamos la versión 7u25, pues es la más reciente ofrecida por la página

de Oracle

1.

En seguida instalamos el archivo descargado en nuestra computadora.

2. Descargar el programa Android SDK

Como últimamente Google ha visto un gran avance en el desarrollo de aplicaciones en Android, siendo un sistema operativo preferido por la comunidad de desarrolladores, se ha dispuesto a entregar un paquete con lo necesario para poder desarrollar estas aplicaciones

de la manera más simple posible. Nos dirigimos a la siguiente página para descargar Android

SDK:

http://developer.android.com/sdk/index.html

El SDK incluye un set comprensible de herramientas de desarrollo. Este incluye un depurador de errores, bibliotecas, un emulador basado en QEMU, documentación, códigos

de ejemplo, y tutoriales2.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página 9

Una vez descargado el SDK que se proporciona en una carpeta comprimida, extraemos el

contenido a una ubicación deseada.

El directorio contiene las siguientes carpetas:

• eclipse. En él se encuentra un ejecutable que abre el IDE de Eclipse, configurado especialmente para el desarrollo de aplicaciones de Android.

• SDK. En esta carpeta se encuentra todas las bibliotecas y documentación de Android.

• SDK Manager. Este ejecutable es un administrador de paquetes necesarios para desarrollar sobre distintas versiones del API de Android. Estas APIs son paquetes con

características específicas que son soportadas por las distintas generaciones de

dispositivos móviles y tabletas.

3. Actualización de las APIs con SDK Manager

Al ejecutar por primera vez el SDK Manager, tendrá como APIs descargadas las versiones

más recientes que se tienen registrados en las bases de datos de Google.

Desde aquí podemos seleccionar las APIs respectivas para la versión a la cual vamos a desarrollar. Cabe mencionar que actualmente la versión más utilizada es la 4.1 (Jelly Bean),

quien acaba de superar recientemente al uso de las versiones 3.0 (Honeycomb) y 4.0 (Ice Cream Sandwich). En este caso, es preferencia del desarrollador o la petición de los

directivos la versión en la que se piensa desarrollar la aplicación.

Se tiene que considerar en el desarrollo de las aplicaciones, que desde la versión 3.0 en

adelante, se cuenta con un soporte de compatibilidad en el desarrollo para dispositivos

grandes, es decir, tabletas.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

10

Ahora bien, si se tiene algo de tiempo libre, se puede descargar todas las APIs disponibles,

los cuales ocuparían una capacidad de 6.9 GB.

4. Configurar la dirección de la carpeta SDK en Eclipse

Ya descargadas las APIs de Android, debemos de darle a conocer al IDE Eclipse donde se

encuentran dichas bibliotecas para que puedan ser usadas en el desarrollo de la aplicación.

Para lograr esto se deben de llevar a cabo los siguientes pasos:

1. Abrimos el IDE Eclipse. Este se encuentra dentro de la carpeta ./adt-bundle-windows-x86_64/eclipse/, como se muestra en la siguiente imagen:

Predeterminadamente, Eclipse nos muestra la siguiente ventana emergente, donde se van a

guardar todos nuestros proyectos. El usuario puede seleccionar la ubicación que le dará a sus

archivos, pero nosotros dejaremos la dirección que viene por defecto.

2. En la barra de menú, seleccionamos la opción Window/Preferences.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

11

3. En la ventana emergente "Preferences", seleccionamos la opción “Android” y presionamos el botón “Browse...”, para ubicar la carpeta “sdk”, que también se

encuentra en ./adt-bundle-windows-x86_64.

4. Una vez ubicada la carpeta, presionan el botón “Apply” y después “OK”.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

12

Listo. Ya tenemos configurado el IDE Eclipse para el desarrollo de aplicaciones.

5. Configurar un dispositivo virtual de Android

En el momento en el que se requiere probar y corregir errores de las aplicaciones, no se

requiere hacerlo necesariamente sobre un dispositivo físico. El SDK cuenta con una herramienta de virtualización del sistema operativo Android, el cuál puede crear los

dispositivos virtuales necesarios para llevar a cabo estas tareas. Para crear un dispositivo

virtual debemos de llevar a cabo los siguientes pasos:

1. Dentro de Eclipse, seleccionamos de la barra de menú, la opción Window/Android

Virtual Device Manager, el cual nos despliega la siguiente ventana:

2. En la etiqueta “Android Virtual Devices”, presionamos el botón “New...” para abrir el

formulario para crear la nueva máquina virtual.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

13

3. En el formulario, escribimos el nombre de la máquina virtual, y seleccionamos el tamaño de la pantalla, versión de Android que contendrá el dispositivo virtual, el

tipo de CPU con el que cuenta el dispositivo, si existe teclado físico, si se despliegan controles de hardware, como el volumen y control de la interfaz, cuanta memoria RAM tiene soportada, así como el tamaño de pila de la máquina virtual, capacidad de almacenamiento interno y si cuenta con una memoria externa (también virtual),

además de algunas opciones más de la emulación. Una vez establecido los parámetros, presionamos el botón aceptar para crear el dispositivo virtual.

4. Para ejecutarlo, simplemente seleccionamos la máquina virtual y presionamos el

botón “Start...”, y en la ventana emergente, presionamos “Launch”.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

14

En este caso ejecuté un dispositivo virtual que asemeja ser una tableta.

NOTA: En algunas ocasiones, al estar desarrollando nuestras aplicaciones, se puede presentar una dificultad cuando se quiere ejecutar una máquina virtual, mostrándonos un

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

15

mensaje de error en el que se describe que no es posible correr el dispositivo virtual. Para

poder corregir el error, tenemos que hacer lo siguiente:

1. Abrir la carpeta en donde se encuentran nuestros códigos desarrollados y nuestro IDE, que en nuestro caso se encuentran en la unidad E:

2. Copiamos la carpeta ".android"

3. Nos dirigimos a la carpeta del usuario

4. Borramos la carpeta ".android" que se encuentra en esta carpeta, y pegamos la que habíamos copiado anteriormente. Con esto se soluciona este problema, y las

ejecuciones de los dispositivos virtuales Android se iniciarán sin ningún problema.

Estructura de un proyecto Android

Para empezar a comprender cómo se construye una aplicación Android vamos a echar un

vistazo a la estructura general de un proyecto tipo3.

Cuando creamos un nuevo proyecto Android en Eclipse se genera automáticamente la

estructura de carpetas necesaria para poder generar posteriormente la aplicación. Esta

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

16

estructura será común a cualquier aplicación, independientemente de su tamaño y

complejidad.

En la siguiente imagen vemos los elementos creados inicialmente para un nuevo proyecto Android:

En los siguientes apartados describiremos los elementos principales de esta estructura.

Carpeta /src/

Contiene todo el código fuente de la aplicación, código de la interfaz gráfica, clases

auxiliares, etc. Inicialmente, Eclipse creará por nosotros el código básico de la pantalla

(Activity) principal de la aplicación, siempre bajo la estructura del paquete java definido.

Carpeta /res/

Contiene todos los ficheros de recursos necesarios para el proyecto: imágenes, vídeos, cadenas de texto, etc. Los diferentes tipos de recursos de deberán distribuir entre las

siguientes carpetas:

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

17

Como ejemplo, para un proyecto nuevo Android, se crean los siguientes recursos para la

aplicación:

Carpeta /gen/

Contiene una serie de elementos de código generados automáticamente al compilar el

proyecto. Cada vez que generamos nuestro proyecto, la maquinaria de compilación de Android genera por nosotros una serie de ficheros fuente en java dirigidos al control de los

recursos de la aplicación.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

18

El más importante es el que se puede observar en la imagen, el fichero R.java, y la clase R.

Esta clase R contendrá en todo momento una serie de constantes con los ID de todos los recursos de la aplicación incluidos en la carpeta /res/, de forma que podamos acceder

fácilmente a estos recursos desde nuestro código a través de este dato. Así, por ejemplo, la

constante R.drawable.icon contendrá el ID de la imagen “icon.png” contenida en la carpeta /res/drawable/. Veamos como ejemplo la clase R creada por defecto para un proyecto nuevo:

package net.sgoliver; public final class R { public static final class attr { } public static final class drawable { public static final int icon=0x7f020000; } public static final class layout { public static final int main=0x7f030000; } public static final class string { public static final int app_name=0x7f040001; public static final int hello=0x7f040000; } }

Carpeta /assets/

Contiene todos los demás ficheros auxiliares necesarios para la aplicación (y que se

incluirán en su propio paquete), como por ejemplo ficheros de configuración, de datos, etc.

La diferencia entre los recursos incluidos en la carpeta /res/raw/ y los incluidos en la carpeta /assets/ es que para los primeros se generará un ID en la clase R y se deberá acceder a ellos

con los diferentes métodos de acceso a recursos. Para los segundos sin embargo no se

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

19

generarán ID y se podrá acceder a ellos por su ruta como a cualquier otro fichero del

sistema. Usaremos uno u otro según las necesidades de nuestra aplicación.

Fichero AndroidManifest.xml

Contiene la definición en XML de los aspectos principales de la aplicación, como por

ejemplo su identificación (nombre, versión, ícono, ...), sus componentes (pantallas,

mensajes, ...), o los permisos necesarios para su ejecución. Veremos más adelante más detalles de este fichero.

En el siguiente apartado veremos los componentes software principales con los que

podemos construir una aplicación Android.

Componentes de una aplicación Android

En el apartado anterior vimos la estructura de un proyecto Android y aprendimos dónde colocar cada uno de los elementos que componen una aplicación, tanto elementos de

software como recursos gráficos o de datos. En éste nuevo post vamos a centrarnos específicamente en los primeros, es decir, veremos los distintos tipos de componentes de

software con los que podremos construir una aplicación Android.

En Java o .NET estamos acostumbrados a manejar conceptos como ventana, control, eventos

o servicios como los elementos básicos en la construcción de una aplicación.

Pues bien, en Android vamos a disponer de esos mismos elementos básicos aunque con un pequeño cambio en la terminología y el enfoque. Repasemos los componentes principales que pueden formar parte de una aplicación Android (Por claridad, y para evitar confusiones

al consultar documentación en inglés, intentaré traducir lo menos posible los nombres originales de los componentes).

Activity

Las actividades (activities) representan el componente principal de la interfaz gráfica de una

aplicación Android. Se puede pensar en una actividad como el elemento análogo a una

ventana en cualquier otro lenguaje visual.

View

Los objetos view son los componentes básicos con los que se construye la interfaz gráfica de

la aplicación, análogo por ejemplo a los controles de Java o .NET. De inicio, Android pone a nuestra disposición una gran cantidad de controles básicos, como cuadros de texto, botones, listas desplegables o imágenes, aunque también existe la posibilidad de extender la

funcionalidad de estos controles básicos o crear nuestros propios controles personalizados.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

20

Service

Los servicios son componentes sin interfaz gráfica que se ejecutan en segundo plano. En concepto, son exactamente iguales a los servicios presentes en cualquier otro sistema

operativo. Los servicios pueden realizar cualquier tipo de acciones, por ejemplo actualizar datos, lanzar notificaciones, o incluso mostrar elementos visuales (p.ej. activities) si se

necesita en algún momento la interacción con del usuario.

Content Provider

Un content provider es el mecanismo que se ha definido en Android para compartir datos entre aplicaciones. Mediante estos componentes es posible compartir determinados datos de nuestra aplicación sin mostrar detalles sobre su almacenamiento interno, su estructura, o

su implementación. De la misma forma, nuestra aplicación podrá acceder a los datos de otra

a través de los content provider que se hayan definido.

Broadcast Receiver

Un broadcast receiver es un componente destinado a detectar y reaccionar ante

determinados mensajes o eventos globales generados por el sistema (por ejemplo: “Batería baja”, “SMS recibido”, “Tarjeta SD insertada”, ...) o por otras aplicaciones (cualquier aplicación puede generar mensajes (intents, en terminología Android) broadcast, es decir,

no dirigidos a una aplicación concreta sino a cualquiera que quiera escucharlo).

Widget

Los widgets son elementos visuales, normalmente interactivos, que pueden mostrarse en la

pantalla principal (home screen) del dispositivo Android y recibir actualizaciones periódicas.

Permiten mostrar información de la aplicación al usuario directamente sobre la pantalla

principal.

Intent

Un intent es el elemento básico de comunicación entre los distintos componentes Android que hemos descrito anteriormente. Se pueden entender como los mensajes o peticiones que son enviados entre los distintos componentes de una aplicación o entre distintas

aplicaciones. Mediante un intent se puede mostrar una actividad desde cualquier otra, iniciar un servicio, enviar un mensaje broadcast, iniciar otra aplicación, etc.

En el siguiente apartado empezaremos ya a ver algo de código, analizando al detalle una

aplicación sencilla.

Desarrollo de una aplicación sencilla

Después de instalar nuestro entorno de desarrollo para Android y comentar la estructura básica de un proyecto y los diferentes componentes software que podemos utilizar ya es

hora de empezar a escribir algo de código.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

21

La aplicación que se realizará es un simple hola mundo, pero con un poco más de características, que dará como resultado un mejor entendimiento del código y el proceso de

creación de la aplicación.

La aplicación contará con 2 pantallas, por un lado la primer pantalla solicitará un nombre al

usuario, y la segunda pantalla se mostrará un mensaje personalizado para el usuario.

Para desarrollar esta aplicación debemos de seguir los siguientes pasos:

1. En el entorno de desarrollo, seleccionamos en la barra de menús, File/New/Android

Application Proyect.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

22

2. En la ventana emergente, seleccionamos el nombre de la aplicación, el cual se llamará “Hola Usuario”, el nombre del proyecto, y el paquete predeterminado en donde se guardará el código fuente. Aquí también seleccionamos el target mínimo

requerido, como ejemplo la versión 2.1. También seleccionamos el target máximo al que va dirigido que es en este caso Android en su versión 4.2. Además, podemos

seleccionar un tema en específico para darle una consistencia con respecto a la apariencia de la aplicación. Al finalizar de llenar los campos requeridos,

seleccionamos la opción “Next”.

3. En la siguiente ventana, podemos seleccionar o no si queremos agregar un ícono personalizado a nuestra aplicación, además de crear un Activity nuevo. Marcamos las

casillas como viene en la siguiente imagen, y presionamos “Next”.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

23

4. En la siguiente ventana, nos muestra las opciones acerca de la apariencia general de la aplicación. Dependiendo del mínimo requerido de la versión de Android, aparecerán soportes para distintos tamaños de pantallas, o efectos que aparecieron

en versiones más actuales. Presionamos la opción “Next”.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

24

5. En la última pantalla del formulario de creación del proyecto, seleccionamos el

nombre de la clase principal, así como el nombre del layout principal. Un layout es la interfaz en donde se colocan todos los componentes que se requieren ver en la

pantalla. Por medio de los activities podemos dibujarlos en la pantalla del dispositivo, además de agregar los procesos que se requieren cuando se realiza

alguna acción en específico, como presionar un botón o demás. Ya para terminar de

crear el proyecto, presionamos finalmente el botón “Finish”.

Como ya vimos, esto nos genera la estructura de carpetas del proyecto y todos los ficheros necesarios para un Hola Mundo básico, es decir, una sola pantalla en donde se muestra

únicamente un mensaje fijo.

Lo primero que vamos a hacer es diseñar la pantalla principal de nuestra aplicación,

modificando la que el programa ha generado por defecto.

6. Abrimos el archivo main.xml (HolaUsuario/res/layout/)en donde se encuentra el conjunto de controles que vamos a requerir. En el reemplazamos el código generado

por defecto por el siguiente código:

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

25

<?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="fill_parent"> <TextView android:text="@string/nombre" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <EditText android:id="@+id/TxtNombre" android:layout_width="fill_parent" android:layout_height="wrap_content" android:inputType="text"></EditText> <Button android:id="@+id/BtnHola" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hola"/> </LinearLayout>

En este XML se definen los elementos visuales que componen la interfaz de nuestra pantalla

principal y se especifican todas sus propiedades. No nos detendremos mucho por ahora en

cada detalle, pero expliquemos un poco lo que vemos en el fichero.

Lo primero que nos encontramos es un elemento LinearLayout. Los layout son elementos no

visibles que determinan cómo se van a distribuir en el espacio los controles que incluyamos en su interior. Los programadores java, y más concretamente de Swing, conocerán este concepto perfectamente. En este caso, un LinearLayout distribuirá los controles uno tras

otro y en la orientación que indique su propiedad android:orientation.

Dentro del layout hemos incluido 3 controles: una etiqueta (TextView), un cuadro de texto (EditText), y un botón (Button). En todos ellos hemos establecido las siguientes

propiedades:

• android:id. ID del control, con el que podremos identificarlo más tarde en nuestro

código. Vemos que el identificador lo escribimos precedido de “@+id/”. Esto tendrá

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

26

como efecto que al compilarse el proyecto se genere automáticamente una nueva constante en la clase R para dicho control.

• android:text. Texto del control. En Android, el texto de un control se puede especificar directamente, o bien utilizar alguna de las cadenas de texto definidas en

los recursos del proyecto (fichero strings.xml (HolaUsuario/res/values/)), en cuyo

caso indicaremos su identificador precedido del prefijo “@string/”.

<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Hola Usuario</string> <string name="hello_world">Hello world!</string> <string name="menu_settings">Settings</string> <string name="nombre">Escribe tu nombre: </string> <string name="hola">Hola </string> </resources>

• android:layout_height y android:layout_width. Dimensiones del control con respecto al layout que lo contiene. Esta propiedad tomará normalmente los valores

“wrap_content” para indicar que las dimensiones del control se ajustarán al contenido del mismo, o bien “fill_parent” para indicar que el ancho o el alto del control se ajustará al ancho o alto del layout contenedor respectivamente.

7. Con esto ya tenemos definida la presentación visual de nuestra ventana principal de la aplicación. De igual forma definiremos la interfaz de la segunda pantalla, creando

un nuevo fichero llamado frmmensaje.xml, y añadiendo esta vez tan solo una

etiqueta (TextView) para mostrar el mensaje personalizado al usuario. Veamos cómo quedaría nuestra segunda pantalla:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/TxtMensaje" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text=""></TextView>

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

27

</LinearLayout>

Una vez definida la interfaz de las pantallas de la aplicación deberemos implementar la

lógica de la misma. Como ya hemos comentado, la lógica de la aplicación se definirá en ficheros java independientes. Para la pantalla principal ya tenemos creado un fichero por

defecto llamado Main.java. Empecemos por comentar su código por defecto:

package uam.pi1.holausuario; import android.os.Bundle; import android.app.Activity; public class Main extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } }

Como ya vimos en un apartado anterior, las diferentes pantallas de una aplicación Android se definen mediante objetos de tipo Activity. Por tanto, lo primero que encontramos en

nuestro fichero java es la definición de una nueva clase HolaUsuario que extiende a Activity. El único método que sobrescribiremos de esta clase será el método OnCreate, llamado

cuando se crea por primera vez la actividad. En este método lo único que encontramos en principio, además de la llamada a su implementación en la clase padre, es la llamada al método setContentView(R.layout.main). Con esta llamada estaremos indicando a Android

que debe establecer como interfaz gráfica de esta actividad la definida en el recurso R.layout.main, que no es más que la que hemos especificado en el fichero /res/layout/main.xml. Una vez más vemos la utilidad de las diferentes constantes de

recursos creadas automáticamente en la clase R al compilar el proyecto4.

8. En principio vamos a crear una nueva actividad para la segunda pantalla de la aplicación análoga a ésta primera, para lo que crearemos una nueva clase FrmMensaje que extienda de Activity y que implemente el método onCreate

indicando que utilice la interfaz definida en R.layout.frmmensaje.

package com.shell.holausuario; import android.os.Bundle;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

28

import android.widget.TextView; import android.app.Activity; public class FrmMensaje extends Activity { @Override public void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.frmmensaje); } }

Como vemos, el código incluido por defecto en estas clases lo único que hace es generar la interfaz de la actividad. A partir de aquí nosotros tendremos que incluir el resto de la lógica

de la aplicación.

9. Empezamos con la actividad principal Main, obteniendo una referencia a los

diferentes controles de la interfaz que necesitemos manipular, en nuestro caso sólo el cuadro de texto y el botón. Para ello utilizaremos el método findViewById()

indicando el ID de cada control, definidos como siempre en la clase R:

final EditText txtNombre = (EditText)findViewById(R.id.TxtNombre); final Button btnHola = (Button)findViewById(R.id.BtnHola);

10. Una vez tenemos acceso a los diferentes controles, ya sólo nos queda implementar las acciones a tomar cuando pulsemos el botón de la pantalla. Para ello

implementaremos el evento onClick de dicho botón.

btnHola.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { Intent intent = new Intent(HolaUsuario.this, FrmMensaje.class); Bundle bundle = new Bundle(); bundle.putString("NOMBRE", txtNombre.getText().toString()); intent.putExtras(bundle); startActivity(intent); } });

Como ya indicamos en el apartado anterior, la comunicación entre los distintos componentes y aplicaciones en Android se realiza mediante intents, por lo que el primer

paso será crear un objeto de este tipo. Existen varias variantes del constructor de la clase Intent, cada una de ellas dirigida a unas determinadas acciones, pero en nuestro caso

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

29

particular vamos a utilizar el intent para llamar a una actividad desde otra de la misma aplicación, para lo que pasaremos al constructor una referencia a la propia actividad

llamadora (HolaUsuario.this), y la clase de la actividad llamada (FrmMensaje.class).

Si quisiéramos tan sólo mostrar una nueva actividad ya tan sólo nos quedaría llamar a

startActivity() pasándole como parámetro el intent creado. Pero en nuestro ejemplo queremos también pasarle cierta información a la actividad, concretamente el nombre que

introduzca el usuario en el cuadro de texto. Para hacer esto vamos a crear un objeto Bundle, que puede contener una lista de pares clave-valor con toda la información a pasar entre las actividades. En nuestro caso sólo añadiremos un dato de tipo String mediante el método

putString(clave, valor). Tras esto añadiremos la información al intent mediante el método putExtras(bundle).

11. Finalizada la actividad principal de la aplicación pasamos ya a la secundaria. Comenzaremos de forma análoga a la anterior, ampliando el método onCreate

obteniendo las referencias a los objetos que manipularemos, esta vez sólo la etiqueta de texto. Tras esto viene lo más interesante, debemos recuperar la información

pasada desde la actividad principal y asignarla como texto de la etiqueta. Para ello accederemos en primer lugar al intent que ha originado la actividad actual mediante el método getIntent() y recuperaremos su información asociada (objeto Bundle)

mediante el método getExtras().

Hecho esto tan sólo nos queda construir el texto de la etiqueta mediante su método

setText(texto) y recuperando el valor de nuestra clave almacenada en el objeto Bundle mediante getString(clave).

package com.shell.holausuario; import android.os.Bundle; import android.widget.TextView; import android.app.Activity; public class FrmMensaje extends Activity { @Override public void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.frmmensaje); TextView txtMensaje = (TextView)findViewById(R.id.TxtMensaje); Bundle bundle = getIntent().getExtras(); txtMensaje.setText("Hola " + bundle.getString("NOMBRE")); }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

30

}

Con esto hemos concluido la lógica de las dos pantallas de nuestra aplicación y tan sólo nos

queda un paso importante para finalizar nuestro desarrollo. Como ya indicamos en alguna ocasión, toda aplicación Android utiliza un fichero especial en formato XML

(AndroidManifest.xml) para definir, entre otras cosas, los diferentes elementos que la componen. Por tanto, todas las actividades de nuestra aplicación deben quedar convenientemente recogidas en este fichero. La actividad principal ya debe aparecer puesto

que se creó de forma automática al crear el nuevo proyecto Android, por lo que debemos añadir tan sólo la segunda. Para este ejemplo nos limitaremos a incluir la actividad en el

XML, más adelante veremos que opciones adicionales podemos especificar.

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.shell.holausuario" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.shell.holausuario.Main" 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="com.shell.holausuario.FrmMensaje"> </activity>

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

31

</application> </manifest>

Si todo se ha desarrollado completamente bien, podemos ver el resultado final ejecutando el

programa en nuestro dispositivo virtual.

Bases de datos

Una base de datos un conjunto de datos pertenecientes a un mismo contexto y almacenados

sistemáticamente para su posterior uso. En este sentido, una biblioteca puede considerarse una base de datos compuesta en su mayoría por documentos y textos impresos en papel e

indexados para su consulta. Actualmente, y debido al desarrollo tecnológico de campos como la informática y la electrónica, la mayoría de las bases de datos están en formato

digital.

Existen programas denominados sistemas gestores de bases de datos, abreviado SGBD, que

permiten almacenar y posteriormente acceder a los datos de forma rápida y estructurada. Las propiedades de estos SGBD, así como su utilización y administración, se estudian dentro

del ámbito de la informática.

Las aplicaciones más usuales son para la gestión de empresas e instituciones públicas.

También son ampliamente utilizadas en entornos científicos con el objeto de almacenar la

información experimental.

Las bases de datos pueden clasificarse de varias maneras, de acuerdo al contexto que se esté manejando, la utilidad de las mismas o las necesidades que satisfagan.

Bases de datos según la variabilidad de los datos almacenados

Bases de datos estáticas.- Son bases de datos de sólo lectura, utilizadas primordialmente

para almacenar datos históricos que posteriormente se pueden utilizar para estudiar el

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

32

comportamiento de un conjunto de datos a través del tiempo, realizar proyecciones, tomar

decisiones y realizar análisis de datos para inteligencia empresarial.

Bases de datos dinámicas.- Éstas son bases de datos donde la información almacenada se modifica con el tiempo, permitiendo operaciones como actualización, borrado y adición de

datos, además de las operaciones fundamentales de consulta. Un ejemplo de esto puede ser la base de datos utilizada en un sistema de información de un supermercado, una farmacia,

un videoclub o una empresa.

Bases de datos según el contenido

Bases de datos bibliográficas.- Sólo contienen un subrogante (representante) de la fuente

primaria, que permite localizarla. Un registro típico de una base de datos bibliográfica contiene información sobre el autor, fecha de publicación, editorial, título, edición, de una determinada publicación, etc. Puede contener un resumen o extracto de la publicación original, pero nunca el texto completo, porque si no, estaríamos en presencia de una base de

datos a texto completo (o de fuentes primarias —ver más abajo). Como su nombre lo indica, el contenido son cifras o números. Por ejemplo, una colección de resultados de análisis de

laboratorio, entre otras.

Bases de datos de texto completo.- Almacenan las fuentes primarias, como por ejemplo,

todo el contenido de todas las ediciones de una colección de revistas científicas.

Directorios.- Un ejemplo son las guías telefónicas en formato electrónico.

Además de la clasificación por la función de las bases de datos, éstas también se pueden clasificar de acuerdo a su modelo de administración de datos.

Algunos modelos con frecuencia utilizados en las bases de datos:

• Bases de datos jerárquicas

• Base de datos de red

• Bases de datos transaccionales

• Bases de datos relacionales

• Bases de datos multidimensionales

• Bases de datos orientadas a objetos

• Bases de datos documentales

• Bases de datos deductivas

Manejador de base de datos SQLite

SQLite es un sistema de gestión de bases de datos relacional compatible con ACID, contenida en una relativamente pequeña escrita en C. SQLite es un proyecto de dominio

público creado por D. Richard Hipp5.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

33

A diferencia de los sistema de gestión de bases de datos cliente-servidor, el motor de SQLite no es un proceso independiente con el que el programa principal se comunica. En lugar de eso, la biblioteca SQLite se enlaza con el programa pasando a ser parte integral del mismo.

El programa utiliza la funcionalidad de SQLite a través de llamadas simples a subrutinas y funciones. Esto reduce la latencia en el acceso a la base de datos, debido a que las llamadas a

funciones son más eficientes que la comunicación entre procesos. El conjunto de la base de datos (definiciones, tablas, índices, y los propios datos), son guardados como un sólo fichero

estándar en la máquina host. Este diseño simple se logra bloqueando todo el fichero de base

de datos al principio de cada transacción.

La biblioteca implementa la mayor parte del estándar SQL-92, incluyendo transacciones de base de datos atómicas, consistencia de base de datos, aislamiento, y durabilidad, triggers y

la mayor parte de las consultas complejas6.

SQLite usa un sistema de tipos inusual. En lugar de asignar un tipo a una columna como en

la mayor parte de los sistemas de bases de datos SQL, los tipos se asignan a los valores individuales. Por ejemplo, se puede insertar una cadena de caracteres en una columna de

tipo entero (a pesar de que SQLite tratará en primera instancia de convertir la cadena en un entero). Algunos usuarios consideran esto como una innovación que hace que la base de datos sea mucho más útil, sobre todo al ser utilizada desde un lenguaje de scripting de tipos

dinámicos. Otros usuarios lo ven como un gran inconveniente, ya que la técnica no es portable a otras bases de datos SQL. SQLite no trataba de transformar los datos al tipo de la

columna hasta la versión 3.

Varios procesos o hilos pueden acceder a la misma base de datos sin problemas. Varios

accesos de lectura pueden ser servidos en paralelo. Un acceso de escritura sólo puede ser servido si no se está sirviendo ningún otro acceso concurrentemente. En caso contrario, el acceso de escritura falla devolviendo un código de error (o puede automáticamente reintentarse hasta que expira un tiempo de expiración configurable). Esta situación de

acceso concurrente podría cambiar cuando se está trabajando con tablas temporales. Sin embargo, podría producirse un interbloqueo debido al multihilo. Este punto fue tratado en

la versión 3.3.4, desarrollada el 11 de febrero de 2006.

Existe un programa independiente de nombre SQLite que puede ser utilizado para consultar

y gestionar los ficheros de base de datos SQLite. También sirve como ejemplo para la

escritura de aplicaciones utilizando la biblioteca SQLite.

Instalación del entorno de desarrollo SQLite

Para poder administrar una base de datos con SQLite, se debe de descargar el software de la

página oficial (http://www.sqlite.org/download).

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

34

Como se requiere desarrollar en Windows 7, nos dirigimos al apartado de Binarios pre compilados de Windows, y seleccionamos la opción sqlite-shell-win32-x86-3071700.zip, el cual contiene el manejador de la base de datos por línea de comandos. Esta versión es

compatible con SQLite 3.7.17 y anteriores.

El archivo de compresión zip tiene almacenado un ejecutable el cual podemos extraer en cualquier directorio de preferencia. Para nuestra comodidad, lo insertamos en la unidad E: (donde tenemos los directorios de desarrollo de la aplicación e interfaces de desarrollo),

dentro de la carpeta "SQLite", que creamos para ese propósito.

Ejemplo de desarrollo de bases de datos con SQLite

Para poder empezar a desarrollar bases de datos por línea de comandos, simplemente ejecutamos la aplicación "sqlite3.exe", el cual nos despliega una ventana de línea de

comandos, en el cual se pueden empezar a ejecutar instrucciones SQL.

Otra forma de ejecutar el programa, es abriendo una línea de comandos (cmd) y escribiendo

la dirección completa en donde se encuentra el ejecutable. También podemos pasar un parámetro al ejecutable, escribiendo la instrucción "sqlite3.exe" seguido por el nombre del archivo que contiene la base de datos SQLite. Si este no existe, uno nuevo es creado

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

35

automáticamente. En el programa "sqlite3", uno puede escribir sentencias SQL (terminando

con punto y coma), presiona "Enter" y el comando SQL se ejecutará.

Por ejemplo, para crear una nueva base de datos llamada "ex1" con una tabla sencilla "tbl1" se

tiene que hacer lo siguiente:

Mayormente, SQLite3 solo lee líneas de entrada y pasan a la biblioteca de SQLite para su ejecución, pero si la entrada empieza con un punto ".", entonces esa línea es capturada e

interpretada por el mismo programa SQLite. Estos comandos son usados típicamente para cambiar el formato de la salida de las consultas, o para ejecutar sentencias de consultas pre cargadas. Para enlistar los comandos de punto disponibles, se puede ingresar ".help" en

cualquier momento. Por ejemplo:

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

36

Para más comandos se puede visitar la página oficial http://www.sqlite.org/sqlite.html, en donde se puede encontrar toda la documentación disponible con respecto a este manejador

de bases de datos.

SQLite en Android

Android incorpora de serie todas las herramientas necesarias para la creación y gestión de

bases de datos SQLite, y entre ellas una completa API para llevar a cabo de manera sencilla todas las tareas necesarias. Sin embargo, en este primer apartado sobre bases de datos en Android no vamos a entrar en mucho detalle con esta API. Por el momento nos limitaremos a ver el código necesario para crear una base de datos, insertaremos algún dato de prueba, y

veremos cómo podemos comprobar que todo funciona correctamente.

En Android, la forma típica para crear, actualizar, y conectar con una base de datos SQLite

será a través de una clase auxiliar llamada SQLiteOpenHelper, o para ser más exactos, de una clase propia que derive de ella y que debemos personalizar para adaptarnos a las

necesidades concretas de nuestra aplicación7.

La clase SQLiteOpenHelper tiene tan sólo un constructor, que normalmente no

necesitaremos sobrescribir, y dos métodos abstractos, onCreate() y onUpgrade(), que

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

37

deberemos personalizar con el código necesario para crear nuestra base de datos y para

actualizar su estructura respectivamente8.

Como ejemplo, nosotros vamos a crear una base de datos muy sencilla llamada BDUsuarios, con una sola tabla llamada Usuarios que contendrá sólo dos campos: nombre e email. Para

ellos, vamos a crear una clase derivada de SQLiteOpenHelper que llamaremos UsuariosSQLiteHelper, donde sobrescribiremos los métodos onCreate() y onUpgrade() para

adaptarlos a la estructura de datos indicada:

package net.sgoliver.android; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; public class UsuariosSQLiteHelper extends SQLiteOpenHelper { //Sentencia SQL para crear la tabla de Usuarios String sqlCreate = "CREATE TABLE Usuarios (codigo INTEGER, nombre TEXT)"; public UsuariosSQLiteHelper(Context contexto, String nombre, CursorFactory factory, int version) { super(contexto, nombre, factory, version); } @Override public void onCreate(SQLiteDatabase db) { //Se ejecuta la sentencia SQL de creación de la tabla db.execSQL(sqlCreate); } @Override public void onUpgrade(SQLiteDatabase db, int versionAnterior, int versionNueva) { //NOTA: Por simplicidad del ejemplo aquí utilizamos directamente //la opción de eliminar la tabla anterior y crearla de nuevo //vacía con el nuevo formato. //Sin embargo lo normal será que haya que migrar datos de la //tabla antigua a la nueva, por lo que este método debería //ser más elaborado. //Se elimina la versión anterior de la tabla db.execSQL("DROP TABLE IF EXISTS Usuarios"); //Se crea la nueva versión de la tabla db.execSQL(sqlCreate); } }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

38

Lo primero que hacemos es definir una variable llamado sqlCreate donde almacenamos la

sentencia SQL para crear una tabla llamada Usuarios con los campos alfanuméricos nombre e email. NOTA: No es objetivo de este tutorial describir la sintaxis del lenguaje SQL ni las

particularidades del motor de base de datos SQLite, por lo que no entraré a describir las sentencias SQL utilizadas. Para más información sobre SQLite puedes consultar la

documentación oficial o empezar por leer una pequeña introducción que hice en este mismo

blog cuando traté el tema de utilizar SQLite desde aplicaciones .NET

El método onCreate() será ejecutado automáticamente por nuestra clase UsuariosDBHelper cuando sea necesaria la creación de la base de datos, es decir, cuando aún no exista. Las

tareas típicas que deben hacerse en este método serán la creación de todas las tablas necesarias y la inserción de los datos iniciales si son necesarios. En nuestro caso, sólo vamos a crear la tabla Usuarios descrita anteriormente. Para la creación de la tabla utilizaremos la

sentencia SQL ya definida y la ejecutaremos contra la base de datos utilizando el método más sencillo de los disponibles en la API de SQLite proporcionada por Android, llamado

execSQL(). Este método se limita a ejecutar directamente el código SQL que le pasemos

como parámetro.

Por su parte, el método onUpgrade() se lanzará automáticamente cuando sea necesaria una actualización de la estructura de la base de datos o una conversión de los datos.

Un ejemplo práctico: imaginemos que publicamos una aplicación que utiliza una tabla con los campos usuario e email (llamémoslo versión 1 de la base de datos). Más adelante,

ampliamos la funcionalidad de nuestra aplicación y necesitamos que la tabla también incluya un campo adicional por ejemplo con la edad del usuario (versión 2 de nuestra base

de datos). Pues bien, para que todo funcione correctamente, la primera vez que ejecutemos

la versión ampliada de la aplicación necesitaremos modificar la estructura de la tabla Usuarios para añadir el nuevo campo edad. Pues este tipo de cosas son las que se encargará de hacer automáticamente el método onUpgrade() cuando intentemos abrir una versión concreta de la base de datos que aún no exista. Para ello, como parámetros recibe la versión

actual de la base de datos en el sistema, y la nueva versión a la que se quiere convertir. En función de esta pareja de datos necesitaremos realizar unas acciones u otras. En nuestro caso

de ejemplo optamos por la opción más sencilla: borrar la tabla actual y volver a crearla con la

nueva estructura, pero como se indica en los comentarios del código, lo habitual será que necesitemos algo más de lógica para convertir la base de datos de una versión a otra y por

supuesto para conservar los datos registrados hasta el momento.

Una vez definida nuestra clase helper, la apertura de la base de datos desde nuestra

aplicación resulta ser algo de lo más sencillo. Lo primero será crear un objeto de la clase

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

39

UsuariosSQLiteHelper al que pasaremos el contexto de la aplicación (en el ejemplo una referencia a la actividad principal), el nombre de la base de datos, un objeto CursorFactory que típicamente no será necesario (en ese caso pasaremos el valor null), y por último la

versión de la base de datos que necesitamos. La simple creación de este objeto puede tener

varios efectos:

Si la base de datos ya existe y su versión actual coincide con la solicitada simplemente se

realizará la conexión con ella.

Si la base de datos existe pero su versión actual es anterior a la solicitada, se llamará automáticamente al método onUpgrade() para convertir la base de datos a la nueva versión

y se conectará con la base de datos convertida.

Si la base de datos no existe, se llamará automáticamente al método onCreate() para crearla

y se conectará con la base de datos creada.

Si la base de datos ya existe y su versión actual coincide con la solicitada simplemente se realizará la conexión con ella. Si la base de datos existe pero su versión actual es anterior a la

solicitada, se llamará automáticamente al método onUpgrade() para convertir la base de

datos a la nueva versión y se conectará con la base de datos convertida.

Si la base de datos no existe, se llamará automáticamente al método onCreate() para crearla y se conectará con la base de datos creada.

package net.sgoliver.android; import android.app.Activity; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; public class AndroidBaseDatos extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //Abrimos la base de datos 'DBUsuarios' en modo escritura UsuariosSQLiteHelper usdbh = new UsuariosSQLiteHelper(this, "DBUsuarios", null, 1); SQLiteDatabase db = usdbh.getWritableDatabase(); //Si hemos abierto correctamente la base de datos if(db != null) {

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

40

//Insertamos 5 usuarios de ejemplo for(int i=1; i<=5; i++) { //Generamos los datos int codigo = i; String nombre = "Usuario" + i; //Insertamos los datos en la tabla Usuarios db.execSQL("INSERT INTO Usuarios (codigo, nombre) " + "VALUES (" + codigo + ", '" + nombre +"')"); } //Cerramos la base de datos db.close(); } } }

Vale, ¿y ahora qué? ¿dónde está la base de datos que acabamos de crear? ¿cómo podemos

comprobar que todo ha ido bien y que los registros se han insertado correctamente?

Vayamos por partes.

En primer lugar veamos dónde se ha creado nuestra base de datos. Todas las bases de datos

SQLite creadas por aplicaciones Android se almacenan en la memoria del teléfono en un

fichero con el mismo nombre de la base de datos situado en una ruta que sigue el siguiente patrón:

/data/data/paquete.java.de.la.aplicacion/databases/nombre_base_datos En el caso de nuestro ejemplo, la base de datos se almacenaría por tanto en la ruta siguiente:

/data/data/net.sgoliver.android/databases/DBUsuarios Para comprobar esto podemos hacer lo siguiente. Una vez ejecutada por primera vez desde Eclipse la aplicación de ejemplo sobre el emulador de Android (y por supuesto antes de

cerrarlo) podemos ir a la perspectiva “DDMS” (Dalvik Debug Monitor Server) de Eclipse y en la solapa “File Explorer” podremos acceder al sistema de archivos del emulador, donde podremos buscar la ruta indicada de la base de datos. Podemos ver esto en la siguiente

imagen:

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

41

Con esto ya comprobamos al menos que el fichero de nuestra base de datos se ha creado en la ruta correcta. Ya sólo nos queda comprobar que tanto las tablas creadas como los datos

insertados también se han incluido correctamente en la base de datos. Para ello podemos recurrir a dos posibles métodos:

1. Transferir la base de datos a nuestro PC y consultarla con cualquier administrador de bases de datos SQLite.

2. Acceder directamente a la consola de comandos del emulador de Android y utilizar los comandos existentes para acceder y consultar la base de datos SQLite.

El primero de los métodos es sencillo. El fichero de la base de datos podemos transferirlo a nuestro PC utilizando el botón de descarga situado en la esquina superior derecha del

explorador de archivos (remarcado en rojo en la imagen anterior). Junto a este botón aparecen otros dos para hacer la operación contraria (copiar un fichero local al sistema de archivos del emulador) y para eliminar ficheros del emulador. Una vez descargado el fichero

a nuestro sistema local, podemos utilizar cualquier administrador de SQLite para abrir y consultar la base de datos, por ejemplo SQLite Administrator (freeware).

El segundo método utiliza una estrategia diferente. En vez de descargar la base de datos a nuestro sistema local, somos nosotros los que accedemos de forma remota al emulador a

través de su consola de comandos (shell). Para ello, con el emulador de Android aún abierto debemos abrir una consola de MS-DOS y utilizar la utilidad adb.exe (Android Debug Bridge) situada en la carpeta platform-tools del SDK de Android (en mi caso: c:\android- sdk-windows\platform-tools\). En primer lugar consultaremos los identificadores de todos los

emuladores en ejecución mediante el comando “adb devices“. Esto nos debe devolver una única instancia si sólo tenemos un emulador abierto, que en mi caso particular se llama

“emulator-5554“.

Tras conocer el identificador de nuestro emulador, vamos a acceder a su shell mediante el

comando “adb -s identificador-del-emulador shell“. Una vez conectados, ya podemos

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

42

acceder a nuestra base de datos utilizando el comando sqlite3 pasándole la ruta del fichero, para nuestro ejemplo “sqlite3 /data/data/net.sgoliver.android/ databases/DBUsuarios“. Si todo ha ido bien, debe aparecernos el prompt de SQLite “sqlite>“, lo que nos indicará que ya

podemos escribir las consultas SQL necesarias sobre nuestra base de datos. Nosotros vamos a comprobar que existe la tabla Usuarios y que se han insertado los cinco registros de

ejemplo. Para ello haremos la siguiente consulta: “SELECT * FROM Usuarios;“. Si todo es correcto esta instrucción debe devolvernos los cinco usuarios existentes en la tabla. En la

imagen siguiente se muestra todo el proceso descrito:

Con esto ya hemos comprobado que nuestra base de datos se ha creado correctamente, que

se han insertado todos los registros de ejemplo y que todo funciona según se espera.

En los siguientes apartados comentaremos las distintas posibilidades que tenemos a la hora de manipular los datos de la base de datos (insertar, eliminar y modificar datos) y cómo podemos realizar consultas sobre los mismos, ya que [como siempre] tendremos varias

opciones disponibles.

Mantenimiento de base de datos en SQLite

La API de SQLite de Android proporciona dos alternativas para realizar operaciones sobre la base de datos que no devuelven resultados (entre ellas la

inserción/actualización/eliminación de registros, pero también la creación de tablas, de

índices, etc).

El primero de ellos, que ya comentamos brevemente en el apartado anterior, es el método

execSQL() de la clase SQLiteDatabase. Este método permite ejecutar cualquier sentencia SQL sobre la base de datos, siempre que ésta no devuelva resultados. Para ello, simplemente aportaremos como parámetro de entrada de este método la cadena de texto correspondiente con la sentencia SQL. Cuando creamos la base de datos en el post anterior ya vimos algún

ejemplo de esto para insertar los registros de prueba. Otros ejemplos podrían ser los siguientes:

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

43

//Insertar un registro db.execSQL("INSERT INTO Usuarios (usuario,email) VALUES ('usu1','[email protected]') "); //Eliminar un registro db.execSQL("DELETE FROM Usuarios WHERE usuario='usu1' "); //Actualizar un registro db.execSQL("UPDATE Usuarios SET email='[email protected]' WHERE usuario='usu1' "); La segunda de las alternativas disponibles en la API de Android es utilizar los métodos

insert(), update() y delete() proporcionados también con la clase SQLiteDatabase. Estos métodos permiten realizar las tareas de inserción, actualización y eliminación de registros de una forma algo más paramétrica que execSQL(), separando tablas, valores y condiciones

en parámetros independientes de estos métodos.

Empecemos por el método insert() para insertar nuevos registros en la base de datos. Este método recibe tres parámetros, el primero de ellos será el nombre de la tabla, el tercero

serán los valores del registro a insertar, y el segundo lo obviaremos por el momento ya que tan sólo se hace necesario en casos muy puntuales (por ejemplo para poder insertar registros completamente vacíos), en cualquier otro caso pasaremos con valor NULL este segundo

parámetro.

Los valores a insertar los pasaremos como elementos de una colección de tipo ContentValues. Esta colección es de tipo diccionario, donde almacenaremos parejas de clave-valor, donde la clave será el nombre de cada campo y el valor será el dato

correspondiente a insertar en dicho campo.

Veamos un ejemplo:

//Creamos el registro a insertar como objeto ContentValues ContentValues nuevoRegistro = new ContentValues(); nuevoRegistro.put("usuario", "usu10"); nuevoRegistro.put("email","[email protected]"); //Insertamos el registro en la base de datos db.insert("Usuarios", null, nuevoRegistro); Los métodos update() y delete() se utilizarán de forma muy parecida a ésta, con la salvedad

de que recibirán un parámetro adicional con la condición WHERE de la sentencia SQL. Por ejemplo, para actualizar el email del usuario de nombre ‘usu1‘ haríamos lo siguiente:

//Establecemos los campos-valores a actualizar ContentValues valores = new ContentValues(); valores.put("email","[email protected]");

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

44

//Actualizamos el registro en la base de datos db.update("Usuarios", valores, "usuario='usu1'"); Como podemos ver, como tercer parámetro del método update() pasamos directamente la

condición del UPDATE tal como lo haríamos en la cláusula WHERE en una sentencia SQL normal.

El método delete() se utilizaría de forma análoga. Por ejemplo para eliminar el registro del

usuario ‘usu2‘ haríamos lo siguiente:

//Eliminamos el registro del usuario 'usu2' db.delete("Usuarios", "usuario='usu2'"); Como vemos, volvemos a pasar como primer parámetro el nombre de la tabla y en segundo

lugar la condición WHERE. Por supuesto, si no necesitáramos ninguna condición,

podríamos dejar como null en este parámetro.

Un último detalle sobre estos métodos. Tanto en el caso de execSQL() como en los casos de update() o delete() podemos utilizar argumentos dentro de las condiciones de la sentencia

SQL. Esto no son más que partes variables de la sentencia SQL que aportaremos en un array de valores aparte, lo que nos evitará pasar por la situación típica en la que tenemos que construir una sentencia SQL concatenando cadenas de texto y variables para formar el comando SQL final. Estos argumentos SQL se indicarán con el símbolo ‘?’, y los valores de

dichos argumentos deben pasarse en el array en el mismo orden que aparecen en la sentencia SQL. Así, por ejemplo, podemos escribir instrucciones como la siguiente:

//Eliminar un registro con execSQL(), utilizando argumentos String[] args = new String[]{"usu1"}; db.execSQL("DELETE FROM Usuarios WHERE usuario=?", args); //Actualizar dos registros con update(), utilizando argumentos ContentValues valores = new ContentValues(); valores.put("email","[email protected]"); String[] args = new String[]{"usu1", "usu2"}; db.update("Usuarios", valores, "usuario=? OR usuario=?", args); Esta forma de pasar a la sentencia SQL determinados datos variables puede ayudarnos

además a escribir código más limpio y evitar posibles errores.

En el siguiente apartado veremos cómo consultar la base de datos para recuperar registros

según un determinado criterio.

Consultas y recuperación de registros en SQLite

De forma análoga a lo que vimos para las sentencias de modificación de datos, vamos a tener dos opciones principales para recuperar registros de una base de datos SQLite en Android.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

45

La primera de ellas utilizando directamente un comando de selección SQL, y como segunda opción utilizando un método específico donde parametrizaremos la consulta a la base de

datos.

Para la primera opción utilizaremos el método rawQuery() de la clase SQLiteDatabase. Este

método recibe directamente como parámetro un comando SQL completo, donde indicamos los campos a recuperar y los criterios de selección. El resultado de la consulta lo

obtendremos en forma de cursor, que posteriormente podremos recorrer para procesar los

registros recuperados. Sirva la siguiente consulta a modo de ejemplo:

Cursor c = db.rawQuery(" SELECT usuario,email FROM Usuarios WHERE usuario='usu1' "); Como en el caso de los métodos de modificación de datos, también podemos añadir a este

método una lista de argumentos variables que hayamos indicado en el comando SQL con el

símbolo ‘?‘, por ejemplo así:

String[] args = new String[] {"usu1"}; Cursor c = db.rawQuery(" SELECT usuario, email FROM Usuarios WHERE usuario=? ", args); Más adelante en este apartado veremos cómo podemos manipular el objeto Cursor para

recuperar los datos obtenidos.

Como segunda opción para recuperar datos podemos utilizar el método query() de la clase

SQLiteDatabase. Este método recibe varios parámetros: el nombre de la tabla, un array con los nombre de campos a recuperar, la cláusula WHERE, un array con los argumentos variables incluidos en el WHERE (si los hay, null en caso contrario), la cláusula GROUP BY

si existe, la cláusula HAVING si existe, y por último la cláusula ORDER BY si existe. Opcionalmente, se puede incluir un parámetro al final más indicando el número máximo de

registros que queremos que nos devuelva la consulta. Veamos el mismo ejemplo anterior

utilizando el método query():

String[] campos = new String[] {"usuario", "email"}; String[] args = new String[] {"usu1"}; Cursor c = db.query("Usuarios", campos, "usuario=?", args, null, null, null); Como vemos, los resultados se devuelven nuevamente en un objeto Cursor que deberemos

recorrer para procesar los datos obtenidos.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

46

Para recorrer y manipular el cursor devuelto por cualquiera de los dos métodos mencionados tenemos a nuestra disposición varios métodos de la clase Cursor, entre los que

destacamos dos de los dedicados a recorrer el cursor de forma secuencial y en orden natural:

• moveToFirst(): mueve el puntero del cursor al primer registro devuelto.

• moveToNext(): mueve el puntero del cursor al siguiente registro devuelto.

Los métodos moveToFirst() y moveToNext() devuelven TRUE en caso de haber realizado el

movimiento correspondiente del puntero sin errores, es decir, siempre que exista un primer registro o un registro siguiente, respectivamente.

Una vez posicionados en cada registro podremos utilizar cualquiera de los métodos

getXXX(índice_columna) existentes para cada tipo de dato para recuperar el dato de cada

campo del registro actual del cursor. Así, si queremos recuperar por ejemplo la segunda columna del registro actual, y ésta contiene un campo alfanumérico, haremos la llamada

getString(1) [NOTA: los índices comienzan por 0, por lo que la segunda columna tiene índice 1], en caso de contener un dato de tipo real llamaríamos a getDouble(1), y de forma análoga para todos los tipos de datos existentes. Con todo esto en cuenta, veamos cómo podríamos

recorrer el cursor devuelto por el ejemplo anterior:

String[] campos = new String[] {"usuario", "email"}; String[] args = new String[] {"usu1"}; Cursor c = db.query("Usuarios", campos, "usuario=?", args, null, null, null); //Nos aseguramos de que existe al menos un registro if (c.moveToFirst()) { //Recorremos el cursor hasta que no haya más registros do { String usuario = c.getString(0); String email = c.getString(1); } while(c.moveToNext()); } Además de los métodos comentados de la clase Cursor existen muchos más que nos pueden ser útiles en muchas ocasiones. Por ejemplo, getCount() te dirá el número total de registros

devueltos en el cursor, getColumnName(i) devuelve el nombre de la columna con índice i, moveToPosition(i) mueve el puntero del cursor al registro con índice i, etc. Podéis consultar

la lista completa de métodos disponibles en la clase Cursor en la documentación oficial de

Android.

Código QR

Un código QR (quick response code o código de respuesta rápida) es un módulo útil para almacenar información en una matriz de puntos o un código de barras bidimensional creado

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

47

por la compañía japonesa Denso Wave, subsidiaria de Toyota, en 1994. Se caracteriza por los tres cuadrados que se encuentran en las esquinas y que permiten detectar la posición del código al lector. La sigla «QR» se deriva de la frase inglesa Quick Response (Respuesta

Rápida en español), pues los creadores (Joaco Retes,Euge Damm y E.Pared) aspiran a que el código permita que su contenido se lea a alta velocidad. Los códigos QR son muy comunes

en Japón y de hecho son el código bidimensional más popular en ese país9.

Un detalle importante sobre el código QR es que, a diferencia de otros formatos de códigos de barras bidimensionales como el BIDI, su código es abierto y sus derechos de patente

(propiedad de Denso Wave) no son ejercidos.

ZXing ("Zebra Crossing")

ZXing (pronunciado "zebra crossing"), es una biblioteca de procesamiento de imágenes de barras 1D-2D de software libre multi-formato, implementado en Java, con presencia en otros lenguajes. Se encuentra enfocado en el uso en cámaras de dispositivos móviles para escanear

y decodificar códigos de barras en el dispositivo, sin comunicación con algún servidor. Sin embargo, el proyecto puede ser utilizado para codificar y decodificar graficas de barras tanto

en computadoras de escritorio y servidores. Este soporta los siguientes formatos10:

• UPC-A and UPC-E

• EAN-8 and EAN-13

• Code 39

• Code 93

• Code 128

• ITF

• Codabar

• RSS-14 (Todas las variantes)

• RSS Expanded (muchas variantes)

• QR Code

• Data Matrix

• Aztec (calidad "beta")

• PDF 417 (calidad "alfa")

Esta biblioteca está dividida en muchos componentes que están soportadas activamente:

• core: LA biblioteca de decodificación de imagen y codigo de prueba.

• javase: Código de cliente especifico J2SE.

• zxingorg: La fuente detrás de zxing.org/w.

• zxing.appspot.com: LA fuente detrás del generador de código de barras en base web.

• android: Cliente Android, llamado Barcode Scanner.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

48

• androidtest: Aplicación de pruebas de Android.

• android-integration: Soporta la integración con Barcode Scanner vía Intent.

Uso de Zxing en una aplicación Android

Como ejemplo de utilización de la tecnología de lectura de códigos QR, realizaremos una

pequeña aplicación que nos muestre la información que recupera la lectura de estos códigos. En esta aplicación, pondremos un botón de inicio de escaneo, para que se despliegue el uso de la cámara de escaneo, y cuando reconozca un código QR, la aplicación mostrará el

mensaje que se encuentra en dicho QR11.

Para ello requerimos realizar los siguientes pasos:

1. En el dispositivo en donde se van a hacer las pruebas, requerimos instalar la aplicación "Barcode Scanner", que se encuentra en la tienda de aplicaciones de

Android.

2. Requerimos de un archivo JAR pre-construido, que se encuentra en los recursos compilados del repositorio de liberación Maven, donde se encuentran los archivos

compilados más recientes12. (http://repo1.maven.org/maven2/com/google/zxing/core/2.2/core-2.2.jar)

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

49

3. En nuestro entorno de desarrollo Android ADT, creamos un nuevo proyecto de

aplicación Android.

4. Escribimos el nombre de la aplicación, nombre del proyecto y nombre del paquete que contendrá nuestros archivos de desarrollo; así como también seleccionar la versión del dispositivo a la cual va dirigida la aplicación. En este caso seleccionamos

como requerimiento mínimo la versión de API 7, correspondiente a la versión 2.1 de

Android (Eclair).

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

50

5. En la siguiente pantalla, seleccionamos estas opciones y presionamos siguiente.

6. Seleccionamos una imagen que represente el icono de la aplicación. En nuestro caso

encontramos esta imagen que representa de algún modo el objetivo de la aplicación.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

51

7. En la siguiente pantalla, seleccionamos una actividad en blanco, ya que es la más

sencilla de manipular.

8. En la última pantalla, escribimos el nombre del Actvity y el nombre del Layout de

este modo:

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

52

9. Una vez creado el proyecto, seleccionamos con el botón secundario la carpeta del

proyecto y seleccionamos la opción Build Path/Configure Build Path…

10. En "Java Build Path", en la etiqueta "Libraries", presionamos la opción "Add Externals JARs…".

11. Buscamos y seleccionamos el archivo core-2.2.jar que descargamos anteriormente.

Seleccionamos la opción OK.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

53

12. Ya que tenemos las bibliotecas necesarias, pasaremos a generar las interfaces que requerimos en la aplicación. Primero requerimos modificar el archivo "strings.xml",

que contendrá las cadenas necesarias para presentar en la aplicación, la cual tendrá

el siguiente código:

<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Decodificador QR</string> <string name="action_settings">Settings</string> <string name="btnScan">Iniciar Escaneo</string> <string name="frmMensaje">Mensaje:</string> </resources>

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

54

En este archivo, agregamos las cadenas "btnScan" y "frmMensaje", las cuales requeriremos para las interfaces de la aplicación.

13. Ahora abrimos el archivo main.xml, y escribimos el código correspondiente:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".Main" > <Button android:id="@+id/btnScan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="50dp" android:text="@string/btnScan" /> </RelativeLayout>

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

55

En la interfaz, agregamos un botón con identificador "btnScan", el cual se ubica en el

centro de la pantalla, a 50dp de la parte superior de toda la interfaz. 14. Como siguiente paso, creamos en la misma carpeta el archivo mensaje.xml, el cual

contendrá el siguiente código:

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

56

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="50dp" android:text="@string/frmMensaje" android:textAppearance="?android:attr/textAppearanceLarge" /> <TextView android:id="@+id/mensaje" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_below="@+id/textView1"

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

57

android:layout_marginTop="20dp" android:gravity="center" /> </RelativeLayout>

En esta interfaz, agregamos un título que muestra el contenido "Mensaje", además de

un cuadro de texto con identificador "mensaje", el cual recibirá el contenido de la lectura de un código QR.

15. Una vez realizado esto, tendremos que realizar los procedimientos necesarios para los objetos de nuestras pantallas. Para esto, primero procedemos a crear una nueva

clase llamada FrmMensaje.java:

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

58

16. Ahora modificamos el archivo Main.java, el cual contendrá el siguiente código:

package uam.pi2.decodificadorqr; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class Main extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

59

final Button scan = (Button)findViewById(R.id.btnScan); scan.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent("com.google.zxing.client.android.SCAN"); intent.putExtra("SCAN_MODE", "QR_VALUE"); startActivityForResult(intent, 0); } }); } public void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == 0) { if (resultCode == RESULT_OK) { Intent frmmensaje = new Intent(this, FrmMensaje.class); Bundle bundle = new Bundle(); bundle.putString("MENSAJE", intent.getStringExtra("SCAN_RESULT")); frmmensaje.putExtras(bundle); startActivity(frmmensaje); } else if (resultCode == RESULT_CANCELED) { Toast toast = Toast.makeText(this, "Escaneo de código cancelado", Toast.LENGTH_SHORT); toast.setGravity(Gravity.TOP, 25, 400); toast.show(); } } } }

17. Como siguiente paso, modificaremos el archivo FrmMensaje.java, agregando el

siguiente código:

package uam.pi2.decodificadorqr; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class FrmMensaje extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

60

setContentView(R.layout.mensaje); TextView txtMensaje = (TextView)findViewById(R.id.mensaje); Bundle bundle = getIntent().getExtras(); txtMensaje.setText(bundle.getString("MENSAJE")); } }

18. Por último paso, abrimos el archivo AndroidManifest.xml, y agregamos el siguiente código para otorgarle a la aplicación los permisos necesarios para abrir las interfaces

y ejecutar los procesos requeridos por la misma.

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="uam.pi2.decodificadorqr" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.CAMERA" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

61

android:name="uam.pi2.decodificadorqr.Main" 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="uam.pi2.decodificadorqr.FrmMensaje"> </activity> </application> </manifest> Habiendo realizado todos estos pasos, solo se requiere realizar las pruebas pertinentes en el

dispositivo.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

62

Desarrollo

Planeación

En este proyecto se planteó llevar a cabo la realización de una aplicación móvil, el cual permitirá al usuario obtener información sensible a la ubicación tanto por medio de la

lectura de códigos especiales QR, como por la navegación dentro de la misma aplicación en

las diferentes interfaces. Esta aplicación debería cumplir con las siguientes características:

• Ser intuitiva: Tanto la navegación como la obtención de la información debe ser clara.

• Ligera: La instalación y ejecución de la aplicación no repercute en la comodidad de manipulación por parte del usuario.

• Centralizada: Muestra la información requerida al momento.

• Actualizable: La información podría ser manipulada para mantenerse al día con respecto a la realidad, dando cabida la posibilidad de tener distintas versiones de la

aplicación, mejorándose.

La información sería almacenada en una base de datos, la cual puede ser manipulada en el exterior, para otorgar al usuario la posibilidad de actualizar la información de la aplicación

por medio de una conexión a un servidor.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

63

Diseño

En un primer acercamiento con los miembros del equipo, así como de los asesores, se realizó una investigación sobre las tecnologías requeridas para el desarrollo del proyecto, así como

el alcance que se piensa obtener en la primera versión de la aplicación.

Se acordó realizar la aplicación con el objetivo de ejecutarse sobre una tableta, por la

comodidad de poder mostrar la suficiente información necesaria en un espacio suficiente. La conexión de la aplicación con la base de datos no se llevó a cabo debido al tiempo de desarrollo, pero se tomo la decisión de realizar la base de datos de la aplicación con una

herramienta externa (SQLite) y después agregarla a la aplicación para su posterior consulta.

El sistema operativo elegido por el equipo fue Android, ya que cuenta con una gran

biblioteca de desarrollo que nos sirvió en el desarrollo, además de la compatibilidad de poder instalar el entorno de desarrollo en las computadoras en las que se realizó la

programación de la aplicación.

Ya que se eligió el SO Android, implicó que la base de datos por programar tendría que ser

desarrollado en SQLite3, ya que dicho manejador de base de datos se encuentra añadido por defecto dentro de cualquier dispositivo Android, por tener la característica de ser muy ligera

y no requerir demasiadas peticiones de ejecución del procesador, ahorrando la batería del

dispositivo.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

64

Como el entorno de desarrollo en Android se basa en parte por el lenguaje Java, requerimos

de instalar la biblioteca de desarrollo JAVA JDK.

Para la tecnología de lectura de códigos QR, el equipo investigó una biblioteca de software libre llamado ZXing (pronunciado "Zebra Crossing"), que es una biblioteca de

procesamiento de imágenes de barras 1D-2D de software libre multiformato, implementado en Java, con presencia en otros lenguajes. Se encuentra enfocado en el uso en cámaras de

dispositivos móviles para escanear y decodificar códigos de barras en el dispositivo, sin comunicación con algún servidor, dándole portabilidad a la aplicación de la cual requiera esta tecnología. Cabe mencionar que el proyecto puede ser utilizado para codificar y

decodificar gráficas de barras en computadoras de escritorio y en servidores.

Una vez entendido el desarrollo de aplicaciones en Android con las tecnologías pertinentes, el equipo de desarrollo se dio a la tarea de analizar la información que podría ser interesante mostrar con la aplicación. Se pensó en mostrar información relevante del área de

investigación de los asesores (Área de Redes y Telecomunicaciones). Para esto se analizaron las siguientes propuestas de información que nos fueron útiles:

1. Ubicación de la oficina de un profesor. 2. Salón asignado para un grupo de determinada Unidad de Enseñanza-Aprendizaje

(UEA). 3. Información de determinado piso de un edificio.

4. Encargado de un laboratorio.

5. Grupos abiertos de determinada UEA. 6. Horario de clases de un estudiante.

7. Salas que se encuentran en un edificio. 8. Profesores que se encuentran en un cubículo. 9. UEAs que se imparten en un salón.

10. Oficinas de determinada área de concentración.

El equipo estableció los datos que podrían ser de utilidad en la base de datos, generando el modelo de entidad - relación de la misma. Después se generó el código necesario para la

creación de la base de datos y los registros de ejemplo, que fueron tomados haciendo una investigación de campo en las instalaciones de la universidad, tomando la información real

que era relevante para el proyecto. Esta información se tomo en la mayoría en el Área de

Redes y Telecomunicaciones de la universidad, en la que se obtuvieron datos sobre:

• Profesores

• Aulas

• Laboratorios

• Oficinas

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

65

• Unidades de Enseñanza-Aprendizaje en las que el equipo de desarrollo se

encontraban cursando, para agregarlos a los horarios de la aplicación.

Como siguiente tarea, se revisó el tema con respecto a la información que contendrían los

códigos QR que se piensan usar para la consulta de la información en la aplicación a desarrollar, generando unos diagramas en donde los participantes pensaron la forma en la

que se podría solucionar dicha problemática13.

Una vez establecido el contenido de los códigos QR, accedimos a una herramienta de desarrollo de códigos QR gratuito en línea, en donde se generaron algunos ejemplos que se

pudieran requerir.

Después de generar los códigos, se empezó a desarrollar un diseño del esqueleto de la

aplicación. Se abordaron temas como el diagrama de navegación y pantallas.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

66

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

67

Implementación

Ya teniendo todo el diseño en cuenta, el equipo se dispuso a desarrollar la aplicación,

llevando el desarrollo en el siguiente orden:

Prerrequisitos (archivos necesarios)

Se tomaron fotografías en la unidad, que nos servirían en la apariencia de la aplicación, dando un ambiente más amigable al usuario. También se descargó la biblioteca de lectura de códigos QR ZXing, de la página oficial. Además, se desarrolló la base de datos con respecto a los requerimientos y al diseño antes establecidos con el entorno de desarrollo por línea de

comandos SQLite, así como algunas consultas en código SQL, para la utilización en la aplicación, generando el archivo uamdb.db, que se ingresaría más adelante a los archivos

requeridos dentro de la aplicación.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

68

uamdb.db

/* Creacion de las tablas */

CREATE TABLE edificio ( _id INTEGER PRIMARY KEY AUTOINCREMENT, letra TEXT NOT NULL, descripcion TEXT ); CREATE TABLE piso ( _id INTEGER PRIMARY KEY AUTOINCREMENT, numPiso INTEGER NOT NULL, descripcion TEXT, idEdificio INTEGER, FOREIGN KEY (idEdificio) REFERENCES edificio (_id) ); CREATE TABLE tipoSala ( _id INTEGER PRIMARY KEY AUTOINCREMENT, tipo TEXT NOT NULL ); CREATE TABLE sala ( _id INTEGER PRIMARY KEY, numSala INTEGER NOT NULL, descripcion TEXT, idPiso INTEGER, idTipoSala INTEGER, FOREIGN KEY (idPiso) REFERENCES piso (_id), FOREIGN KEY (idTipoSala) REFERENCES tipoSala (_id) ); CREATE TABLE profesor ( _id INTEGER PRIMARY KEY AUTOINCREMENT, nombre TEXT NOT NULL, apellidos TEXT NOT NULL, email TEXT NOT NULL, descripcion TEXT ); CREATE TABLE salaProfesor ( _id INTEGER PRIMARY KEY AUTOINCREMENT, idProfesor INTEGER, idSala INTEGER,

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

69

relacion TEXT NOT NULL, FOREIGN KEY (idProfesor) REFERENCES profesor (_id), FOREIGN KEY (idSala) REFERENCES sala (_id) ); CREATE TABLE uea ( _id INTEGER PRIMARY KEY, nombre TEXT NOT NULL ); CREATE TABLE grupo ( _id INTEGER PRIMARY KEY AUTOINCREMENT, grupo TEXT NOT NULL, idUEA INTEGER, idProfesor INTEGER, FOREIGN KEY (idUEA) REFERENCES uea (_id), FOREIGN KEY (idProfesor) REFERENCES profesor (_id) ); CREATE TABLE horario ( _id INTEGER PRIMARY KEY AUTOINCREMENT, idSala INTEGER, idGrupo INTEGER, inicio CURRENT_TIME NOT NULL, --HH:MM:SS fin CURRENT_TIME NOT NULL, dia TEXT NOT NULL, FOREIGN KEY (idSala) REFERENCES sala (_id), FOREIGN KEY (idGrupo) REFERENCES grupo (_id) ); CREATE TABLE estudiante ( _id INTEGER PRIMARY KEY AUTOINCREMENT, idGrupo INTEGER NOT NULL, FOREIGN KEY (idGrupo) REFERENCES grupo (_id) ); /* Inserción de los registros de ejemplo */

INSERT INTO edificio (letra, descripcion) VALUES ('B','Aulas, Fuego Nuevo, Coordinacion de Sistemas Escolares'), ('C','Aulas, Auditorios, Salas de audiovisuales'), ('D','Aulas, Oficinas del CELEX, Proteccion Civil'), ('E','Aulas, Auitorios'), ('H','Division de Ciencias Sociales y Humanidades'), ('T','Division de Ciencias Basicas e Ingenieria'), ('AT','Division de Ciencias Basicas e Ingenieria') ;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

70

INSERT INTO uea (_id, nombre) VALUES (2131096, 'Introduccion a la Programacion en Administracion'), (2131098, 'Proyecto de Investigacion II'), (2151014, 'Redes de Telecomunicaciones'), (2211075, 'Administracion General') ; INSERT INTO profesor (nombre, apellidos, email, descripcion) VALUES ('Oscar', 'Avila Mejia', '[email protected]', 'Profesor del Departamento de Ingenieria Electrica'), ('Reyna Carolina', 'Medina Ramirez', '[email protected]', 'Jefe del Area de Redes y Telecomunicaciones'), ('Antonio', 'Barba Alvarez', '[email protected]', 'Profesor del Departamento de Economia'), ('Jose Luis', 'Quiroz Fabian', '[email protected]', 'Profesor del Area de Computacion y Sistemas'), ('Miguel', 'Lopez Guerrero', '[email protected]', 'Coordinador de la carrera de Ingenieria Electronica'), ('Ricardo', 'Marcelin Jimenez', '[email protected]', 'Profesor del Departamento de ingenieria Electrica') ; INSERT INTO tipoSala (tipo) VALUES ('Cubiculo'), ('Aula'), ('Oficina'), ('Laboratorio'), ('Sala de conferencias'), ('Auditorio') ; INSERT INTO piso (idEdificio, numPiso, descripcion) VALUES ((SELECT e._id FROM edificio e WHERE e.letra = 'T'), 3, 'Area de Redes y Telecomunicaciones, Cubiculos de profesores'), ((SELECT e._id FROM edificio e WHERE e.letra = 'B'), 0, 'Coordinacion de Sistemas Escolares, Teatro del Fuego Nuevo'), ((SELECT e._id FROM edificio e WHERE e.letra = 'B'), 1, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'B'), 2, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'B'), 3, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'C'), 0, 'Auditorios OMECOATECALLI y CECOATECALLI, Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'C'), 1, 'Aulas'),

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

71

((SELECT e._id FROM edificio e WHERE e.letra = 'C'), 2, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'D'), 0, 'Prestamo de equipo, Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'D'), 1, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'D'), 2, 'Aulas, CELEX'), ((SELECT e._id FROM edificio e WHERE e.letra = 'E'), 0, 'Aulas, Auditorios'), ((SELECT e._id FROM edificio e WHERE e.letra = 'E'), 1, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'E'), 2, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'E'), 3, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'T'), 0, 'Laboratorios'), ((SELECT e._id FROM edificio e WHERE e.letra = 'T'), 1, 'Area de Computacion, Laboratorios, Cubiculos de profesores'), ((SELECT e._id FROM edificio e WHERE e.letra = 'T'), 2, 'Laboratorios, Cubiculos de profesores'), ((SELECT e._id FROM edificio e WHERE e.letra = 'AT'), 0, 'Salas de Conferencia, Laboratorios'), ((SELECT e._id FROM edificio e WHERE e.letra = 'AT'), 1, 'Laboratorios'), ((SELECT e._id FROM edificio e WHERE e.letra = 'AT'), 2, 'Cubiculos de profesores, Laboratorios'), ((SELECT e._id FROM edificio e WHERE e.letra = 'AT'), 3, 'Cubiculos de profesores'), ((SELECT e._id FROM edificio e WHERE e.letra = 'H'), 0, 'Cubiculos de profesores') ; INSERT INTO grupo (grupo, idUEA, idProfesor) VALUES ('CL08', 2131098, (SELECT p._id FROM profesor p WHERE p.apellidos = 'Medina Ramirez' )), ('CK51', 2151014, (SELECT p._id FROM profesor p WHERE p.apellidos = 'Avila Mejia' )), ('HA03', 2211075, (SELECT p._id FROM profesor p WHERE p.apellidos = 'Barba Alvarez' )), ('CE01', 2131096, (SELECT p._id FROM profesor p WHERE p.apellidos = 'Quiroz Fabian' )) ; INSERT INTO sala (numSala, descripcion, idPiso, idTipoSala) VALUES (9, 'Cubiculo del Area de Redes y Telecomunicaciones',

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

72

(SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'T' AND p.numPiso = 3), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Cubiculo')), (15, 'Salon de clases', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'C' AND p.numPiso = 2), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Aula')), (5, 'Salon de clases', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'D' AND p.numPiso = 1), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Aula')), (7, 'Salon de clases', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'D' AND p.numPiso = 1), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Aula')), (5, 'Salon de clases', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'E' AND p.numPiso = 2), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Aula')), (15, 'Salon de clases', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'E' AND p.numPiso = 2), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Aula')), (47, 'Cubiculo del Area de Computacion y Sistemas', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'T' AND p.numPiso = 1), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Cubiculo')), (69, 'Cubiculo del Area de Computacion en Paralelo', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'T' AND p.numPiso = 1), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Cubiculo')), (24, 'Laboratorio de Ingenieria de Software (LIS)', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'T' AND p.numPiso = 3), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Laboratorio')), (5, 'Laboratorio de Computo (CEUAMI)', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

73

WHERE e.letra = 'AT' AND p.numPiso = 1), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Laboratorio')), (9, 'Laboratorio de Electronica', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'AT' AND p.numPiso = 1), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Laboratorio')), (20, 'Laboratorio de Computo', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'AT' AND p.numPiso = 2), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Laboratorio')), (35, 'Cubiculo Area de Economia', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'H' AND p.numPiso = 0), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Cubiculo')), (26, 'Laboratorio de Analisis de Rendimiento y Teleservicios (ARTe)', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'T' AND p.numPiso = 3), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Laboratorio')), (3, 'Cubiculo de Departamento de Ingenieria Electrica', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idEdificio WHERE e.letra = 'T' AND p.numPiso = 3), (SELECT t._id FROM tipoSala t WHERE t.tipo = 'Cubiculo')) ; INSERT INTO salaProfesor (idProfesor, idSala, relacion) VALUES ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Medina Ramirez'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'T' AND p.numPiso = 3 AND s.numSala = 9), 'Cubiculo'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Lopez Guerrero'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'T' AND p.numPiso = 3 AND s.numSala = 9), 'Cubiculo'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Quiroz Fabian'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'T' AND p.numPiso = 1 AND s.numSala = 69), 'Cubiculo'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Quiroz Fabian'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

74

ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'T' AND p.numPiso = 1 AND s.numSala = 69), 'Encargado'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Barba Alvarez'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'H' AND p.numPiso = 0 AND s.numSala = 35), 'Cubiculo'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Avila Mejia'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'E' AND p.numPiso = 2 AND s.numSala = 15), 'Cubiculo'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Marcelin Jimenez'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'T' AND p.numPiso = 3 AND s.numSala = 26), 'Encargado'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Marcelin Jimenez'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'T' AND p.numPiso = 3 AND s.numSala = 3), 'Cubiculo') ; INSERT INTO horario (idSala, idGrupo, inicio, fin, dia) VALUES ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'C' AND p.numPiso = 2 AND s.numSala = 15), (SELECT g._id FROM grupo g WHERE g.idUEA = 2151014 AND g.grupo = 'CK51'), '18:00:00', '19:30:00', 'miercoles'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'C' AND p.numPiso = 2 AND s.numSala = 15), (SELECT g._id FROM grupo g WHERE g.idUEA = 2151014 AND g.grupo = 'CK51'), '18:00:00', '19:30:00', 'lunes'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'AT' AND p.numPiso = 1 AND s.numSala = 9), (SELECT g._id FROM grupo g WHERE g.idUEA = 2151014 AND g.grupo = 'CK51'), '18:00:00', '21:00:00', 'jueves'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

75

ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'D' AND p.numPiso = 1 AND s.numSala = 5), (SELECT g._id FROM grupo g WHERE g.idUEA = 2211075 AND g.grupo = 'HA03'), '12:00:00', '14:00:00', 'lunes'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'D' AND p.numPiso = 1 AND s.numSala = 5), (SELECT g._id FROM grupo g WHERE g.idUEA = 2211075 AND g.grupo = 'HA03'), '12:00:00', '14:00:00', 'miercoles'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'D' AND p.numPiso = 1 AND s.numSala = 5), (SELECT g._id FROM grupo g WHERE g.idUEA = 2211075 AND g.grupo = 'HA03'), '12:00:00', '14:00:00', 'viernes'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'C' AND p.numPiso = 2 AND s.numSala = 15), (SELECT g._id FROM grupo g WHERE g.idUEA = 2131096 AND g.grupo = 'CE01'), '12:30:00', '15:00:00', 'lunes'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'D' AND p.numPiso = 1 AND s.numSala = 7), (SELECT g._id FROM grupo g WHERE g.idUEA = 2131096 AND g.grupo = 'CE01'), '12:30:00', '14:30:00', 'miercoles'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idEdificio AND p._id = s.idPiso WHERE e.letra = 'AT' AND p.numPiso = 1 AND s.numSala = 5), (SELECT g._id FROM grupo g WHERE g.idUEA = 2131096 AND g.grupo = 'CE01'), '12:00:00', '14:00:00', 'viernes') ; INSERT INTO estudiante (idGrupo) VALUES ((SELECT g._id FROM uea u INNER JOIN grupo g ON u._id = g.idUEA WHERE u._id = 2151014 AND g.grupo = 'CK51')), ((SELECT g._id FROM uea u INNER JOIN grupo g ON u._id = g.idUEA WHERE u._id = 2131098 AND g.grupo = 'CL08')), ((SELECT g._id FROM uea u INNER JOIN grupo g ON u._id = g.idUEA WHERE u._id = 2211075 AND g.grupo = 'HA03')) ;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

76

Generación de la aplicación

En el entorno de desarrollo Android ADT, se creó un nuevo proyecto de aplicación Android,

llamado UAM QR App, que contendría los archivos fuente de la aplicación a desarrollar.

Inserción de las imágenes

Se agregaron a las carpetas "res/drawlable-*/" las imágenes que nos servirían para dar una

mejor apariencia a la aplicación. Los nombres de los archivos deben de respetar una nomenclatura que contengan caracteres [a-z0-9_.].

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

77

Decodificador QR

También se agregó la biblioteca de lectura de códigos QR, descargando el archivo core.jar, y

agregándolo a la lista de bibliotecas disponible en la aplicación. Para hacer esto, seleccionamos con el botón secundario la carpeta del proyecto y seleccionamos la opción "Build Path/Configure Build Path…". En "Java Build Path", en la etiqueta "Libraries",

presionamos la opción "Add Externals JARs…". Buscamos y seleccionamos el archivo descargado y pulsamos OK.

Inserción de la base de datos

Agregamos el archivo de la base de datos uamdb.db en la carpeta assets.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

78

Utilidades

Modificamos el archivo strings.xml, con el siguiente código:

<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">UAM QR App</string> <string name="action_settings">Settings</string> <string name="edificios">Edificios</string> <string name="pisos">Pisos</string> <string name="salas">Salas</string> <string name="ueas">UEAS</string> <string name="grupos">Grupos</string> <string name="uam">Universidad Autónoma Metropolitana</string> <string name="qr">Lectura de código QR</string> <string name="uea">Lista de UEAs</string> <string name="horario">Horario</string> <string name="profesor">Profesores</string> <string name="headIdUEA">Id</string> <string name="headUEA">UEA</string> <string name="headGrupo">Grupo</string> <string name="headLunes">LUN</string> <string name="headMartes">MAR</string> <string name="headMiercoles">MIE</string> <string name="headJueves">JUE</string> <string name="headViernes">VIE</string> <string name="labelEncargado">Encargado</string> <string name="headProfesor">Profesor</string> </resources>

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

79

Layouts (Interfaces de la aplicación)

En la carpeta "res/layout/" del proyecto, se generaron los archivos XML que contendrían el código fuente de las interfaces que se iban a presentar en la aplicación.

main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".Main" > <ImageButton android:id="@+id/ueaButton" android:layout_width="120dp" android:layout_height="120dp" android:layout_alignTop="@+id/qrButton" android:layout_toLeftOf="@+id/qrButton" android:contentDescription="@string/uea" android:src="@drawable/uea" /> <ImageButton android:id="@+id/scheduleButton" android:layout_width="120dp" android:layout_height="120dp" android:layout_alignTop="@+id/ueaButton" android:layout_toLeftOf="@+id/ueaButton" android:contentDescription="@string/horario" android:src="@drawable/schedule" /> <ImageButton android:id="@+id/buildingButton" android:layout_width="120dp" android:layout_height="120dp" android:layout_alignTop="@+id/qrButton" android:layout_toRightOf="@+id/qrButton" android:contentDescription="@string/edificios" android:src="@drawable/building" /> <ImageView android:id="@+id/fotoSalon" android:layout_width="match_parent"

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

80

android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="20dp" android:clickable="false" android:contentDescription="@string/uam" android:src="@drawable/logo" /> <ImageButton android:id="@+id/teacherButton" android:layout_width="120dp" android:layout_height="120dp" android:layout_alignTop="@+id/buildingButton" android:layout_toRightOf="@+id/buildingButton" android:contentDescription="@string/profesor" android:src="@drawable/teacher" /> <ImageButton android:id="@+id/qrButton" android:layout_width="120dp" android:layout_height="120dp" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="72dp" android:contentDescription="@string/qr" android:src="@drawable/qr_reader" /> </RelativeLayout>

qr.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/idUEA" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="50dp" android:textAppearance="?android:attr/textAppearanceLarge" /> <TextView

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

81

android:id="@+id/mensaje" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/idUEA" android:layout_centerHorizontal="true" android:layout_marginTop="48dp" /> </RelativeLayout>

schedule.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TableLayout android:id="@+id/tableLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:stretchColumns="*" > <TableRow> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> <TableRow android:id="@+id/encabezados" android:layout_width="match_parent" android:layout_height="wrap_content" >

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

82

<TextView android:id="@+id/headIdUEA" android:text="@string/headIdUEA" /> <TextView android:id="@+id/headUEA" android:text="@string/headUEA" android:layout_span="3" /> <TextView android:id="@+id/headGrupo" android:text="@string/headGrupo" /> <TextView android:id="@+id/headLunes" android:text="@string/headLunes" /> <TextView android:id="@+id/headMartes" android:text="@string/headMartes" /> <TextView android:id="@+id/headMiercoles" android:text="@string/headMiercoles" /> <TextView android:id="@+id/headJueves" android:text="@string/headJueves" /> <TextView android:id="@+id/headViernes" android:text="@string/headViernes" /> </TableRow> </TableLayout> <ListView android:id="@+id/listaHorarioLaboratorio" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/tableLayout1" android:layout_alignRight="@+id/tableLayout1" android:layout_below="@+id/tableLayout1" android:layout_marginTop="20dp" > </ListView>

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

83

</RelativeLayout>

building.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/listaEdificios" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/foto" android:layout_alignRight="@+id/foto" android:layout_below="@+id/foto" android:layout_marginTop="20dp" > </ListView> <ImageView android:id="@+id/foto" android:layout_width="match_parent" android:layout_height="300dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:src="@drawable/foto_edificio" android:contentDescription="@string/edificios" /> </RelativeLayout>

floor.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/numPisos" android:layout_width="match_parent" android:layout_height="wrap_content"

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

84

android:layout_alignLeft="@+id/letraEdificio" android:layout_alignRight="@+id/fotoSalon" android:layout_below="@+id/fotoSalon" android:layout_marginTop="20dp" > </ListView> <ImageView android:id="@+id/fotoSalon" android:layout_width="400dp" android:layout_height="300dp" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:contentDescription="@string/pisos" android:src="@drawable/foto_piso" /> <TextView android:id="@+id/letraEdificio" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignTop="@+id/fotoSalon" android:layout_marginLeft="20dp" android:textAppearance="?android:attr/textAppearanceLarge" android:textSize="150sp" /> <TextView android:id="@+id/descripcionEdificio" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/letraEdificio" android:layout_below="@+id/letraEdificio" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:layout_toLeftOf="@+id/fotoSalon" android:text="" /> </RelativeLayout>

room.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

85

android:layout_height="match_parent" > <ListView android:id="@+id/numSalas" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/edificioPiso" android:layout_alignRight="@+id/fotoSalon" android:layout_below="@+id/fotoSalon" android:layout_marginTop="20dp" > </ListView> <ImageView android:id="@+id/fotoSalon" android:layout_width="400dp" android:layout_height="300dp" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:contentDescription="@string/salas" android:src="@drawable/foto_salon" /> <TextView android:id="@+id/edificioPiso" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignTop="@+id/fotoSalon" android:layout_marginLeft="20dp" android:textAppearance="?android:attr/textAppearanceLarge" android:textSize="150sp" /> <TextView android:id="@+id/descripcionPiso" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/edificioPiso" android:layout_below="@+id/edificioPiso" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:layout_toLeftOf="@+id/fotoSalon" android:text="" /> </RelativeLayout>

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

86

sala.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/imageView1" android:layout_width="350dp" android:layout_height="270dp" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:src="@drawable/foto_salon" android:contentDescription="@string/salas" /> <TextView android:id="@+id/salon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignTop="@+id/imageView1" android:layout_marginLeft="20dp" android:text="" android:textAppearance="?android:attr/textAppearanceLarge" android:textSize="100sp" /> <TableLayout android:id="@+id/tableLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/salon" android:layout_alignRight="@+id/imageView1" android:layout_below="@+id/imageView1" android:layout_marginTop="20dp" android:stretchColumns="*" > <TableRow> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView />

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

87

<TextView /> <TextView /> <TextView /> </TableRow> <TableRow android:id="@+id/encabezados" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/headIdUEA" android:text="@string/headIdUEA" /> <TextView android:id="@+id/headUEA" android:text="@string/headUEA" android:layout_span="3" /> <TextView android:id="@+id/headGrupo" android:text="@string/headGrupo" /> <TextView android:id="@+id/headLunes" android:text="@string/headLunes" /> <TextView android:id="@+id/headMartes" android:text="@string/headMartes" /> <TextView android:id="@+id/headMiercoles" android:text="@string/headMiercoles" /> <TextView android:id="@+id/headJueves" android:text="@string/headJueves" /> <TextView android:id="@+id/headViernes" android:text="@string/headViernes" /> </TableRow> </TableLayout> <ListView

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

88

android:id="@+id/listaHorarioSalon" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/tableLayout1" android:layout_alignRight="@+id/tableLayout1" android:layout_below="@+id/tableLayout1" android:layout_marginTop="20dp" > </ListView> <TextView android:id="@+id/descripcionSalon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/salon" android:layout_below="@+id/salon" android:layout_marginTop="20dp" android:text="" android:textAppearance="?android:attr/textAppearanceMedium" /> </RelativeLayout>

cubículo.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/imageView1" android:layout_width="350dp" android:layout_height="270dp" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:src="@drawable/foto_salon" android:contentDescription="@string/salas" /> <TextView android:id="@+id/salon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignTop="@+id/imageView1"

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

89

android:layout_marginLeft="20dp" android:text="" android:textAppearance="?android:attr/textAppearanceLarge" android:textSize="100sp" /> <ListView android:id="@+id/listaProfesoresSalon" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignRight="@+id/imageView1" android:layout_below="@+id/imageView1" android:layout_marginTop="20dp" > </ListView> <TextView android:id="@+id/descripcionSalon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/salon" android:layout_below="@+id/salon" android:layout_marginTop="20dp" android:text="" android:textAppearance="?android:attr/textAppearanceMedium" /> </RelativeLayout>

laboratorio.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/imageView1" android:layout_width="350dp" android:layout_height="270dp" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:src="@drawable/foto_salon" android:contentDescription="@string/salas" /> <TextView android:id="@+id/salon" android:layout_width="wrap_content"

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

90

android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignTop="@+id/imageView1" android:layout_marginLeft="20dp" android:text="" android:textAppearance="?android:attr/textAppearanceLarge" android:textSize="100sp" /> <TextView android:id="@+id/descripcionSalon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/salon" android:layout_below="@+id/salon" android:layout_marginTop="20dp" android:text="" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/labelEncargados" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/descripcionSalon" android:layout_below="@+id/imageView1" android:layout_marginTop="20dp" android:text="@string/labelEncargado" android:textAppearance="?android:attr/textAppearanceLarge" /> <TextView android:id="@+id/nombreEncargado" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/labelEncargados" android:layout_alignBottom="@+id/labelEncargados" android:layout_marginLeft="20dp" android:layout_toRightOf="@+id/labelEncargados" android:text="" android:textAppearance="?android:attr/textAppearanceMedium" /> <TableLayout android:id="@+id/tableLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/salon" android:layout_alignRight="@+id/imageView1" android:layout_below="@+id/labelEncargados" android:layout_marginTop="20dp"

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

91

android:stretchColumns="*" > <TableRow> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> <TableRow android:id="@+id/encabezados" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/headIdUEA" android:text="@string/headIdUEA" /> <TextView android:id="@+id/headUEA" android:text="@string/headUEA" android:layout_span="3" /> <TextView android:id="@+id/headGrupo" android:text="@string/headGrupo" /> <TextView android:id="@+id/headLunes" android:text="@string/headLunes" /> <TextView android:id="@+id/headMartes" android:text="@string/headMartes" /> <TextView android:id="@+id/headMiercoles" android:text="@string/headMiercoles" /> <TextView

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

92

android:id="@+id/headJueves" android:text="@string/headJueves" /> <TextView android:id="@+id/headViernes" android:text="@string/headViernes" /> </TableRow> </TableLayout> <ListView android:id="@+id/listaHorarioLaboratorio" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/tableLayout1" android:layout_alignRight="@+id/tableLayout1" android:layout_below="@+id/tableLayout1" android:layout_marginTop="20dp" > </ListView> </RelativeLayout>

profesor.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/nombreProfesor" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" android:layout_marginTop="30dp" android:layout_toLeftOf="@+id/imageView1" android:textAppearance="?android:attr/textAppearanceLarge" /> <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true"

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

93

android:layout_alignTop="@+id/nombreProfesor" android:layout_marginRight="30dp" android:src="@drawable/foto_profe" android:contentDescription="@string/profesor" /> <TextView android:id="@+id/descripcionProfesor" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/nombreProfesor" android:layout_alignRight="@+id/nombreProfesor" android:layout_below="@+id/nombreProfesor" android:layout_marginTop="20dp" /> <TextView android:id="@+id/emailProfesor" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/descripcionProfesor" android:layout_alignRight="@+id/descripcionProfesor" android:layout_below="@+id/descripcionProfesor" android:layout_marginTop="20dp" /> <ListView android:id="@+id/cubiculoProfesor" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/emailProfesor" android:layout_alignRight="@+id/emailProfesor" android:layout_below="@+id/emailProfesor" android:layout_marginTop="20dp" > </ListView> </RelativeLayout>

teacher.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/listaProfesores" android:layout_width="match_parent"

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

94

android:layout_height="wrap_content" android:layout_alignLeft="@+id/foto" android:layout_alignRight="@+id/foto" android:layout_below="@+id/foto" android:layout_marginTop="20dp" > </ListView> <ImageView android:id="@+id/foto" android:layout_width="match_parent" android:layout_height="300dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:src="@drawable/foto_profe" android:contentDescription="@string/edificios" /> </RelativeLayout>

grupos.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/imageView1" android:layout_width="400dp" android:layout_height="300dp" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:contentDescription="@string/uea" android:src="@drawable/foto_profe" /> <TextView android:id="@+id/ueaGrupos" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignTop="@+id/imageView1"

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

95

android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_toLeftOf="@+id/imageView1" android:text="" android:textAppearance="?android:attr/textAppearanceLarge" /> <TableLayout android:id="@+id/tableLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/ueaGrupos" android:layout_alignRight="@+id/imageView1" android:layout_below="@+id/imageView1" android:layout_marginTop="20dp" android:stretchColumns="*" > <TableRow android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:text="@string/headGrupo" /> <TextView android:layout_span="3" android:text="@string/headProfesor" /> <TextView android:text="@string/headLunes" /> <TextView android:text="@string/headMartes" /> <TextView android:text="@string/headMiercoles" />

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

96

<TextView android:text="@string/headJueves" /> <TextView android:text="@string/headViernes" /> </TableRow> </TableLayout> <ListView android:id="@+id/listaGrupos" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/tableLayout1" android:layout_alignRight="@+id/tableLayout1" android:layout_below="@+id/tableLayout1" android:layout_marginTop="20dp" > </ListView> </RelativeLayout>

uea.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/listaUEAs" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/foto" android:layout_alignRight="@+id/foto" android:layout_below="@+id/foto" android:layout_marginTop="20dp" > </ListView> <ImageView android:id="@+id/foto" android:layout_width="match_parent" android:layout_height="300dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_marginTop="20dp"

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

97

android:src="@drawable/foto_uea" android:contentDescription="@string/ueas" /> </RelativeLayout>

Recursos para los layouts

Se generaron 2 interfaces especiales (custom_row_grupo.xml, custom_row_horario.xml), para poder presentar la información enlistada para cada grupo de la UEA, así como también

para cada elemento de la lista del horario del usuario.

custom_row_horario.xml

<?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:stretchColumns="*" > <TableRow> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> <TableRow android:id="@+id/tableRow1" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/idUEA" /> <TextView android:id="@+id/uea" android:layout_span="3" /> <TextView android:id="@+id/grupo" /> <TextView android:id="@+id/lunes" /> <TextView android:id="@+id/martes" /> <TextView android:id="@+id/miercoles" /> <TextView android:id="@+id/jueves" /> <TextView android:id="@+id/viernes" /> </TableRow>

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

98

</TableLayout>

custom_row_grupo.xml

<?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:stretchColumns="*"> <TableRow > <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/grupolista" /> <TextView android:id="@+id/profesorGrupo" android:layout_span="3" /> <TextView android:id="@+id/grupolunes" /> <TextView android:id="@+id/grupomartes" /> <TextView android:id="@+id/grupomiercoles" /> <TextView android:id="@+id/grupojueves" /> <TextView android:id="@+id/grupoviernes" /> </TableRow> </TableLayout>

Clases abstractas para los registros de la base de datos

Para una correcta manipulación de los datos de la base de datos, se generaron las clases respectivas. En ellas contienen atributos intrínsecos a los registros o consultas, así como los métodos necesarios para su creación, lectura y modificación de sus atributos. Con estas

herramientas construidas, se procedió a generar el archivo DBHelper.java, el cual contiene

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

99

todos los procedimientos necesarios para la creación y consulta de la base de datos generada

anteriormente.

Edificio.java

package uam.pi.uamqrapp; public class Edificio { private int id; private String letra; private String descripcion; Edificio() { this.id = 0; this.letra = new String(""); this.descripcion = new String(""); } public Edificio(int id, String letra, String descripcion) { this.id = id; this.letra = new String(letra); this.descripcion = new String(descripcion); } public int getId() { return this.id; } public String getLetra() { return this.letra; } public String getDescripcion() { return this.descripcion; } }

Piso.java

package uam.pi.uamqrapp; public class Piso { private int id; private int numPiso; private String descripcion;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

100

private int idEdificio; public Piso() { this.id = 0; this.numPiso = 0; this.descripcion = new String(""); this.idEdificio = 0; } public Piso(int id, int numPiso, String descripcion, int idEdificio) { this.id = id; this.numPiso = numPiso; this.descripcion = new String(descripcion); this.idEdificio = idEdificio; } public int getId() { return this.id; } public int getNumPiso() { return this.numPiso; } public String getDescripcion() { return this.descripcion; } public int getIdEdificio() { return this.idEdificio; } }

Sala.java

package uam.pi.uamqrapp; public class Sala { private int id; private int numSala; private String descripcion; private int idPiso; private int idTipo; public Sala() {

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

101

this.id = 0; this.numSala = 0; this.descripcion = new String(""); this.idPiso = 0; this.idTipo = 0; } public Sala(int id, int numSala, String descripcion, int idPiso, int idTipo) { this.id = id; this.numSala = numSala; this.descripcion = new String(descripcion); this.idPiso = idPiso; this.idTipo = idTipo; } public int getId() { return this.id; } public int getNumSala() { return this.numSala; } public String getDescripcion() { return this.descripcion; } public int getIdPiso() { return this.idPiso; } public int getIdTipo() { return this.idTipo; } }

TipoSala.java

package uam.pi.uamqrapp; public class TipoSala { private int id; private String tipo; public TipoSala() { this.id = 0;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

102

this.tipo = new String(""); } public TipoSala (int id, String tipo) { this.id = id; this.tipo = tipo; } public int getid() { return this.id; } public String gettipo() { return this.tipo; } }

Profesor.java

package uam.pi.uamqrapp; public class Profesor { private int id; private String nombre; private String apellidos; private String email; private String descripcion; public Profesor() { this.id = 0; this.nombre = new String(""); this.apellidos = new String(""); this.email = new String(""); this.descripcion = new String(""); } public Profesor(int id, String nombre, String apellidos, String email, String descripcion) { this.id = id; this.nombre = nombre; this.apellidos = apellidos; this.email = email; this.descripcion = descripcion; } public int getid() { return this.id;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

103

} public String getnombre() { return this.nombre; } public String getapellidos() { return this.apellidos; } public String getemail() { return this.email; } public String getdescripcion() { return this.descripcion; } }

SalaProfesor.java

package uam.pi.uamqrapp; public class SalaProfesor { private int id; private int idProfesor; private int idSala; private String relacion; public SalaProfesor() { this.id = 0; this.idProfesor = 0; this.idSala = 0; this.relacion = new String(""); } public SalaProfesor(int id, int idProfesor, int idSala, String relacion) { this.id = id; this.idProfesor = idProfesor; this.idSala = idSala; this.relacion = new String(relacion); } public int getId() {

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

104

return this.id; } public int getIdProfesor() { return this.idProfesor; } public int getIdSala() { return this.idSala; } public String getrelacion() { return this.relacion; } }

UEA.java

package uam.pi.uamqrapp; public class UEA { private int id; private String nombre; public UEA() { this.id = 0; this.nombre = new String(""); } public UEA (int id, String nombre) { this.id = id; this.nombre = nombre; } public int getid() { return this.id; } public String getnombre() { return this.nombre; } }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

105

Grupo.java

package uam.pi.uamqrapp; public class Grupo { private int id; private int idUEA; private int idProfesor; public Grupo() { this.id = 0; this.idUEA = 0; this.idProfesor = 0; } public Grupo(int id, int idUEA, int idProfesor) { this.id = id; this.idUEA = idUEA; this.idProfesor = idProfesor; } public int getId() { return this.id; } public int getIdUEA() { return this.idUEA; } public int getIdProfesor() { return this.idProfesor; } }

Horario.java

package uam.pi.uamqrapp; public class Horario { private int idUEA; private String grupo; private String uea; private String lunes; private String martes; private String miercoles; private String jueves;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

106

private String viernes; public Horario () { this.idUEA = 0; this.grupo = new String(""); this.uea = new String(""); this.lunes = new String(""); this.martes = new String(""); this.miercoles = new String(""); this.jueves = new String(""); this.viernes = new String(""); } public int getIdUEA () { return this.idUEA; } public String getGrupo () { return this.grupo; } public String getUEA () { return this.uea; } public String getLunes () { return this.lunes; } public String getMartes () { return this.martes; } public String getMiercoles () { return this.miercoles; } public String getJueves () { return this.jueves; } public String getViernes () { return this.viernes; } public void setidUEA (int idUEA) { this.idUEA = idUEA;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

107

} public void setgrupo (String grupo) { this.grupo = grupo; } public void setuea (String uea) { this.uea = uea; } public void setlunes (String lunes) { this.lunes = lunes; } public void setmartes (String martes) { this.martes = martes; } public void setmiercoles (String miercoles) { this.miercoles = miercoles; } public void setjueves (String jueves) { this.jueves = jueves; } public void setviernes (String viernes) { this.viernes = viernes; } }

Estudiante.java

package uam.pi.uamqrapp; public class Estudiante { private int id; private int idGrupo; public Estudiante() { this.id = 0; this.idGrupo = 0; } public Estudiante(int id, int idGrupo) { this.id = id;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

108

this.idGrupo = idGrupo; } public int getId() { return this.id; } public int getIdGrupo() { return this.idGrupo; } }

GrupoLista.java

package uam.pi.uamqrapp; public class GrupoLista { private int idUEA; private int idGrupo; private String grupo; private String nombreProfesor; private String lunes; private String martes; private String miercoles; private String jueves; private String viernes; public GrupoLista() { this.idUEA = 0; this.idGrupo = 0; this.grupo = new String(""); this.nombreProfesor = new String(""); this.lunes = new String(""); this.martes = new String(""); this.miercoles = new String(""); this.jueves = new String(""); this.viernes = new String(""); } public GrupoLista (int idUEA, int idGrupo, String grupo, String nombreProfesor, String lunes, String martes, String miercoles, String jueves, String viernes) { this.idUEA = idUEA; this.idGrupo = idGrupo; this.grupo = new String (grupo); this.nombreProfesor = new String (nombreProfesor);

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

109

this.lunes = new String (lunes); this.martes = new String (martes); this.miercoles = new String (miercoles); this.jueves = new String (jueves); this.viernes = new String (viernes); } public int getidUEA() { return this.idUEA; } public int getidGrupo() { return this.idGrupo; } public String getGrupo() { return this.grupo; } public String getnombreProfesor() { return this.nombreProfesor; } public String getlunes() { return this.lunes; } public String getmartes() { return this.martes; } public String getmiercoles() { return this.miercoles; } public String getjueves() { return this.jueves; } public String getviernes () { return this.viernes; } public void setidUEA (int idUEA) { this.idUEA = idUEA; }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

110

public void setidGrupo (int idGrupo) { this.idGrupo = idGrupo; } public void setgrupo (String grupo) { this.grupo = grupo; } public void setnombreProfesor( String nombreProfesor) { this.nombreProfesor = nombreProfesor; } public void setlunes (String lunes) { this.lunes = lunes; } public void setmartes (String martes) { this.martes = martes; } public void setmiercoles( String miercoles) { this.miercoles = miercoles; } public void setjueves (String jueves) { this.jueves = jueves; } public void setviernes (String viernes) { this.viernes = viernes; } } Utilidades de las clases

Se crearon además, unas clases que se requieren para la correcta consulta de las listas de los

horarios, las cuales identificamos con la terminación "Adapter" al final del nombre de los

archivos14.

GrupoAdapter.java

package uam.pi.uamqrapp; import java.util.ArrayList; import android.content.Context; import android.view.LayoutInflater;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

111

import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; public class GrupoAdapter extends BaseAdapter { private ArrayList<GrupoLista> searchArrayList; private LayoutInflater myInflater; public GrupoAdapter (Context context, ArrayList<GrupoLista> h) { this.searchArrayList = h; myInflater = LayoutInflater.from(context); } @Override public int getCount() { return searchArrayList.size(); } @Override public Object getItem(int position) { return searchArrayList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = myInflater.inflate(R.layout.custom_row_grupo, null); holder = new ViewHolder(); holder.grupo = (TextView)convertView.findViewById(R.id.grupolista); holder.profesorGrupo = (TextView)convertView.findViewById(R.id.profesorGrupo); holder.grupolunes = (TextView)convertView.findViewById(R.id.grupolunes);

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

112

holder.grupomartes = (TextView)convertView.findViewById(R.id.grupomartes); holder.grupomiercoles = (TextView)convertView.findViewById(R.id.grupomiercoles); holder.grupojueves = (TextView)convertView.findViewById(R.id.grupojueves); holder.grupoviernes = (TextView)convertView.findViewById(R.id.grupoviernes); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.grupo.setText(searchArrayList.get(position).getGrupo()); holder.profesorGrupo.setText(searchArrayList.get(position).getnombreProfesor()); holder.grupolunes.setText(searchArrayList.get(position).getlunes()); holder.grupomartes.setText(searchArrayList.get(position).getmartes()); holder.grupomiercoles.setText(searchArrayList.get(position).getmiercoles()); holder.grupojueves.setText(searchArrayList.get(position).getjueves()); holder.grupoviernes.setText(searchArrayList.get(position).getviernes()); return convertView; } static class ViewHolder { TextView grupo; TextView profesorGrupo; TextView grupolunes; TextView grupomartes; TextView grupomiercoles; TextView grupojueves; TextView grupoviernes; } }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

113

HorarioAdapter.java

package uam.pi.uamqrapp; import java.util.ArrayList; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; public class HorarioAdapter extends BaseAdapter { private static ArrayList<Horario> searchArrayList; private LayoutInflater myInflater; public HorarioAdapter (Context context, ArrayList<Horario> h) { searchArrayList = h; myInflater = LayoutInflater.from(context); } @Override public int getCount() { return searchArrayList.size(); } @Override public Object getItem(int position) { return searchArrayList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = myInflater.inflate(R.layout.custom_row_horario, null); holder = new ViewHolder(); holder.idUEA = (TextView) convertView.findViewById(R.id.idUEA); holder.uEA = (TextView) convertView.findViewById(R.id.uea);

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

114

holder.grupo = (TextView) convertView.findViewById(R.id.grupo); holder.lunes = (TextView) convertView.findViewById(R.id.lunes); holder.martes = (TextView) convertView.findViewById(R.id.martes); holder.miercoles = (TextView) convertView.findViewById(R.id.miercoles); holder.jueves = (TextView) convertView.findViewById(R.id.jueves); holder.viernes = (TextView) convertView.findViewById(R.id.viernes); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.idUEA.setText(Integer.toString(searchArrayList.get(position).getIdUEA())); holder.uEA.setText(searchArrayList.get(position).getUEA()); holder.grupo.setText(searchArrayList.get(position).getGrupo()); holder.lunes.setText(searchArrayList.get(position).getLunes()); holder.martes.setText(searchArrayList.get(position).getMartes()); holder.miercoles.setText(searchArrayList.get(position).getMiercoles()); holder.jueves.setText(searchArrayList.get(position).getJueves()); holder.viernes.setText(searchArrayList.get(position).getViernes()); return convertView; } static class ViewHolder { TextView idUEA; TextView uEA; TextView grupo; TextView lunes; TextView martes; TextView miercoles; TextView jueves; TextView viernes; } }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

115

HorarioSalaAdapter.java

package uam.pi.uamqrapp; import java.util.ArrayList; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; public class HorarioSalaAdapter extends BaseAdapter { private static ArrayList<Horario> searchArrayList; private LayoutInflater myInflater; public HorarioSalaAdapter (Context context, ArrayList<Horario> h) { searchArrayList = h; myInflater = LayoutInflater.from(context); } @Override public int getCount() { return searchArrayList.size(); } @Override public Object getItem(int position) { return searchArrayList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = myInflater.inflate(R.layout.custom_row_horario, null); holder = new ViewHolder(); holder.idUEA = (TextView) convertView.findViewById(R.id.idUEA); holder.uEA = (TextView) convertView.findViewById(R.id.uea);

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

116

holder.grupo = (TextView) convertView.findViewById(R.id.grupo); holder.lunes = (TextView) convertView.findViewById(R.id.lunes); holder.martes = (TextView) convertView.findViewById(R.id.martes); holder.miercoles = (TextView) convertView.findViewById(R.id.miercoles); holder.jueves = (TextView) convertView.findViewById(R.id.jueves); holder.viernes = (TextView) convertView.findViewById(R.id.viernes); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.idUEA.setText(Integer.toString(searchArrayList.get(position).getIdUEA())); holder.uEA.setText(searchArrayList.get(position).getUEA()); holder.grupo.setText(searchArrayList.get(position).getGrupo()); holder.lunes.setText(searchArrayList.get(position).getLunes()); holder.martes.setText(searchArrayList.get(position).getMartes()); holder.miercoles.setText(searchArrayList.get(position).getMiercoles()); holder.jueves.setText(searchArrayList.get(position).getJueves()); holder.viernes.setText(searchArrayList.get(position).getViernes()); return convertView; } static class ViewHolder { TextView idUEA; TextView uEA; TextView grupo; TextView lunes; TextView martes; TextView miercoles; TextView jueves; TextView viernes; } }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

117

Bases de datos

Se generó la clase específica para el manejo y administración de la base de datos:

DBHelper.java

package uam.pi.uamqrapp; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import android.annotation.SuppressLint; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

118

public class DBHelper extends SQLiteOpenHelper { private enum Day { lunes, martes, miercoles, jueves, viernes; } @SuppressLint("SdCardPath") private static final String DB_PATH = "/data/data/uam.pi2.uamqrapp/databases/"; private static final String DB_NAME = "uamdb.db"; private SQLiteDatabase myDataBase; private final Context context; private boolean checkDB() { SQLiteDatabase checkdb = null; try { String myPath = DB_PATH + DB_NAME; checkdb = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); } catch (SQLiteException e) { // La base de datos no existe todavía } if (checkdb != null) { checkdb.close(); } return checkdb != null ? true : false; } private void copyDB() throws IOException { InputStream myInput = context.getAssets().open(DB_NAME); String outFileName = DB_PATH + DB_NAME; OutputStream myOutput = new FileOutputStream(outFileName); byte[] buffer = new byte[1024]; int lenght; while ((lenght = myInput.read(buffer)) > 0) { myOutput.write(buffer, 0, lenght); } myOutput.flush(); myOutput.close(); myInput.close(); } private GrupoLista actualizaGrupo(GrupoLista g, Cursor c) { String [] dias = c.getString(5).split(","); for (String d : dias) {

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

119

switch (Day.valueOf(d)) { case lunes: g.setlunes(c.getString(3) + "\n" + c.getString(4)); break; case martes: g.setmartes(c.getString(3) + "\n" + c.getString(4)); break; case miercoles: g.setmiercoles(c.getString(3) + "\n" + c.getString(4)); break; case jueves: g.setjueves(c.getString(3) + "\n" + c.getString(4)); break; case viernes: g.setviernes(c.getString(3) + "\n" + c.getString(4)); break; } } return g; } private int posGrupo(ArrayList<GrupoLista> list, int uea, String grupo) { int i = 0; for (GrupoLista g : list) { if ((g.getidUEA() == uea) && (g.getGrupo().equals(grupo))) { return i; } else { i++; } } return -1; } private GrupoLista insertaGrupo(Cursor c) { GrupoLista g = new GrupoLista(); String[] dias = c.getString(5).split(","); g.setidUEA(c.getInt(0)); g.setidGrupo(c.getInt(6)); g.setgrupo(c.getString(1)); g.setnombreProfesor(c.getString(2)); for (String d : dias) { switch (Day.valueOf(d)) {

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

120

case lunes: g.setlunes(c.getString(3) + "\n" + c.getString(4)); break; case martes: g.setmartes(c.getString(3) + "\n" + c.getString(4)); break; case miercoles: g.setmiercoles(c.getString(3) + "\n" + c.getString(4)); break; case jueves: g.setjueves(c.getString(3) + "\n" + c.getString(4)); break; case viernes: g.setviernes(c.getString(3) + "\n" + c.getString(4)); break; } } return g; } private boolean noExisteGrupo(ArrayList<GrupoLista> list, int idUEA, String grupo) { for (GrupoLista g : list) { if ((g.getidUEA() == idUEA) && (g.getGrupo().equals(grupo))) { return false; } } return true; } private boolean noExiste(List<Horario> list, int uea, String grupo) { for (Horario h : list) { if ((h.getIdUEA() == uea) && (h.getGrupo().equals(grupo))) { return false; } } return true; } private Horario insertaHorario(Cursor cursor) { Horario h = new Horario(); String [] dias = cursor.getString(5).split(","); h.setidUEA(cursor.getInt(0));

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

121

h.setuea(cursor.getString(1)); h.setgrupo(cursor.getString(2)); for (String d : dias) { switch (Day.valueOf(d)) { case lunes: h.setlunes(cursor.getString(4) + "\n" + cursor.getString(3)); break; case martes: h.setmartes(cursor.getString(4) + "\n" + cursor.getString(3)); break; case miercoles: h.setmiercoles(cursor.getString(4) + "\n" + cursor.getString(3)); break; case jueves: h.setjueves(cursor.getString(4) + "\n" + cursor.getString(3)); break; case viernes: h.setviernes(cursor.getString(4) + "\n" + cursor.getString(3)); break; } } return h; } private Horario actualizaHorario(Horario h, Cursor cursor) { String [] dias = cursor.getString(5).split(","); for (String d : dias) { switch (Day.valueOf(d)) { case lunes: h.setlunes(cursor.getString(4) + "\n" + cursor.getString(3)); break; case martes: h.setmartes(cursor.getString(4) + "\n" + cursor.getString(3)); break; case miercoles: h.setmiercoles(cursor.getString(4) + "\n" + cursor.getString(3)); break; case jueves:

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

122

h.setjueves(cursor.getString(4) + "\n" + cursor.getString(3)); break; case viernes: h.setviernes(cursor.getString(4) + "\n" + cursor.getString(3)); break; } } return h; } private int posHorario(List<Horario> list, int uea, String grupo) { int i = 0; for (Horario h : list) { if ((h.getIdUEA() == uea) && (h.getGrupo().equals(grupo))) { return i; } else { i++; } } return -1; } private Horario insertaHorarioSala(Cursor cursor) { Horario h = new Horario(); String [] dias = cursor.getString(4).split(","); h.setidUEA(cursor.getInt(0)); h.setuea(cursor.getString(1)); h.setgrupo(cursor.getString(2)); for (String d : dias) { switch (Day.valueOf(d)) { case lunes: h.setlunes(cursor.getString(3)); break; case martes: h.setmartes(cursor.getString(3)); break; case miercoles: h.setmiercoles(cursor.getString(3)); break; case jueves: h.setjueves(cursor.getString(3)); break;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

123

case viernes: h.setviernes(cursor.getString(3)); break; } } return h; } public DBHelper(Context context) { super(context, DB_NAME, null, 1); this.context = context; } public void createDB() throws IOException { boolean dbExist = checkDB(); if (!dbExist) { this.getReadableDatabase(); try { copyDB(); } catch (IOException e) { throw new Error("Error copiando la base de datos"); } } } public void open() throws SQLException { try { createDB(); } catch (IOException e) { throw new Error("Ha sido imposible crear la base de datos"); } String myPath = DB_PATH + DB_NAME; myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); } public synchronized void close() { if (myDataBase != null) { myDataBase.close(); } super.close(); } @Override public void onCreate(SQLiteDatabase db) { }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

124

@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } public void addGroup(int id) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("idGrupo", id); db.insert("estudiante", null, values); db.close(); } public void removeGroup (int i) { SQLiteDatabase db = this.getWritableDatabase(); db.delete("estudiante", "idGrupo = " + i, null); } /* Funciones para los activities */ public List<Edificio> getAllEdificio() { List<Edificio> list = new ArrayList<Edificio>(); SQLiteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery("SELECT * FROM edificio", null); if (cursor.moveToFirst()) { do { Edificio e = new Edificio( Integer.parseInt(cursor.getString(0)), cursor.getString(1), cursor.getString(2) ); list.add(e); } while (cursor.moveToNext()); } db.close(); return list; } public List<Piso> getAllPiso(int id) { List<Piso> list = new ArrayList<Piso>(); SQLiteDatabase db = this.getWritableDatabase(); String query = new String( "SELECT " + "p._id, p.numPiso, p.descripcion, p.idEdificio " + "FROM edificio e INNER JOIN piso p " + "ON e._id = p.idEdificio " +

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

125

"WHERE p.idEdificio = " + Integer.toString(id) + " ORDER BY p.numPiso" ); Cursor cursor = db.rawQuery(query, null); if (cursor.moveToFirst()) { do { Piso p = new Piso( Integer.parseInt(cursor.getString(0)), Integer.parseInt(cursor.getString(1)), cursor.getString(2), Integer.parseInt(cursor.getString(3))); list.add(p); } while (cursor.moveToNext()); } db.close(); return list; } public List<Sala> getAllSala(int idEdificio, int idPiso) { List<Sala> list = new ArrayList<Sala>(); SQLiteDatabase db = this.getWritableDatabase(); String query = new String( "SELECT " + "s._id, s.numSala, s.descripcion, s.idPiso, s.idTipoSala " + "FROM edificio e INNER JOIN piso p INNER JOIN sala s " + "ON e._id = p.idEdificio AND p._id = s.idPiso " + "WHERE p.idEdificio = " + idEdificio + " AND s.idPiso = " + idPiso + " ORDER BY s.numSala" ); Cursor cursor = db.rawQuery(query, null); if (cursor.moveToFirst()) { do { Sala s = new Sala( cursor.getInt(0), cursor.getInt(1), cursor.getString(2), cursor.getInt(3), cursor.getInt(4) ); list.add(s); } while (cursor.moveToNext()); } db.close(); return list; }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

126

public List<Profesor> getAllProfesor() { List<Profesor> list = new ArrayList<Profesor>(); SQLiteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery("SELECT * FROM profesor ORDER BY apellidos", null); if (cursor.moveToFirst()) { do { Profesor p = new Profesor( cursor.getInt(0), cursor.getString(1), cursor.getString(2), cursor.getString(3), cursor.getString(4) ); list.add(p); } while (cursor.moveToNext()); } db.close(); return list; } public List<SalaProfesor> getAllSalaProfesor(int idProfesor) { List<SalaProfesor> list = new ArrayList<SalaProfesor>(); SQLiteDatabase db = this.getWritableDatabase(); Cursor c = db.rawQuery("SELECT * FROM salaProfesor WHERE idProfesor = " + idProfesor, null); if (c.moveToFirst()) { do { SalaProfesor s = new SalaProfesor(c.getInt(0), c.getInt(1), c.getInt(2), c.getString(3)); list.add(s); } while (c.moveToNext()); } db.close(); return list; } public List<UEA> getAllUeas() { List<UEA> list = new ArrayList<UEA>(); SQLiteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery("SELECT * FROM uea ORDER BY _id", null); if (cursor.moveToFirst()) { do { UEA u = new UEA( cursor.getInt(0),

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

127

cursor.getString(1) ); list.add(u); } while (cursor.moveToNext()); } db.close(); return list; } public ArrayList<GrupoLista> getAllGrupos(int idUEA) { ArrayList<GrupoLista> list = new ArrayList<GrupoLista>(); SQLiteDatabase db = this.getWritableDatabase(); String query = "SELECT " + "u._id idUEA, " + "g.grupo Grupo, " + "r.nombre || ' ' || r.apellidos Nombre, " + "h.inicio || '\n' || h.fin Hora, " + "e.letra || '-' || p.numPiso || substr('00' || s.numSala, -2, 2) Salon, " + "GROUP_CONCAT(h.dia) Dias, " + "g._id idGrupo" + " " + "FROM " + "uea u " + "INNER JOIN grupo g " + "INNER JOIN horario h " + "INNER JOIN sala s " + "INNER JOIN piso p " + "INNER JOIN edificio e " + "INNER JOIN profesor r " + "ON " + "u._id = g.idUEA " + "AND g._id = h.idGrupo " + "AND h.idSala = s._id " + "AND s.idPiso = p._id " + "AND p.idEdificio = e._id " + "AND g.idProfesor = r._id " + "WHERE " + "u._id = " + idUEA + " GROUP BY " + "Salon, idUEA " ; Cursor c = db.rawQuery(query, null); if (c.moveToFirst()) { do {

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

128

if (list.isEmpty() || noExisteGrupo(list, c.getInt(0), c.getString(1))) { list.add(insertaGrupo(c)); } else { int pos = posGrupo(list, c.getInt(0), c.getString(1)); list.set(pos, actualizaGrupo(list.get(pos), c)); } } while (c.moveToNext()); } db.close(); return list; } public ArrayList<Horario> getAllHorario() { ArrayList<Horario> list = new ArrayList<Horario>(); SQLiteDatabase db = this.getReadableDatabase(); String sql = "SELECT " + "u._id idUEA, " + "u.nombre UEA, " + "g.grupo Grupo, " + "e.letra || '-' || p.numPiso || substr('00' || s.numSala, -2, 2) Salon, " + "h.inicio || '\n' || h.fin Hora, " + "GROUP_CONCAT(h.dia) Dias " + "FROM " + "uea u " + "INNER JOIN grupo g " + "INNER JOIN horario h " + "INNER JOIN sala s " + "INNER JOIN piso p " + "INNER JOIN edificio e " + "INNER JOIN estudiante t " + "ON " + "u._id = g.idUEA " + "AND g._id = h.idGrupo " + "AND h.idSala = s._id " + "AND s.idPiso = p._id " + "AND p.idEdificio = e._id " + "AND t.idGrupo = g._id " + "GROUP BY " + "Salon, UEA " + "ORDER BY " + "UEA";

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

129

Cursor cursor = db.rawQuery(sql, null); int i; if (cursor.moveToFirst()) { do { if (list.isEmpty() || noExiste(list, cursor.getInt(0), cursor.getString(2)) ) { list.add(insertaHorario(cursor)); } else { i = posHorario(list, cursor.getInt(0), cursor.getString(2)); list.set(i, actualizaHorario(list.get(i), cursor)); } } while (cursor.moveToNext()); } db.close(); return list; } public Edificio getEdificio(int idEdificio) { Edificio e = new Edificio(); SQLiteDatabase db = this.getReadableDatabase(); Cursor c = db.rawQuery("SELECT * FROM edificio WHERE _id = " + idEdificio, null); if (c.moveToFirst()) { e = new Edificio( c.getInt(0), c.getString(1), c.getString(2) ); } db.close(); return e; } public Edificio getEdificio (String letra) { Edificio e = new Edificio(); SQLiteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery("Select * FROM edificio e WHERE e.letra = " + '"' + letra + '"', null); if (cursor.moveToFirst()) { e = new Edificio(cursor.getInt(0), cursor.getString(1), cursor.getString(2)); } db.close();

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

130

return e; } public Piso getPiso(int idPiso) { Piso p = new Piso(); SQLiteDatabase db = this.getReadableDatabase(); Cursor c = db.rawQuery("SELECT * FROM piso WHERE _id = " + idPiso, null); if (c.moveToFirst()) { p = new Piso( c.getInt(0), c.getInt(1), c.getString(2), c.getInt(3) ); } db.close(); return p; } public Piso getPiso(String letra, int numPiso) { Piso p = new Piso(); SQLiteDatabase db = this.getWritableDatabase(); String query = new String( "SELECT p._id, p.numPiso, p.descripcion, p.idEdificio " + "FROM edificio e INNER JOIN piso p " + "ON e._id = p.idEdificio " + "WHERE e.letra = " + '"' + letra + '"' + "AND p.numPiso = " + numPiso ); Cursor cursor = db.rawQuery(query, null); if (cursor.moveToFirst()) { p = new Piso(cursor.getInt(0), cursor.getInt(1), cursor.getString(2), cursor.getInt(3)); } db.close(); return p; } public Sala getSala(int idSala) { Sala s = new Sala(); SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.rawQuery("SELECT _id, numSala, descripcion, idPiso, idTipoSala FROM sala WHERE _id = " + idSala, null); if(cursor.moveToFirst()) { s = new Sala(

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

131

cursor.getInt(0), cursor.getInt(1), cursor.getString(2), cursor.getInt(3), cursor.getInt(4) ); } db.close(); return s; } public Sala getSala(String edificio, int piso, int sala) { Sala s = new Sala(); SQLiteDatabase db = this.getReadableDatabase(); String query = "SELECT s._id, s.numSala, s.descripcion, s.idPiso, s.idTipoSala " + "FROM edificio e INNER JOIN piso p INNER JOIN sala s " + "ON e._id = p.idEdificio AND p._id = s.idPiso " + "WHERE e.letra = " + '"' + edificio + '"' + " " + "AND p.numPiso = " + piso + " " + "AND s.numSala = " + sala ; Cursor cursor = db.rawQuery(query, null); if (cursor.moveToFirst()) { s = new Sala( cursor.getInt(0), cursor.getInt(1), cursor.getString(2), cursor.getInt(3), cursor.getInt(4) ); } db.close(); return s; } public String getSalaComplete(int idSala) { String sala = new String(); SQLiteDatabase db = this.getReadableDatabase(); String query = "SELECT " + "e.letra || '-' || p.numPiso || substr('00' || s.numSala, -2, 2) Salon " + "FROM " + "sala s " +

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

132

"INNER JOIN edificio e " + "INNER JOIN piso p " + "ON " + "s.idPiso = p._id " + "AND p.idEdificio = e._id " + "WHERE " + "s._id = " + idSala; Cursor c = db.rawQuery(query, null); if (c.moveToFirst()) { sala = c.getString(0); } return sala; } public Profesor getProfesor(int idProfesor) { Profesor p = new Profesor(); SQLiteDatabase db = this.getReadableDatabase(); Cursor c = db.rawQuery("SELECT * FROM profesor WHERE _id = " + idProfesor, null); if (c.moveToFirst()) { p = new Profesor( c.getInt(0), c.getString(1), c.getString(2), c.getString(3), c.getString(4) ); } db.close(); return p; } public List<Profesor> getProfesorSalon(int idSala) { List<Profesor> list = new ArrayList<Profesor>(); SQLiteDatabase db = this.getWritableDatabase(); String query = "SELECT " + "r._id, r.nombre, r.apellidos " + "FROM " + "profesor r " + "INNER JOIN salaProfesor sp " + "INNER JOIN sala s " + "ON " + "s._id = sp.idSala " + "AND r._id = sp.idProfesor " + "WHERE " + "sp.idSala = " + idSala +

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

133

" AND sp.relacion = " + '"' + "Cubiculo" + '"' ; Cursor cursor = db.rawQuery(query, null); if (cursor.moveToFirst()) { do { Profesor p = new Profesor( cursor.getInt(0), cursor.getString(1), cursor.getString(2), "", "" ); list.add(p); } while (cursor.moveToNext()); } db.close(); return list; } public Profesor getEncargado(int idSala) { Profesor p = new Profesor(); SQLiteDatabase db = this.getReadableDatabase(); String query = "SELECT " + "r._id, r.nombre, r.apellidos " + "FROM " + "profesor r " + "INNER JOIN salaProfesor sp " + "INNER JOIN sala s " + "ON " + "s._id = sp.idSala " + "AND r._id = sp.idProfesor " + "WHERE " + "sp.idSala = " + idSala + " AND sp.relacion = " + '"' + "Encargado" + '"' ; Cursor cursor = db.rawQuery(query, null); if (cursor.moveToFirst()) { p = new Profesor( cursor.getInt(0), cursor.getString(1), cursor.getString(2), "", "" ); }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

134

db.close(); return p; } public UEA getUEA(int idUEA) { UEA u = new UEA(); SQLiteDatabase db = this.getReadableDatabase(); Cursor c = db.rawQuery("SELECT * FROM uea WHERE _id = " + idUEA, null); if (c.moveToFirst()) { u = new UEA(c.getInt(0), c.getString(1)); } db.close(); return u; } public ArrayList<Horario> getHorario (int idSala) { ArrayList<Horario> list = new ArrayList<Horario>(); SQLiteDatabase db = this.getReadableDatabase(); String sql = "SELECT " + "u._id idUEA, " + "u.nombre UEA, " + "g.grupo Grupo, " + "h.inicio || '\n' || h.fin Hora, " + "GROUP_CONCAT(h.dia) Dias " + "FROM " + "uea u " + "INNER JOIN grupo g " + "INNER JOIN horario h " + "INNER JOIN sala s " + "INNER JOIN piso p " + "INNER JOIN edificio e " + "ON " + "u._id = g.idUEA " + "AND g._id = h.idGrupo " + "AND h.idSala = s._id " + "AND s.idPiso = p._id " + "AND p.idEdificio = e._id " + "WHERE " + "s._id = " + idSala + " GROUP BY " + "UEA " + "ORDER BY " + "UEA";

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

135

Cursor cursor = db.rawQuery(sql, null); int i; if (cursor.moveToFirst()) { do { if (list.isEmpty() || noExiste(list, cursor.getInt(0), cursor.getString(2)) ) { list.add(insertaHorarioSala(cursor)); } else { i = posHorario(list, cursor.getInt(0), cursor.getString(2)); list.set(i, actualizaHorario(list.get(i), cursor)); } } while (cursor.moveToNext()); } db.close(); return list; } public int numEdificios() { int contador; SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.rawQuery("SELECT * FROM edificio", null); contador = cursor.getCount(); cursor.close(); return contador; } public int numPisos(int id) { int contador; SQLiteDatabase db = this.getReadableDatabase(); String query = new String( "SELECT " + "p._id, p.numPiso, p.descripcion, p.idEdificio " + "FROM edificio e INNER JOIN piso p " + "ON e._id = p.idEdificio " + "WHERE p.idEdificio = " + Integer.toString(id) + " ORDER BY p.numPiso" ); Cursor cursor = db.rawQuery(query, null); contador = cursor.getCount(); cursor.close(); return contador; }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

136

public int numSalas(int idEdificio, int idPiso) { int contador; SQLiteDatabase db = this.getReadableDatabase(); String query = new String( "SELECT " + "s._id, s.numSala, s.descripcion, s.idPiso, s.idTipoSala " + "FROM edificio e INNER JOIN piso p INNER JOIN sala s " + "ON e._id = p.idEdificio AND p._id = s.idPiso " + "WHERE p.idEdificio = " + idEdificio + " AND s.idPiso = " + idPiso + " ORDER BY s.numSala" ); Cursor cursor = db.rawQuery(query, null); contador = cursor.getCount(); cursor.close(); return contador; } public int numProfesores() { int contador; SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.rawQuery("SELECT * FROM profesor", null); contador = cursor.getCount(); cursor.close(); return contador; } public int numUeas() { int contador; SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.rawQuery("SELECT * FROM uea", null); contador = cursor.getCount(); cursor.close(); return contador; } }

Intents

Se generaron las clases necesarias para la generación y comportamiento de cada una de las

pantallas requeridas en la aplicación, en la cual agregamos los comportamientos de los

botones y listas de la aplicación, para la navegación entre interfaces de la aplicación.

Main.java

package uam.pi.uamqrapp;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

137

import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageButton; import android.widget.Toast; import android.app.Activity; import android.content.Intent; public class Main extends Activity { private DBHelper db; ImageButton scheduleBtn; ImageButton ueaBtn; ImageButton qrBtn; ImageButton buildingBtn; ImageButton teacherBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); db = new DBHelper(this); db.open(); scheduleBtn = (ImageButton)findViewById(R.id.scheduleButton); ueaBtn = (ImageButton)findViewById(R.id.ueaButton); qrBtn = (ImageButton)findViewById(R.id.qrButton); buildingBtn = (ImageButton)findViewById(R.id.buildingButton); teacherBtn = (ImageButton)findViewById(R.id.teacherButton); scheduleBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Main.this, FrmSchedule.class); startActivity(intent); } }); ueaBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Main.this, FrmUEA.class); startActivity(intent);

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

138

} }); qrBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent("com.google.zxing.client.android.SCAN"); intent.putExtra("SCAN_MODE", "QR_VALUE"); startActivityForResult(intent, 0); } }); buildingBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Main.this, FrmBuilding.class); startActivity(intent); } }); teacherBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Main.this, FrmTeacherList.class); startActivity(intent); } }); } @Override public void onPause() { super.onPause(); db.close(); } @Override public void onResume() { super.onResume(); db.open(); } public void onActivityResult(int requestCode, int resultCode, Intent intent) { String edificio = new String(); int piso = 0;

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

139

int sala = 0; Intent frame = new Intent(); db.open(); if (requestCode == 0) { if (resultCode == RESULT_OK) { Bundle bundle = new Bundle(); String[] mensaje = intent.getStringExtra("SCAN_RESULT").split("#"); if (mensaje[0].equals("UAM QR App") && (mensaje.length > 1) && (mensaje.length < 5)) { switch (mensaje.length) { case 4: sala = Integer.parseInt(mensaje[3]); case 3: piso = Integer.parseInt(mensaje[2]); case 2: edificio = new String (mensaje[1]); break; } switch (mensaje.length) { case 4: bundle.putInt("idSala", db.getSala(edificio, piso, sala).getId()); bundle.putString("numSala", "" + db.getSala(edificio, piso, sala).getNumSala()); bundle.putInt("idTipo", db.getSala(edificio, piso, sala).getIdTipo()); case 3: bundle.putInt("idPiso", db.getPiso(edificio, piso).getId()); bundle.putString("numPiso", "" + piso); case 2: bundle.putInt("idEdificio", db.getEdificio(edificio).getId()); bundle.putString("letra", edificio); break; } switch (mensaje.length) { case 4: frame = new Intent(this, FrmRoom.class); break; case 3: frame = new Intent(this, FrmRoomList.class); break; case 2:

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

140

frame = new Intent(this, FrmFloor.class); break; } frame.putExtras(bundle); startActivity(frame); } else { Intent frmMensaje = new Intent(this, FrmQR.class); bundle.putString("MENSAJE", intent.getStringExtra("SCAN_RESULT")); frmMensaje.putExtras(bundle); startActivity(frmMensaje); } } else if(resultCode == RESULT_CANCELED) { // Handle cancel Toast toast = Toast.makeText(this, "Escaneo cancelado", Toast.LENGTH_LONG); toast.setGravity(Gravity.TOP, 25, 400); toast.show(); } } } }

FrmBuilding.java

package uam.pi.uamqrapp; import java.util.List; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; public class FrmBuilding extends Activity { private DBHelper db; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.building);

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

141

db = new DBHelper(this); db.open(); final List<Edificio> edificios = db.getAllEdificio(); String[] letraEdificio = new String[db.numEdificios()]; int i = 0; for (Edificio e : edificios) { letraEdificio[i] = e.getLetra(); i++; } ListView listview = (ListView)findViewById(R.id.listaEdificios); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, letraEdificio); listview.setAdapter(adapter); listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Edificio e = edificios.get(position); int idEdificio = e.getId(); Intent intent = new Intent(FrmBuilding.this, FrmFloor.class); Bundle bundle = new Bundle(); bundle.putInt("idEdificio", idEdificio); bundle.putString("letra", e.getLetra()); intent.putExtras(bundle); startActivity(intent); } }); } @Override public void onPause() { super.onPause(); db.close(); } @Override public void onResume() { super.onResume(); db.open();

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

142

} }

FrmFloor.java

package uam.pi.uamqrapp; import java.util.List; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; public class FrmFloor extends Activity { private DBHelper db; @Override public void onCreate(Bundle savedInstanceState) { final int idEdificio; final String letra; super.onCreate(savedInstanceState); setContentView(R.layout.floor); db = new DBHelper(this); db.open(); Bundle bundle = getIntent().getExtras(); idEdificio = bundle.getInt("idEdificio"); letra = new String(bundle.getString("letra")); Edificio e = db.getEdificio(idEdificio); TextView desc = (TextView)findViewById(R.id.descripcionEdificio); desc.setText(e.getDescripcion()); final List<Piso> list = db.getAllPiso(idEdificio); String[] numPiso = new String[db.numPisos(idEdificio)]; int i = 0; for (Piso p : list) { numPiso[i] = Integer.toString(p.getNumPiso()); i++; }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

143

TextView textview = (TextView)findViewById(R.id.letraEdificio); textview.setText(letra); ListView listview = (ListView)findViewById(R.id.numPisos); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, numPiso); listview.setAdapter(adapter); listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Piso p = list.get(position); int idPiso = p.getId(); Intent intent = new Intent(FrmFloor.this, FrmRoomList.class); Bundle bundle = new Bundle(); bundle.putInt("idEdificio", idEdificio); bundle.putString("letra", letra); bundle.putInt("idPiso", idPiso); bundle.putString("numPiso", Integer.toString(p.getNumPiso())); intent.putExtras(bundle); startActivity(intent); } }); } @Override public void onPause() { super.onPause(); db.close(); } @Override public void onResume() { super.onResume(); db.open(); } }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

144

FrmRoomList.java

package uam.pi.uamqrapp; import java.util.List; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; public class FrmRoomList extends Activity { private DBHelper db; @Override public void onCreate(Bundle savedInstanceState) { final int idEdificio; final int idPiso; final String letra; final String numPiso; db = new DBHelper(this); db.open(); super.onCreate(savedInstanceState); setContentView(R.layout.room); Bundle bundle = getIntent().getExtras(); idEdificio = bundle.getInt("idEdificio"); idPiso = bundle.getInt("idPiso"); letra = new String(bundle.getString("letra")); numPiso = new String(bundle.getString("numPiso")); Piso p = db.getPiso(idPiso); TextView desc = (TextView)findViewById(R.id.descripcionPiso); desc.setText(p.getDescripcion()); final List<Sala> list = db.getAllSala(idEdificio, idPiso); String[] numSala = new String[db.numSalas(idEdificio, idPiso)]; int i = 0; for (Sala s : list) {

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

145

numSala[i] = Integer.toString(s.getNumSala()); i++; } TextView textview = (TextView)findViewById(R.id.edificioPiso); textview.setText(letra + "-" + numPiso); ListView listview = (ListView)findViewById(R.id.numSalas); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, numSala); listview.setAdapter(adapter); listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Sala s = list.get(position); Intent intent = new Intent(FrmRoomList.this, FrmRoom.class); Bundle bundle = new Bundle(); bundle.putInt("idEdificio", idEdificio); bundle.putString("letra", letra); bundle.putInt("idPiso", idPiso); bundle.putString("numPiso", numPiso); bundle.putInt("idSala", s.getId()); bundle.putString("numSala", Integer.toString(s.getNumSala())); bundle.putInt("idTipo", s.getIdTipo()); intent.putExtras(bundle); startActivity(intent); } }); } @Override public void onPause() { super.onPause(); db.close(); }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

146

@Override public void onResume() { super.onResume(); db.open(); } }

FrmRoom.java

package uam.pi.uamqrapp; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; public class FrmRoom extends Activity { private DBHelper db; @Override public void onCreate(Bundle savedInstanceState) { int idSala, idTipo; String edificio, piso, sala; Bundle bundle = getIntent().getExtras(); idSala = bundle.getInt("idSala"); idTipo = bundle.getInt("idTipo"); edificio = new String(bundle.getString("letra")); piso = new String(bundle.getString("numPiso")); sala = new String(bundle.getString("numSala")); ListView listview = new ListView(this); ArrayList<Horario> h; db = new DBHelper(this); db.open(); super.onCreate(savedInstanceState);

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

147

switch (idTipo) { case 1 : //Cubículo setContentView(R.layout.cubiculo); final List<Profesor> list = db.getProfesorSalon(idSala); String[] profesores = new String[list.size()]; int i = 0; for (Profesor p : list) { profesores[i] = p.getnombre() + " " + p.getapellidos(); i++; } listview = (ListView)findViewById(R.id.listaProfesoresSalon); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, profesores); listview.setAdapter(adapter); listview.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = new Intent (FrmRoom.this, FrmProfesor.class); Bundle bundle = new Bundle(); bundle.putInt("idProfesor", list.get(position).getid()); intent.putExtras(bundle); startActivity(intent); } }); break; case 2 : //Aula setContentView(R.layout.sala); h = db.getHorario(idSala); listview = (ListView)findViewById(R.id.listaHorarioSalon); listview.setAdapter(new HorarioAdapter(this, h)); listview.setOnItemClickListener(new OnItemClickListener() { @Override

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

148

public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast toast = Toast.makeText(FrmRoom.this, "En construcción", Toast.LENGTH_LONG); toast.show(); } }); break; case 4 : //Laboratorio setContentView(R.layout.laboratorio); TextView encargado = (TextView)findViewById(R.id.nombreEncargado); encargado.setText(db.getEncargado(idSala).getnombre() + " " + db.getEncargado(idSala).getapellidos()); h = db.getHorario(idSala); listview = (ListView)findViewById(R.id.listaHorarioLaboratorio); listview.setAdapter(new HorarioAdapter(this, h)); listview.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast toast = Toast.makeText(FrmRoom.this, "En construcción", Toast.LENGTH_LONG); toast.show(); } }); break; default : Toast toast = Toast.makeText(this, "En construcción", Toast.LENGTH_SHORT); toast.show(); break; } TextView text = (TextView)findViewById(R.id.salon); text.setText(edificio + "-" + piso + String.format("%02d", Integer.parseInt(sala))); TextView desc = (TextView)findViewById(R.id.descripcionSalon); desc.setText(db.getSala(idSala).getDescripcion());

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

149

} @Override public void onPause() { super.onPause(); db.close(); } @Override public void onResume() { super.onResume(); db.open(); } }

FrmProfesor.java

package uam.pi.uamqrapp; import java.util.List; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.AdapterView.OnItemClickListener; public class FrmProfesor extends Activity { private DBHelper db; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.profesor); db = new DBHelper(this); db.open(); Bundle bundle = getIntent().getExtras(); Profesor p = db.getProfesor(bundle.getInt("idProfesor"));

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

150

TextView textNombre = (TextView)findViewById(R.id.nombreProfesor); String nombre = new String(p.getnombre() + " " + p.getapellidos()); textNombre.setText(nombre); TextView textDescripcion = (TextView)findViewById(R.id.descripcionProfesor); textDescripcion.setText(p.getdescripcion()); TextView textEmail = (TextView)findViewById(R.id.emailProfesor); textEmail.setText(p.getemail()); final List<SalaProfesor> list = db.getAllSalaProfesor(p.getid()); String[] c = new String[list.size()]; int i = 0; for (SalaProfesor s : list) { c[i] = db.getSalaComplete(s.getIdSala()) + " (" + s.getrelacion() + ")"; i++; } ListView cubiculo = (ListView)findViewById(R.id.cubiculoProfesor); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, c); cubiculo.setAdapter(adapter); cubiculo.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { SalaProfesor sp = list.get(position); Sala s = db.getSala(sp.getIdSala()); Piso p = db.getPiso(s.getIdPiso()); Edificio e = db.getEdificio(p.getIdEdificio()); Bundle bundle = new Bundle(); bundle.putInt("idSala", sp.getIdSala()); bundle.putInt("idTipo", s.getIdTipo()); bundle.putString("letra", e.getLetra()); bundle.putString("numPiso", "" + p.getNumPiso()); bundle.putString("numSala", "" + s.getNumSala()); Intent intent = new Intent(FrmProfesor.this, FrmRoom.class); intent.putExtras(bundle);

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

151

startActivity(intent); } }); } @Override public void onPause() { super.onPause(); db.close(); } @Override public void onResume() { super.onResume(); db.open(); } }

FrmTeacherList.java

package uam.pi.uamqrapp; import java.util.List; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.AdapterView.OnItemClickListener; public class FrmTeacherList extends Activity { private DBHelper db; @Override public void onCreate(Bundle savedInstanceState) { db = new DBHelper(this); db.open(); super.onCreate(savedInstanceState); setContentView(R.layout.teacher);

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

152

final List<Profesor> list = db.getAllProfesor(); String[] profesores = new String[db.numProfesores()]; int i = 0; for (Profesor p : list) { profesores[i] = p.getnombre() + " " + p.getapellidos(); i++; } ListView listview = (ListView)findViewById(R.id.listaProfesores); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, profesores); listview.setAdapter(adapter); listview.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Profesor p = list.get(position); Bundle bundle = new Bundle(); bundle.putInt("idProfesor", p.getid()); Intent intent = new Intent(FrmTeacherList.this, FrmProfesor.class); intent.putExtras(bundle); startActivity(intent); } }); } @Override public void onPause() { super.onPause(); db.close(); } @Override public void onResume() { super.onResume(); db.open(); }

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

153

}

FrmUEA.java

package uam.pi.uamqrapp; import java.util.List; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ListView; public class FrmUEA extends Activity { DBHelper db; @Override public void onCreate(Bundle savedInstanceState) { db = new DBHelper(this); db.open(); super.onCreate(savedInstanceState); setContentView(R.layout.uea); final List<UEA> list = db.getAllUeas(); String[] ueas = new String[db.numUeas()]; int i = 0; for (UEA u : list) { ueas[i] = u.getid() + " - " + u.getnombre(); i++; } ListView listview = (ListView)findViewById(R.id.listaUEAs); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, ueas); listview.setAdapter(adapter); listview.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

154

UEA u = list.get(position); Intent intent = new Intent(FrmUEA.this, FrmGrupos.class); Bundle bundle = new Bundle(); bundle.putInt("idUEA", u.getid()); intent.putExtras(bundle); startActivity(intent); } }); } @Override public void onPause() { super.onPause(); db.close(); } @Override public void onResume() { super.onResume(); db.open(); } }

FrmGrupos.java

package uam.pi.uamqrapp; import java.util.ArrayList; import android.app.Activity; import android.os.Bundle; import android.widget.ListView; import android.widget.TextView; public class FrmGrupos extends Activity { private DBHelper db; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.grupos); db = new DBHelper(this); db.open(); Bundle bundle = getIntent().getExtras(); UEA u = db.getUEA(bundle.getInt("idUEA"));

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

155

TextView textview = (TextView)findViewById(R.id.ueaGrupos); textview.setText(u.getnombre()); ArrayList<GrupoLista> h = db.getAllGrupos(u.getid()); ListView listview = (ListView)findViewById(R.id.listaGrupos); if (h.size() > 0) { listview.setAdapter(new GrupoAdapter(this, h)); } } }

FrmSchedule.java

package uam.pi.uamqrapp; import java.util.ArrayList; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; public class FrmSchedule extends Activity { DBHelper db; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.schedule); db = new DBHelper(this); db.open(); ArrayList<Horario> h = db.getAllHorario(); ListView listview = (ListView)findViewById(R.id.listaHorarioLaboratorio); listview.setAdapter(new HorarioAdapter(this, h)); listview.setOnItemClickListener(new OnItemClickListener() {

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

156

@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast toast = Toast.makeText(FrmSchedule.this, "En construcción", Toast.LENGTH_LONG); toast.show(); } }); } @Override public void onPause() { super.onPause(); db.close(); } @Override public void onResume() { super.onResume(); db.open(); } }

FrmQR.java

package uam.pi.uamqrapp; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class FrmQR extends Activity{ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.qr); TextView txtMensaje = (TextView)findViewById(R.id.mensaje); Bundle bundle = getIntent().getExtras(); txtMensaje.setText(bundle.getString("MENSAJE")); } }

Permisos (AndroidManifest.xml)

Por último, otorgamos los permisos pertinentes para cada una de las interfaces de la

aplicación.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

157

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="uam.pi.uamqrapp" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="uam.pi.uamqrapp.Main" 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="uam.pi.uamqrapp.FrmBuilding" android:label="@string/edificios"> </activity> <activity android:name="uam.pi.uamqrapp.FrmFloor" android:label="@string/pisos"> </activity> <activity android:name="uam.pi.uamqrapp.FrmGrupos" android:label="@string/grupos"> </activity> <activity android:name="uam.pi.uamqrapp.FrmProfesor" android:label="@string/profesor"> </activity> <activity android:name="uam.pi.uamqrapp.FrmQR" android:label="MensajeQR"> </activity> <activity android:name="uam.pi.uamqrapp.FrmRoom" android:label="@string/salas">

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

158

</activity> <activity android:name="uam.pi.uamqrapp.FrmRoomList" android:label="@string/pisos"> </activity> <activity android:name="uam.pi.uamqrapp.FrmSchedule" android:label="@string/horario"> </activity> <activity android:name="uam.pi.uamqrapp.FrmTeacherList" android:label="@string/profesor"> </activity> <activity android:name="uam.pi.uamqrapp.FrmUEA" android:label="@string/uea"> </activity> </application> </manifest>

Resultados

Se decidió realizar una prueba que consistía, en que a una determinada selección de usuarios potenciales de la aplicación, se les mostraría la aplicación en ejecución, al inicio la

intención era distribuirla a sus dispositivos personales pero por problemas de compatibilidad con celulares, se decidió que les mostraríamos una tableta con la aplicación en ejecución y al finalizar la sesión de uso, se continuará con unas preguntas evaluadoras,

que nos ayudarán a valorar los resultados arrojados en la aplicación. Las preguntas en las

que consistía la evaluación fueron las siguientes:

1. ¿Dispositivo en que utilizaría la aplicación? a. Tableta b. Celular c. Ambos

2. ¿Su consulta en la aplicación fue exitosa? a. Si b. No

3. ¿La interfaz de la aplicación le fue? a. Intuitiva b. Regular c. Confusa

4. ¿Usted considera que la aplicación le sería de utilidad dentro la universidad? ¿Porqué?

a. Si

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

159

b. No 5. ¿La aplicación le pareció?

a. Rápida b. Regular c. Lenta

Los resultados arrojados por la evaluación a una población de 30 personas, de las cuales participaron alumnos, profesores y público en general, nos dieron la pauta de varias sugerencias acerca de la aplicación, aunque la tendencia fue de que la mayoría de los usuarios preferiría usar su teléfono celular para usar la aplicación, el soporte a versiones

más antiguas del elegido en el proyecto, pues esta última está diseñada para tabletas con la

versión de Android 3.0 (Honeycomb).

Discusión La principal discusión que se abordó después de los resultados era sí convenía portar la aplicación de tabletas a celulares para que la disponibilidad se más abierta a los usuarios más

potenciales, aunque vimos que sería muy conveniente se decidió dejar el cambio para una

versión posterior de la aplicación.

Conclusiones Al finalizar el desarrollo se obtuvo una aplicación estable con un rendimiento aceptable y todos los requerimientos que se plantearon al inicio se cumplen satisfactoriamente, después de haber realizado pruebas y someter la aplicación a una evaluación con usuarios

potenciales, se llego a la conclusión de que se obtuvo una aplicación estable y que aún por ser una primer versión cumple las expectativas planteadas al inicio del desarrollo. Para un futuro trabajo, se puede tomar como base esta aplicación, y desarrollar la conexión con un

servidor que contenga la información requerida y actualizada, aligerando el tamaño en disco de la aplicación, logrando una mejor respuesta de ejecución, así como evitar la necesidad de

actualizar la aplicación por completo.

Aplicación móvil para proporcionar información sensible a la ubicación(contexto)

14 de julio de 2013

Página

160

Referencias 1 Oracle. http://www.oracle.com/technetwork/es/java/javase/downloads/index.html. Enero 2013. 2 Android Developers. http://developer.android.com/sdk/index.html. Enero 2013. 3 Sgoliver.net blog. http://www.sgoliver.net/blog/?p=1267. Enero 2013. 4 W.M. Lee, Beggining Android™ Application Development.1ra Edición. 2011. Wiley Publishing Inc. Indianapolis, Indiana. 43-47. 5 Wikipedia. http://es.wikipedia.org/wiki/SQLite. Febrero 2013. 6 SQLite. http://www.sqlite.org. Febrero 2013. 7 NetRunners, hijos del ciberespacio. http://blog.netrunners.es/usar-nuestra-propia-base-de-datos-sqlite-en-android/. Junio 2013. 8 W.M. Lee, Beggining Android™ Application Development.1ra Edición. 2011. Wiley Publishing Inc. Indianapolis, Indiana. 218-234. 9 Código QR. http://es.wikipedia.org/wiki/Código_QR. Mayo 2013. 10 ZXing. https://code.google.com/p/zxing/. Mayo 2013. 11 Stack Overflow. http://stackoverflow.com/questions/8708705/how-to-use-zxing-in-android. Junio 2013. 12 Maven release repository. http://repo1.maven.org/maven2/com/google/zxing/core/2.2/. Junio 2013 13 Kaywa QR Code. http://qrcode.kaywa.com/. Mayo 2013 14 Vogella. http://www.vogella.com/articles/AndroidListView/. Junio 2013.