188
Escuela Superior de Ingeniería Universidad de Cádiz Titulación Grado en Ingeniería Informática Trabajo de Fin de Grado UniSubject Aplicación Móvil que Comparar Universidades A Nivel Material y Asignatura Departamento: Ingeniería Informática Director del Proyecto: Carlos Rioja del Rio Autor del Proyecto: Alecia Adelaide May Reid

UniSubject - rodin.uca.es

  • Upload
    others

  • View
    10

  • Download
    0

Embed Size (px)

Citation preview

Page 1: UniSubject - rodin.uca.es

Escuela Superior de Ingeniería Universidad de Cádiz

Titulación

Grado en Ingeniería Informática Trabajo de Fin de Grado

UniSubject

Aplicación Móvil que Comparar Universidades A Nivel Material y Asignatura

Departamento: Ingeniería Informática Director del Proyecto: Carlos Rioja del Rio Autor del Proyecto: Alecia Adelaide May Reid

Page 2: UniSubject - rodin.uca.es

Agradecimientos A mi tutor, por su confianza y apoyo durante el trabajo. A mi familia por entender los momentos de mi ausencia en las reuniones familiares mientras preparo este trabajo.

Page � of �2 188

Page 3: UniSubject - rodin.uca.es

Resumen El desarrollo de un sistema para dispositivos móviles cuyo propósito sea la búsqueda y comparación de asignaturas agrupadas por material y facultad de distintas universidades. Aporta información y señalización en la mapa google.

El sistema utilizará la tecnología disponible para propiciar la búsqueda y comparación de datos especificas, ofreciendo las herramientas necesarias para que los usuarios puedan comparar y elegir la universidad que más le gusta según las descripción de las asignaturas que quiere cursar en menos de 5 minutos.

Palabras Claves:

Universidad Asignatura Faculty Android Sistema de Búsqueda Comparación entre Asignaturas Comparación entre Material Comparación entre Facultad.

Page � of �3 188

Page 4: UniSubject - rodin.uca.es

Índice General

I Prolegómenos 1. Introducción 1.1 Motivación 1.2 Descripción del sistema actual 1.3 Objetivos y alcance del proyecto 1.4 Organización del documento 2. Planificación 2.1 Metodologia de desarrollo 2.2 Planificación del proyecto 2.3 organización 2.4 Coste 2.5 Gestión de riesgo

II Desarrollo 3. Analysis de Requisite 3.1 Catalogo de actores 3.2 Requisitos funcionales 3.3 Requisites de informaciones 3.4 Requisites no funcionales 3.5 Reglas de negocio 3.6 Estudios de alternativas tecnológicas 3.7 Análisis de GAP

4. Diseño del sistema 4.1 Diseño de la arquitectura 4.1.1 Arquitectura fisica 4.1.2 Arquitectura lógico 4.1.3 Arquitectura de diseño 4.2 Diseño de la interface usuario 4.3 Diseño de datos 4.4 Diseño de componentes 4.5 Parametrización del software base 5. Implementation del sistema 5.1 Entorno tecnología 5.2 Código Fuente 5.3 Calidad de código 6. Pruebas de sistema 6.1 Pruebas unitarias

Page � of �4 188

Page 5: UniSubject - rodin.uca.es

6.2 Pruebas de integración 6.3 Pruebas de sistema 6.3.1 Pruebas funcional 6.3.2 Pruebas no funcional 6.4 Pruebas de aceptación

III Epílogo 7. Manual de usuario 7.1 Introducción 7.2 Características 7.3 Requisitos previos 7.4 Instalación 8. Manual de installation y explotación 8.1 Introducción 8.2 Requisitos previos 8.3 Inventário de componentes 8.4 procedimientos de instalación 8.5 Procedimiento de operación y nivel de servicio 8.6 Pruebas de implantación

9. Conclusiones 9.1 objectivos 9.2 Lesiones aprendidas 9.3 Trabajo futuro

Bibliografía

Información sobre Licencia

Page � of �5 188

Page 6: UniSubject - rodin.uca.es

Parte 1

Prolegómeno

Page � of �6 188

Page 7: UniSubject - rodin.uca.es

Capítulo 1 Introducción

En este capítulo presentaré mi proyecto, expondré la motivación que ha llevado a su realización, el objetivo principal y la profundidad que deseo alcanzar. También detallaré como está estructurada la presente memoria.

1.1 Motivación

La principal motivación del proyecto es aportar un enfoque alternativo y actual al campo de los sistemas de basados en las búsqueda y comparación de asignaturas universitarias, donde actualmente para buscar una asignatura tendrá que hacer una búsqueda de universidades y después de pasar por media de su pagina entonces empieza facultad por facultad y material por material y luego asignatura por asignatura. Todo este proceso por cada universidad el usuario tiene como resultado de su búsqueda. Al final si no tiene escrito la información sobre la asignatura no hay manera de compararlo.

Con esta aplicación las universidades puede registrar su universidad en el sistema y tendrá sus facultad, material y asignaturas a la disposición a los usuarios de la aplicación. La realización del proyecto también proporciona una gran oportunidad para reforzar y ampliar la formación recibida durante el paso por la titulación, obteniendo una visión integradora de los conocimientos obtenidos en las distintas materias que la componen y obteniendo nuevos conocimientos sobre el desarrollo de sistemas para dispositivos móviles, un campo que ha experimentado una importante expansión en los últimos tiempos, consiguiendo una gran aceptación en la sociedad actual, donde los usuarios desean disponer de la tecnología en cualquier momento en el lugar donde se encuentren al menos tiempo y esfuerzo posible.

1.2 Objetivos y alcance del proyecto

El sistema utiliza la tecnología disponible para propiciar la búsqueda y comparación de asignaturas agrupadas por material y facultad de distintas universidades o el mismo. Aporta información y señalización en la mapa google. Ofreciendo las herramientas necesarias para que los usuarios puedan elegir la universidad a estudiar según la descripción de las asignaturas.

Con el enfoque anterior como punto de partida, he desarrollada un sistema para dispositivos móviles cuyo propósito sea la la búsqueda y comparación de asignaturas agrupadas por material y facultad de distintas universidades o el mismo, al encontrar la universidad ideal en menos de 5 minutos el usuario puede ir directamente a la pagina web de dicha universidad o le llama directamente o le manda un email desde la aplicación.

Page � of �7 188

Page 8: UniSubject - rodin.uca.es

Los usuarios y universidades podrán registrar sus perfiles en el sistema, y una vez registrados podrán iniciar sesión en cualquier momento para acceder a todas las funciones que ofrece la aplicación según el tipo de usuario.

El usuario denominada privado podrá realizar búsqueda y comparación directas en tiempos más cortas que resulta en una decision mas rápida para el usuario. El usuario como universidad puede editar el perfil y datos sobre su universidad, facultas, majors y asignaturas. Todos los usuarios registrados en el sistema podrán subir fotos al album de fotos de las universidades.

El usuario podrá personalizar su perfil. También podrá consultar el perfil de los usuarios como universidad.

1.3 Descripción de la Tecnología actual usada

Dentro de este proyecto, Android conforma la base sobre la que se desarrolla la aplicación. Sin embargo, son necesarias unas series de tecnologías adicionales para que la aplicación cobre su sentido y pueda aportar las funcionalidades que caracterizan a este tipo de aplicación. En este proyecto en particular las tecnologías usadas son las descritas a lo largo de este sección

Tal y como se puede observar, las tecnologías crean dependencias entre sí: • Para poder almacenar información se precisan bases de datos, las cuales se

acceden mediante el lenguaje SQL. • La aplicación solicita mediante HTTP la información que necesita y se le es

devuelta en forma de ficheros XML. • El lenguaje PHP permite realizar scripts que atiendan a las peticiones de la

aplicación, automatizando las búsquedas en la BBDD y la posterior devolución de resultados.

Todas las tecnologías juntas conforman un prototipo de la comunicación y interconexión. A continuación, se describen con claridad las diferentes tecnologías conceptos, explicando su funcionamiento, sus pros y sus contras.

Page � of �8 188

Page 9: UniSubject - rodin.uca.es

Bases de Datos Una base de datos (BBDD) es un conjunto de datos pertenecientes a un mismo contexto y almacenados sistemáticamente para su posterior uso. Dentro de esta definición global, en este PFC nos centraremos en las BBDD en formato digital, las cuales permiten

almacenar una gran variedad de tipos de datos. Las aplicaciones pueden ir desde la gestión de empresas hasta el uso en entornos científicos, pasando también, por ejemplo, por su uso en servicios web. Gracias a las BBDD, son posibles por ejemplo, los foros, las redes sociales y aplicaciones móviles en general.

Para poder gestionar y manipular las BBDD se precisa de unos programas denominados sistemas gestores de bases de datos (SGBD, en inglés DBMS, Database Management System) que permiten almacenar y posteriormente acceder a los datos de forma rápida y estructurada.

Entre los diferentes tipos de BBDD la más usual, y la que se utilizar en el TFG presente, es la BBDD del tipo dinámico relacional. Fueron enunciadas por Edgar Frank Codd en 1970 [11]. Las BBDD relacionales se basan en el uso de relaciones o tablas, que a su vez están compuestas por registros (las filas de una tabla), llamados tuplas, y campos (las columnas de una tabla). La principal ventaja de estas BBDD es que no importa el orden en el que se almacenan los datos. Para poder introducir datos o extraerlos se utilizan consultas a la BBDD. También permiten ordenarlas tomando cualquier campo como criterio y generar informes que contienen sólo determinados campos de cada tupla o registro.

Ejemplo de estructura de BBDD relacional

Page � of �9 188

Page 10: UniSubject - rodin.uca.es

Las ventajas de este modelo son: • Garantiza herramientas para evitar la duplicidad de registros, a través de campos

claves o llaves. • Garantiza la integridad referencial: Así al eliminar un registro elimina todos los

registros relacionados dependientes. • Favorece la normalización por ser más comprensible y aplicable.

Puntos fuertes de una Base de Datos • Proveen facilidades para la manipulación de grandes volúmenes de datos

(consistencia, modificaciones con impacto mínimo, seguridad). • Las facilidades anteriores bajan drásticamente los tiempos de desarrollo y

aumentan la calidad del sistema desarrollado si son bien explotados por los desarrolladores.

• Usualmente, proveen interfaces y lenguajes de consulta que simplifican la recuperación de los datos.

Puntos débiles de una Base de Datos • Necesidad: si se tienen muy pocos datos no es eficiente el uso de una BBDD. • Complejidad: los DBMS son software muy complejos y las personas que vayan

a usarlo deben tener conocimiento de las funcionalidades del mismo para poder aprovecharlo al máximo.

• Tamaño: la complejidad y la gran cantidad de funciones que tienen hacen que sea un software de gran tamaño, que requiere de gran cantidad de memoria para poder correr.

• Coste del hardware adicional: los requisitos de hardware para correr un DBMS por lo general son relativamente altos, por lo que estos equipos pueden llegar a costar gran cantidad de dinero.

SQLite es una herramienta de software libre, que permite almacenar información en dispositivos empotrados de una forma sencilla, eficaz, potente, rápida y en equipos con pocas capacidades de hardware, como puede ser una PDA o un teléfono celular. SQLite implementa el estándar SQL92 y también agrega extensiones que facilitan su uso en cualquier

ambiente de desarrollo. Esto permite que SQLite soporte desde las consultas más básicas hasta las más complejas del lenguaje SQL, y lo más importante es que se puede usar tanto en dispositivos móviles como en sistemas de escritorio, sin

Page � of �10 188

Page 11: UniSubject - rodin.uca.es

necesidad de realizar procesos complejos de importación y exportación de datos, ya que existe compatibilidad al 100% entre las diversas plataformas disponibles, haciendo que la portabilidad entre dispositivos y plataformas sea transparente.

Historia de SQLite SQLite apareció en mayo del año 2000 de la mano de su creador D. Richard Hip, quién ha liberado las diferentes versiones de SQLite en base a la licencia GPL por lo que su código es de dominio público y puede ser modificado por cualquier persona. Gracias a esto, SQLite ha sido mejorada a lo largo de 7 años por un gran número de colaboradores y también ha sido migrada a diversas plataformas.

Características Estas son algunas de las características principales de SQLite:

• La base de datos completa se encuentra en un solo archivo. • Puede funcionar enteramente en memoria, lo que la hace muy rápida. • Tiene un footprint menor a 230KB. • Es totalmente autocontenida (sin dependencias externas). • Cuenta con librerías de acceso para muchos lenguajes de programación. • Soporta texto en formato UTF-8 y UTF-16, así como datos numéricos de 64 bits. • Soporta funciones SQL definidas por el usuario (UDF). • El código fuente es de dominio público y se encuentra muy bien documentado. • Plataformas de SQLite • SQLite está construida en C, lo cual facilita la migración a diversas plataformas

de sistemas operativos y de dispositivos. Dado que una base de datos de SQLite se almacena por completo en un solo archivo, está puede ser exportada a cualquier otra plataforma y tener inter-operatibilidad al 100% sin ningún requerimiento de programación adicional o cambios de configuración.

Lenguajes de Programación de SQLite Gracias a que SQLite es software libre, es posible encontrar una gran cantidad de componentes, librerías y drivers para interactuar con SQLite desde una gran diversidad de lenguajes y plataformas de programación. Ya sea que estemos utilizando lenguajes modernos como Java, Perl, Python, PHP, Ruby, C#, lenguajes más antiguos como Pascal, SmallTalk, Clipper, o lenguajes poco conocidos como Suneido, REXX, S-Lang, para todos podemos encontrar librerías y ejemplos de código para SQLite.

Veamos algunas razones para escoger SQLite como una herramienta de desarrollo:

• Tamaño: SQLite tiene una pequeña memoria y una única biblioteca es necesaria para acceder a bases de datos, lo que lo hace ideal para aplicaciones de bases de datos incorporadas.

Page � of �11 188

Page 12: UniSubject - rodin.uca.es

• Rendimiento de base de datos: SQLite realiza operaciones de manera eficiente y es más rápido que MySQL y PostgreSQL.

• Portabilidad: se ejecuta en muchas plataformas y sus bases de datos pueden ser fácilmente portadas sin ninguna configuración o administración.

• Estabilidad: SQLite es compatible con ACID, reunión de los cuatro criterios de Atomicidad, Consistencia, Aislamiento y Durabilidad.

• SQL: implementa un gran subconjunto de la ANSI – 92 SQL estándar, incluyendo sub-consultas, generación de usuarios, vistas y triggers.

• Interfaces: cuenta con diferentes interfaces del API, las cuales permiten trabajar con C++, PHP, Perl, Python, Ruby, Tcl, groovy, etc.

• Costo: SQLite es de dominio público, y por tanto, es libre de utilizar para cualquier propósito sin costo y se puede redistribuir libremente.

Puntos fuertes de SQLite Alguna de las característica más relevantes de SQLite son las siguientes:

No posee configuración De la forma en que fue creado y diseñado SQLite, NO necesita ser instalado. NO prender, reiniciar o apagar un servidor, e incluso configurarlo. Esta cualidad permite que no haya un administrador de base de datos para crear las tablas, vistas, asignar permisos. O bien la adopción de medidas de recuperación de servidor por cada caída del sistema.

Portabilidad SQLite puede ser ejecutado en diferentes sistemas operativos, como ser Windows, Linux, BSD, Mac OS X, Solaris, HPUX,AIX o estar embebido en muchos otros como QNX, VxWorks, Symbian, Palm OS, Windows CE. Se pude notar que muchos de ellos trabajan a 16, 32 y 64 Bits. La portabilidad no está dada en sí por el software, sino por la base de datos condensada en un solo fichero, que puede estar situado en cualquier directorio, trayendo como ventaja que la base de datos puede ser fácilmente copiada a algún dispositivo USB o ser enviada vía correo electrónico.

Registros de longitud variable Generalmente los motores asignan una cantidad fija de espacio en disco para cada fila en la mayoría de los campos de una determinada tabla. Por ejemplo, tomemos un campo de tipo VARCHAR(255), esto significa que el motor le asignará 255 bytes de espacio fijo en disco, independientemente de la cantidad de información que se almacene en ese campo. En cambio, SQLite aplica su tecnología y realizará todo lo contrario, utilizando para ello la cantidad de espacio en disco necesario para almacenar la información real del campo. Tomando el ejemplo anterior, si quisiera almacenar un solo carácter en un campo definido como VARCHAR(255), entonces un único byte de espacio de disco se consume.

Page � of �12 188

Page 13: UniSubject - rodin.uca.es

El uso de registros de longitud variable por SQLite, tiene una serie de ventajas, entre ellas el resultado de un pequeño archivo de base de datos y optimización de la velocidad de la misma, puesto que hay menos información desperdiciada que leer y recorrer.

Puntos débiles de SQLite Así como encontramos algunas ventajas y características realmente asombrosas, también cuenta con algunas limitaciones:

• Limitaciones en Where: esta limitación está dada por el soporte para clausuras anidadas.

• Falta de Clave Foránea: se hace caso omiso de las claves foráneas; esto quiere decir, cuando se realice la creación de la tabla desde el modo consola, está permitiendo el uso de la clausura, aunque no realizara el chequeo de la misma.

• Falta de documentación en español: si bien ya contamos con una comunidad latino americana de SQLite, sería importante encontrar mucha más documentación, libros, review, etc. como muchos otros motores de bases de datos cuentan hoy en día.

MySQL es un sistema de gestión de bases de datos relacionales (SGBDR) de código abierto que ocupa desde marzo de 2014 el segundo puesto entre los SGBD más ampliamente utilizados del mundo.

El proyecto de desarrollo de MySQL ha hecho su código accesible bajo los términos de la Licencia Pública General de GNU, así como bajo una variedad de acuerdos de propiedad. MySQL perteneció y fue patrocinado por una única empresa para fines de lucro, la compañía sueca MySQL AB, ahora propiedad de la Corporación Oracle.

MySQL es una elección popular de base de datos para su uso en aplicaciones web, y es un componente central de la ampliamente utilizada estructura de software de aplicación web de código abierto LAMP (y otras estructuras "AMP"). LAMP es un acrónimo para "Linux, Apache, MySQL, Perl/PHP/Python". Proyectos de software libre de código abierto que requieren un sistema completo de gestión de bases de datos con frecuencia utilizan MySQL.

Para uso comercial, existen varias ediciones de pago disponibles, y ofrecen funcionalidad extra. Entre las aplicaciones que utilizan bases de datos MySQL se encuentran: TYPO3, MODx, Joomla, WordPress, phpBB, MyBB, Drupal y otro software. MySQL también es utilizado en muchos sitios web de perfil alto y gran

Page � of �13 188

Page 14: UniSubject - rodin.uca.es

escala, incluyendo Google (aunque no para búsquedas), Facebook, Twitter, Flickr y YouTube.

MySQL funciona en muchas plataformas, incluyendo AIX, BSDi, FreeBSD, HP-UX, eComStation, i5/OS, IRIX, Linux, OS X, Microsoft Windows, NetBSD, Novell NetWare, OpenBSD, OpenSolaris, OS/2 Warp, QNX, Oracle Solaris, Symbian, SunOS, SCO OpenServer, SCO UnixWare, Sanos y Tru64. También existe una adaptación de MySQL a OpenVMS. MySQL está escrito en C y C++. Las principales características disponibles en MySQL 5.6 incluyen compatibilidad entre plataformas, procedimientos almacenados, disparadores, cursores, vistas actualizables, DDL online cuando se utiliza el motor de almacenamiento InnoDB, esquema de información, esquema de rendimiento, modo estricto, soporte DTP, transacciones con puntos de guardado, soporte SSL, sub-consultas, soporte para replicación, indexación y búsqueda de texto completo, biblioteca de base de datos embebida, soporte para unicode, tablas particionadas, múltiples motores de almacenamiento, etc.

MySQL también cuenta con algunas limitaciones. Como ocurre con otras bases de datos SQL, MySQL no cumple actualmente con el estándar completo de SQL para algunas de las funcionalidades implementadas, incluyendo las referencias de clave foránea cuando se utilizan algunos motores de almacenamiento que no sean el predeterminado InnoDB. Hasta MySQL 5.7, los disparadores están limitados a uno por acción/tiempo, lo que significa que como máximo un disparador puede ser definido para ejecutarse después de una operación de inserción, y uno antes de la inserción en la misma tabla. No se pueden definir disparadores en vistas. MySQL, como muchas otras bases de datos relacionales transaccionales, está fuertemente limitado por el rendimiento del disco duro. Esto es especialmente cierto en términos de latencia de escritura.

HTTP (HyperText Transfer Protocol o protocolo de transferencia de hipertexto) es el protocolo usado en cada transacción de la Web (WWW). HTTP fue desarrollado por el consorcio W3C y la IETF [17], colaboración que culminó en 1999 con la publicación de una serie de RFCs, siendo el más importante de ellos el RFC 2616 [18], que especifica la versión 1.1. HTTP define la sintaxis y la semántica que

utilizan los elementos software de la arquitectura web (clientes, servidores, proxies) para comunicarse. Es un protocolo orientado a transacciones y sigue el esquema petición-respuesta entre un cliente y un servidor. Al cliente que efectúa la petición (un navegador o un spider) se lo conoce como "user agent" (agente del usuario). A la información transmitida se la llama recurso y se la

Page � of �14 188

Page 15: UniSubject - rodin.uca.es

identifica mediante un URL. Los recursos pueden ser archivos, el resultado de la ejecución de un programa, una consulta a una base de datos, la traducción automática de un documento, etc.

HTTP es un protocolo sin estado, es decir, que no guarda ninguna información sobre conexiones anteriores, sin embargo, el desarrollo de aplicaciones web necesita frecuentemente mantener estado. Para esto se usan las cookies, que es información que un servidor puede almacenar en el sistema cliente. Esto le permite a las aplicaciones web instituir la noción de sesión, y también permite rastrear usuarios ya que las cookies pueden guardarse en el cliente por tiempo indeterminado.

El formato de las peticiones HTTP se puede ver en la Globalmente están formadas por 3 campos principales:

• Request Line - Indica el método utilizado. • Header Line – Cabeceras incluidas. • Entity Body – El cuerpo del mensaje. Entre el cuerpo y los 2 campos anteriores

se incluye una línea en blanco.

HTTP define 8 métodos para realizar determinadas acciones, de los cuales 3 son los más usados:

• HEAD - Solicita una representación del recurso solicitado, pero sin el cuerpo del mensaje

• GET – Solicita una representación del recurso solicitado con el cuerpo del mensaje incluido

• POST – Envía información para que sea procesada en el recurso identificado. La información se incluye en el cuerpo de la petición

Page � of �15 188

Page 16: UniSubject - rodin.uca.es

Puntos fuertes de HTTP HTTP es un protocolo sin estado, lo que permite que los hosts no tengan la necesidad de retener información entre peticiones. Permite conexiones seguras Permite conexiones persistentes, mediante las cuales se reduce el tiempo de espera ya que el cliente no debe renegociar la conexión TCP después de la primera petición enviada.

Puntos débiles de HTTP El hecho de que sea un protocolo sin estado es un inconveniente para los desarrolladores web que deben pensar en maneras alternativas de mantener el estado de las sesiones. Una de las maneras más utilizadas es mediante el uso de cookies. Dicho método también deja al descubierto determinados agujeros de seguridad. Las conexiones seguras son eficaces contra fisgones pero no con ataques del estilo man-in-the-middle. HTTP sólo protege los datos durante el tránsito, una vez en la máquina de destino, dependerá de la máquina su seguridad.

Partiendo con la noción de que el Hypertext Transfer Protocol o HTTP o Protocolo de Transferencia de Hipertexto es el protocolo que se usa en cada transacción de datos en la web, viene a aparecer esa letra “S” en el HTTPS que mas de alguno hemos visto en nuestros navegadores mas recientes. Pues HTTPS viene a ser el

Protocolo Seguro de Transferencia de Hipertexto y está obviamente basado en el antes mencionado HTTP pero con la particularidad de utilizar un cifrado basado en la Secure Socket Layers mas conocidas como SSL y así crear un canal de transferencia cifrado con el que obviamente aumenta la seguridad en el tráfico de información en comparación al protocolo HTTP común Este protocolo HTTPS es usado por los entidades bancarias pues la información que manejan es de suma confidencialidad e importancia y por ello se necesita mantener cifrado el canal de transferencia. Últimamente se ha mejorado la seguridad no solo en servicios web bancarios sino en servicios que usuarios como nosotros usamos día a día como lo son nuestras cuentas de correo (Hotmail, Gmail, Yahoo Mail), nuestras cuentas hacia redes sociales como Twitter y Facebook entre otros sitios comunmente visitados por la mayoría de la gente que navega por internet.

Page � of �16 188

Page 17: UniSubject - rodin.uca.es

Entonces como funciona el HTTPS? Pues es sencillo pues el navegador que estemos utilizando actua como la entidad que nos señala si el sitio que estamos visitando está correctamente cifrado y de ser así a nombre de quien está el certificado SSL antes mencionado por lo que estamos confiando en la información de seguridad que nos da nuestro navegador de internet y por lo tanto sabremos que no se trata de algún sitio falsificado que podría tratar de robar nuestros datos o credenciales por lo que entonces podríamos concluir en la sentencia de que el protocolo HTTPS nos sirve para cifrar la transferencia de hypertexto y por lo tanto mejora nuestra seguridad y la de nuestros datos.

Funcionamiento de HTTPS

PHP es un lenguaje de programación interpretado, diseñado originalmente para la creación de páginas web dinámicas, ya que puede ser embebido dentro de código HTML. Es usado principalmente en interpretación del lado del servidor (server-side scripting), tomando código en PHP como entrada y sirviendo páginas web en la salida. Mediante extensiones es también posible la

generación de archivos PDF, Flash, así como imágenes en diferentes formatos . Mientras que PHP fuer originalmente creado por Rasmus Lerdorf en 1995, la principal implementación de PHP la produce The PHP Group y sirve como estándar de facto para PHP, ya que este no posee una especificación oficial.

Page � of �17 188

Page 18: UniSubject - rodin.uca.es

El gran parecido que posee PHP con los lenguajes más comunes de programación estructurada, como C y Perl, permiten a la mayoría de los programadores crear aplicaciones complejas con una curva de aprendizaje muy corta.

Aunque todo en su diseño está orientado a facilitar la creación de página web, es posible crear aplicaciones con una interfaz gráfica para el usuario, utilizando la extensión PHP-Qt o PHP-GTK. También puede ser usado desde la línea de comandos, de la misma manera como Perl o Python pueden hacerlo, a esta versión de PHP se la llama PHP CLI (Command Line Interface).

Permite la conexión a diferentes tipos de servidores de BBDD tales como MySQL, Postgres, Oracle, ODBC, DB2, Microsoft SQL Server, Firebird y SQLite. PHP también tiene la capacidad de ser ejecutado en la mayoría de los sistemas operativos, tales como UNIX (y de ese tipo, como Linux o Mac OS X) y Windows, y puede interactuar con los servidores de web más populares ya que existe en versión CGI, módulo para Apache, e ISAPI.

Código PHP embebido dentro de código HTML

Puntos fuertes de PHP • Es un lenguaje multiplataforma. • Capacidad de conexión con la mayoría de los gestores de base de datos que se

utilizan en la actualidad, destaca su conectividad con MySQL. • Capacidad de expandir su potencial utilizando la enorme cantidad de módulos

(llamados extensiones). • Posee una amplia documentación en su página oficial, entre la cual se destaca

que todas las funciones del sistema están explicadas y ejemplificadas en un único archivo de ayuda.

• Es libre, por lo que se presenta como una alternativa de fácil acceso para todos. • Permite técnicas de Programación Orientada a Objetos.

Page � of �18 188

Page 19: UniSubject - rodin.uca.es

• Biblioteca nativa de funciones sumamente amplia e incluida. • No requiere definición de tipos de variables. • Tiene manejo de excepciones (desde PHP5).

Puntos débiles de PHP PHP presenta bastantes problemas de seguridad debidos principalmente a vulne rabilidades causadas por no prese ntar un esq uema o reglas de programación adecuadas. Además, hay que añadir las vulnerabilidades causadas debido a aplicaciones escritas en versiones de PHP antiguas.

Por otro lado, PHP es un lenguaje del tipo weakly-typed, es decir, que implícitamente convierte los tipos de las variables cuando las usa. Esto provoca que no se sepa con seguridad que resultado se obtendrá al tratar con datos de diferentes tipos en la misma sentencia.

XML, siglas en inglés de eXtensible Markup Language (lenguaje de marcas ampliable), es un metalenguaje extensible de etiquetas desarrollado por el World Wide Web Consortium (W3C). Es una simplificación y adaptación del SGML y permite definir la gramática de lenguajes específicos (de la misma manera que HTML es a su vez un lenguaje definido por SGML). Por lo tanto XML no es realmente un lenguaje en particular, sino una manera de definir lenguajes para diferentes

necesidades. Algunos de estos lenguajes que usan XML para su definición son XHTML, SVG, MathML. XML 1.0 se convirtió en una recomendación del W3C el 10 de febrero de 1998.

XML no ha nacido sólo para su aplicación en Internet, sino que se propone como un estándar para el intercambio de información estructurada entre diferentes plataformas. Se puede usar en bases de datos, editores de texto, hojas de cálculo y casi cualquier cosa imaginable. Tiene un papel muy importante en la actualidad ya que permite la compatibilidad entre sistemas para compartir la información de una manera segura, fiable y fácil.

Puntos fuertes de XML • Permite separar contenido de presentación. • Es extensible mediante la adición de nuevas etiquetas. • El analizador es un componente estándar, no es necesario crear un analizador

específico para cada lenguaje. Esto posibilita el empleo de uno de los tantos disponibles. De esta manera se evitan bugs y se acelera el desarrollo de la aplicación.

Page � of �19 188

Page 20: UniSubject - rodin.uca.es

• Si un tercero decide usar un documento creado en XML, es sencillo entender su estructura y procesarlo. Mejora la compatibilidad entre aplicaciones.

Puntos débiles de XML • XML no es especialmente bueno manejando grandes cantidades de datos • XML se vuelve complicado de entender si hay mucha información en un solo

documento • Ciertos tipos de información (imágenes, otros tipos de información binaria) no

están muy bien representados en XML.

CONCEPTOS SOBRE ANDROID Una plataforma de software es un elemento crucial en el desarrollo del mismo. Mediante el marco de trabajo que proporcionan las plataformas se puede crear nuevo software y que este se pueda ejecutar sobre ellas. Las plataformas de desarrollo típicas incluyen una arquitectura de computadores, un sistema operativo (S.O.), lenguajes de programación y sus correspondientes librerías o interfaces gráficas (user interface o UI)

Estructura de capas

Las plataformas son comúnmente mencionadas con las APIs (funciones y métodos que ofrece una biblioteca para ser utilizada por otro software como una capa de abstracción). Un conjunto completo de APIs constituye una plataforma software. Estas plataformas son normalmente dependientes de los sistemas operativos aunque existen otras en las que no es así.

Java es un ejemplo de plataforma no dependiente del S.O. debido a que Java es tanto el lenguaje como la plataforma de desarrollo, la cual incluye la Java Virtual Machine (JVM) cuya función es interpretar el bytecode resultante de la compilación del código fuente del programa en Java.

Page � of �20 188

Page 21: UniSubject - rodin.uca.es

Android es una plataforma de software y un sistema operativo para dispositivos móviles basada en un kernel Linux, desarrollada por Google y más tarde por la Open Handset Alliance. Esta plataforma permite a los desarrolladores escribir código en Java que se ejecuten en móviles mediante las librerías Java desarrolladas por Google. También se pueden escribir aplicaciones en otros lenguajes, como por ejemplo C, para posteriormente ser compiladas en código nativo ARM y ejecutarlas, aunque este proceso de desarrollo no está soportado oficialmente por Google. La

mayor parte de la plataforma de Android está disponible bajo licencia de software libre de Apache y otras licencias de código abierto.

Es una solución completa de software de código libre para teléfonos y dispositivos móviles. Es un paquete que engloba un sistema operativo, un "runtime" de ejecución basado en Java, un conjunto de librerías de bajo y medio nivel y un conjunto inicial de aplicaciones destinadas al usuario final (todas ellas desarrolladas en Java). Android se distribuye bajo una licencia libre permisiva (Apache) que permite la integración con soluciones de código propietario.

Desde 2011 Android tiene la base instalada más grande entre todos los sistemas operativos móviles y desde 2013 los dispositivos Android venden más que los dispositivos Windows, iOS y Mac OS combinados. Desde julio de 2013 la tienda Google Play tiene más de 1 millón de aplicaciones Android publicadas y más de 50 billones de aplicaciones descargadas. Una encuesta realizada a los desarrolladores entre los meses de abril y mayo de 2013 muestra que el 71% de los desarrolladores móviles desarrollan para Android.

El código fuente de Android fue publicado por Google bajo licencias de código abierto, aunque la mayoría de los dispositivos Android incluyen en última instancia una combinación de código abierto y software propietario. Inicialmente desarrollado por Android Inc. con el respaldo económico Google, que lo compró en 2005. Android fue revelado en 2007, junto a la fundación de la Open Handset Alliance (OHA), un consorcio de hardware, software y las empresas de telecomunicaciones dedicada a la promoción de estándares abiertos para dispositivos móviles.

La naturaleza abierta del sistema Android ha alentado a una gran comunidad de desarrolladores y entusiastas para que utilicen el código abierto como base para proyectos impulsados por la comunidad, que añadan nuevas características para usuarios avanzados o lleven Android a los dispositivos que fueron lanzados inicialmente funcionando con otros sistemas operativos.

Page � of �21 188

Page 22: UniSubject - rodin.uca.es

La Historia de Android En Julio de 2005, Google adquirió Android, Inc, una pequeña startup de California. En esos momentos, la compañía se dedicaba a la creación de software para teléfonos móviles. Una vez en Google, el equipo desarrolló un S.O. basado en Linux para dispositivos móviles. Más adelante, Google adaptó su buscador y sus aplicaciones para su uso en móviles. En septiembre del 2007, Google tenía varias patentes de aplicaciones sobre el área de la telefonía móvil. El 5 de noviembre del mismo año, se anunció la fundación de la Open Handset Alliance al mismo tiempo que la creación de la plataforma Android. La Open Handset Alliance está formada por un consorcio de 34 compañías de hardware, software y telecomunicaciones, entre las cuales se incluyen Google, HTC, Intel y Motorola entre otras, dedicadas a investigar estándares abiertos para dispositivos móviles. El primer teléfono en el mercado que posee Android es el T-Mobile G1 (también conocido como Dream), lanzado el día 22 de octubre de 2008 que viene con la versión Android 1.0 preinstalada. Este móvil es el resultado conjunto de T-Mobile, HTC y Google. Por último, desde el 21 de octubre de 2008, Android está disponible como código abierto Gracias a esto, cualquiera puede añadir extensiones, nuevas aplicaciones o reemplazar las existentes por otras dentro del dispositivo móvil

Características de Android • Amplia variedad de diseños (VGA, librerías de gráficos 2D y 3D...) • Almacenamiento de datos en BBDD SQLite • Conectividad (GSM/EDGE, CDMA, EV-DO, UMTS, Bluetooth y Wi-Fi) • Mensajería (SMS y MMS) • Navegador Web • Máquina virtual de Java • Las aplicaciones escritas en Java pueden ser compiladas y ejecutadas en la

maquina virtual de Dalvik, la cual es una especializada máquina virtual diseñada para uso en dispositivos móviles.

• Soporte de formatos (MPEG-4, H.264, MP3, AAC, OGG, AMR, JPEG, PNG,GIF)

• Soporte para hardware adicional (cámaras de video, pantallas táctiles, GPS, acelerómetros...)

• Entorno de desarrollo (emulador, herramientas de depuración, perfiles de memoria y funcionamiento, plugin para Eclipse IDE)

Page � of �22 188

Page 23: UniSubject - rodin.uca.es

Arquitectura de Android La arquitectura interna de la plataforma Android, está básicamente formada por 4 componentes: aplicaciones, armazón de aplicaciones, librerías y kernel/Linux, como se muestra en la siguiente gráfica por orden ascendente:

Gráfica 1. Arquitectura android

Un núcleo o kernel (de la raíz germánica Kern) es un software que constituye la parte más importante del sistema operativo. Es el principal responsable de facilitar a los distintos programas acceso seguro al hardware de la computadora o en forma básica, es el encargado de gestionar recursos, a través de servicios de llamada al sistema.

Kernel linux versión 2.6 que sirve como base de la pila de software y se encarga de las funciones más básicas del sistema: gestión de drivers, seguridad, comunicaciones, etc.

Capa de bibliotecas de Android incluye un set de librerías C/C++ usadas por varios componentes del sistema. Estas capacidades se exponen a los desarrolladores a través del framework de aplicaciones de Android, el cual interactúa con las librerías mediante JNI (Java Native Interface). Algunas son: System C library (implementación librería C estándar), librerías de medios, librerías de gráficos, 3d, SQLite, entre otras.

Runtime de Android incluye un set de librerías base que proveen la mayor parte de las funcionalidades disponibles en las librerías base del lenguaje de programación Java. Cada aplicación Android corre su propio proceso, con su propia instancia de la máquina virtual Dalvik. Dalvik ha sido escrito de forma que un dispositivo puede

Page � of �23 188

Page 24: UniSubject - rodin.uca.es

correr múltiples máquinas virtuales de forma eficiente. Dalvik ejecuta archivos en el formato Dalvik Executable (.dex), el cual está optimizado para memoria mínima.

Framework para el desarrollo de aplicaciones, dividido en subsistemas para la gestión del sistema. Los desarrolladores tienen acceso completo a los mismos APIs del framework usados por las aplicaciones base. La arquitectura está diseñada para simplificar la reutilización de componentes; cualquier aplicación puede publicar sus capacidades y cualquier otra aplicación puede luego hacer uso de esas capacidades. Éste mismo mecanismo permite que los componentes sean reemplazados por el usuario. También incluye un sistema de vistas para manejar el interfaz de usuario de las aplicaciones, que incluye posibilidad de visualización de mapas o renderizado html directamente en el interfaz gráfico de la aplicación.

Aplicaciones base, que incluyen un teléfono, cliente de e-mail, programa de envío de SMS, calendario, mapas, navegador, contactos... que pueden a su vez ser usados por otras aplicaciones.

Las aplicaciones Android están programadas en Java, pero no corriendo sobre Java ME, sino sobre Dalvik, una máquina virtual Java desarrollada por Google y optimizada para dispositivos empotrados. La creación de una VM propia es un movimiento estratégico que permite a Google evitar conflictos con Sun por la licencia de la máquina virtual, así como asegurarse el poder innovar y modificar ésta sin tener que batallar dentro del JCP.

Cada aplicación Android corre su propio proceso, con su propia instancia de la máquina virtual Dalvik. Dalkiv ha sido escrito de forma que un dispositivo puede correr múltiples máquinas virtuales de forma eficiente.

Page � of �24 188

Page 25: UniSubject - rodin.uca.es

Figura 1. Versiones android

Android SDK El kit de desarrollo de software (software development kit o SDK) incluye un conjunto de herramientas de desarrollo, tales como un debugger, librerías, un emulador (basado en QEMU), documentación, código de ejemplo y tutoriales. Está soportado en S.O. Windows, Linux y Mac. El entorno de desarrollo (integrated development environment o IDE) oficialmente soportado es Eclipse conjuntamente con el plugin ADT proporcionado por Google. Desde noviembre del 2007 a septiembre del 2008 han ido surgiendo nuevas actualizaciones del SDK siendo la última la 1.0, la cual soluciona algunos errores de las anteriores y añade nuevas funcionalidades y cambios en las APIs.

Page � of �25 188

Page 26: UniSubject - rodin.uca.es

Anatomía de una aplicación de Android Dentro de una aplicación de Android hay cuatro componentes principales: Activitity, Listeners, Servicios y Content Provider. Todas las aplicaciones de Android están formadas por algunos de estos elementos o combinaciones de ellos

Activity Las Activities (o Actividades) son el elemento constituyente de Android más común. Para implementarlas se utiliza una clase por cada Actividad que extiende de la clase base Activity. Cada clase mostrará una interfaz de usuario, compuesta por Views (o Vistas). Cada vez que se cambie de Vista, se cambiará de Actividad, como por ejemplo en una aplicación de mensajería que se tiene una Vista que muestra la lista de contactos y otra Vista para escribir los mensajes. Cuando cambiamos de Vista, la anterior queda pausada y puesta dentro de una pila de historial para poder retornar en caso necesario. También se pueden eliminar las Vistas del historial en caso de que no se necesiten más.

Intents Un Intent es un objeto mensaje y que, en general, describe que quiere hacer una aplicación. Las dos partes más importantes de un Intent son la acción que se quiere realizar y la información necesaria que se proporciona para poder realizarla, la cual se expresa en formato URI. Un ejemplo seria ver la información de contacto de una persona, la cual mediante un Intent con la acción ver y la URI que representa a esa persona se podría obtener.

Relacionado con los Intents hay una clase llamada IntentFilter que es una descripción de que Intents puede una Actividad gestionar. Mediante los IntentFilters, el sistema puede resolver Intents, buscando cuales posee cada actividad y escogiendo aquel que mejor se ajuste a sus necesidades. El proceso de resolver Intents se realiza en tiempo real, lo cual ofrece dos beneficios:

• Las actividades pueden reutilizar funcionalidades de otros componentes simplemente haciendo peticiones mediante un Intent.

• Las actividades pueden ser remplazadas por nuevas actividades con IntentFilters equivalentes.

Listeners Los Listeneres se utilizan para reaccionar a eventos externos (por ejemplo, una llamada). Los Listeners no tienen UI pero pueden utilizar el servicio NotificationManager para avisar al usuario. Para lanzar un aviso no hace falta que la aplicación se esté ejecutando, en caso necesario, Android la iniciará si se activa el Listeners por algún evento.

Servicios Un Servicio es básicamente un código que se ejecuta durante largo tiempo y sin necesidad de UI, como puede ser un gestor de descarga en el cual se indican los

Page � of �26 188

Page 27: UniSubject - rodin.uca.es

contenidos a descargar y posteriormente el usuario puede acceder a una nueva Vista sin que el gestor se interrumpa.

En caso de que haya múltiples servicios a la vez, se les puede indicar diferentes prioridades según las necesidades.

Content Provider En Android, las aplicaciones pueden guardar su información en ficheros, BBDD SQLite... Pero en caso de que lo que se quiera sea compartir dicha información con otras aplicaciones, lo necesario es un Content Provider. Un Content Provider es una clase que implementa un conjunto estándar de métodos que permite a otras aplicaciones guardar y obtener la información que maneja dicho Content Provider.

Android Manifiest En Android existe un archivo XML llamado AndroidManifest que, aunque no forme parte del código principal de la aplicación, es necesario para su correcto funcionamiento. Este archivo es el fichero de control que le dice al sistema que tiene que hacer con todos los componentes anteriormente mencionados en este apartado que pertenecen a una aplicación en concreto.

Tipos de aplicación de Android Un Android Package (.apk) es el fichero que contiene el código de la aplicación y sus recursos, y que posteriormente se instala en el dispositivo para poder ejecutar la aplicación.

Tareas Una tarea en Android es lo que el usuario ve como una aplicación y el desarrollador ve como una o más Actividades donde el usuario interactuar y va pasando de Vista en Vista. Dentro de las tareas, una actividad toma el papel de punto de entrada (será la primera en mostrarse cuando se ejecute la aplicación) y las demás, si hay, formarán parte de la misma tarea, a la espera de ser instanciadas.

Procesos En Android, los procesos se ejecutan a nivel de kernel y el usuario normalmente no tiene constancia de ellos. Todo el código de la aplicación se suele ejecutar en un proceso dedicado pero también se puede especificar si sólo se quiere que se ejecute en el proceso una determinada clase o componente de la aplicación. Los principales usos de los procesos son:

• Mejorar la estabilidad o seguridad de las aplicaciones. • Reducir la sobrecarga de proceso ejecutando el código de múltiples aplicaciones

en el mismo proceso. • Ayudar al sistema a gestionar los recursos separando partes de código

Page � of �27 188

Page 28: UniSubject - rodin.uca.es

• pesado en un proceso separado que puede ser eliminado independientemente de otras partes de la aplicación.

Threads En lo referente a threads, Android evita la creación de threads adicionales por parte de un proceso, manteniendo la aplicación en un sólo thread al menos que no los cree la propia aplicación. Esto repercute de manera importante en las llamadas a instancias a Actividades, Listeners y Servicios, ya que sólo pueden ser hechas por el thread principal del proceso en el que están corriendo.

Por otro lado, al no crearse un thread por cada instancia, dichas instancias no deben realizar operaciones largas o bloqueantes cuando son llamadas, de lo contrario, bloquearían todos los demás componentes del proceso.

Ciclo de vida de una aplicación de Android Cada aplicación de Android corre en su propio proceso, el cual es creado por la aplicación cuando se ejecuta y permanece hasta que la aplicación deja de trabajar o el sistema necesita memoria para otras aplicaciones.

Una característica fundamental de Android es que el ciclo de vida de una aplicación no está controlado por la misma aplicación sino que lo determina el sistema a partir de una combinación de estados como pueden ser que aplicaciones están funcionando, que prioridad tienen para el usuario y cuanta memoria queda disponible en el sistema. De esta manera, Android sitúa cada proceso en una jerarquía de importancia basada en los estados comentados, como se puede ver a continuación.

1. Un proceso en primer plano es uno que se requiere para lo que el usuario está actualmente haciendo. Se considera en primer plano si:

• Esta ejecutándose una Actividad perteneciente a la pantalla con la que el usuario está inter actuando.

• Está ejecutando un BroadcastReceiver • Esta ejecutándose un servicio.

2. Un proceso visible es aquel que contiene una Actividad que es visible al usuario mediante la pantalla pero no en primer plano (esta pausada). Este proceso solo se eliminará en caso de que sea necesario para mantener ejecutándose los procesos en primer plano.

3. Un proceso de servicio es aquel que contiene un servicio que ha sido inicializado. No son directamente visibles al usuario y el sistema los mantendrá a no ser que no pueda servir los dos anteriores.

4. Un proceso en background es aquel que acoge una actividad que no está actualmente visible al usuario. Mientras que dichos procesos implementen bien su

Page � of �28 188

Page 29: UniSubject - rodin.uca.es

propio ciclo de vida, el sistema puede eliminarlos para dar memoria a cualquiera de los 3 servicios anteriores.

5. Un proceso vacío es aquel que no contiene ningún componente activo de ninguna aplicación. La única razón para mantener dicho proceso es para mejorar sus inicializaciones posteriores a modo de caché. Para comprender mejor el ciclo de vida de una aplicación de Android, en la Fig. 2.3 se muestra el diagrama de flujo de dicho ciclo, mencionando también los métodos que se llaman durante el transcurso del mismo.

Ciclo de vida de una aplicación en Android

Page � of �29 188

Page 30: UniSubject - rodin.uca.es

Almacenamiento Android presenta varias formas de almacenamiento de la información, las cuales, se describen en la Tabla 2.1. Es importante notar que en Android todos los datos de la aplicación son privados a esta.

Mecanismos de almacenamiento de la información en Android

Android Studio es un IDE específico para la plataforma Android, basado en el IDE para Java IntelliJ IDEA de JetBrains. Fue anunciado por Ellie Powers (jefe de producto de Google) el 16 de mayo de 2013, durante la conferencia anual para desarrolladores Google I/O. Android Studio es tá disponible para que los

desarrolladores puedan probarlo de forma gratuita. Android Studio estuvo en fase de acceso anticipado comenzando con la versión 0.1 en mayo de 2013, cuando pasó a fase beta comenzando con la versión 0.8 que fue lanzada en Junio de 2014. Android Studio ofrece algunas características y mejoras respecto a Eclipse ADT que permiten un desarrollo más rápido y productivo.

Una característica de Android Studio es que permite actualizaciones de código y renderizado de la aplicación en tiempo real. Esto permite observar cómo se verá la aplicación al mismo tiempo que se realizan cambios en el código. El IDE también permite observar el aspecto que tendrá la aplicación en diferentes tamaños de pantalla, disponiendo de una enorme biblioteca de dispositivos donde elegir. No solo cuenta tan solo con una gran variedad de emuladores para realizar una vista previa de la aplicación, sino que además es posible observar el diseño en varios tamaños de pantalla mientras que realizamos cambios en el mismo. Ésta es una característica muy útil para los desarrolladores que necesitan diseñar sus aplicaciones para que éstas se ajuste a un gran número de pantallas distintitas.

Para el desarrollo de aplicaciones destinadas a una audiencia internacional, Android Studio también incluye diferentes herramientas de idioma. Se puede obtener una vista

Mecanismo Descripición

Preferencias Mecanismo ligero para almacenar y recuperar parejas de claves-valor, útil para guardar preferencias

Ficheros Se pueden guardar tanto en el dispositivo como en dispositivos extraíbles

BBDD Soporte para crear BBDD SQLite privadas pertenecientes al package que las creó

Content Provider Explicado en 2.4.4

Red Uso de la red para almacenar y recuperar información

Page � of �30 188

Page 31: UniSubject - rodin.uca.es

en tiempo real sobre cómo la aplicación funciona en diferentes idiomas, pudiendo comprobar cómo los cambios en el texto afectan a otros elementos de la aplicación cuando el idioma cambia. También cuenta con un conjunto de herramientas de análisis que ayudan a completar el código y lo analiza antes de lanzarlo. La API de Android, por ejemplo, está marcada con más información sobre qué rutinas podrían devolver un puntero nulo. Android Studio utiliza esto para intentar resaltar errores potenciales si el desarrollador olvida capturar las excepciones.

Una desventaja de Android Studio es que requiere conexión a Internet durante la mayor parte del tiempo. Por ejemplo, cuando un nuevo proyecto es creado se descargan algunos paquetes Gradle a través de Internet (ya que Android Studio está fuertemente integrado con Gradle). Esto puede suponer un problema para los desarrolladores que tienen una conexión lenta o cuando se experimentan problemas de conexión. Sin embargo, Android Studio es más prometedor que Eclipse, ya que Google tiene planeado añadirle nuevas características. La compañía quiere integrar más y más servicios en Android Studio en el futuro. A pesar de que aún está en desarrollo y no es adecuado para desarrollar proyectos importantes, ya que algunas características aún están sin finalizar y pueden provocar errores, en el futuro Android Studio será el mejor entorno de desarrollo para Android.

Sistema de construcción Tengo que decir que no tengo gran experiencia con este sistema de construcción pero hay varias características que me gustan bastante:

• Utiliza un DSL (Lenguaje Específico de Dominio) basado en Groovy (nada de XMLs complejos).

• Nos permite añadirlo a nuestros servidores de integración continua • Construcción por convención (al estilo Maven) • Compatible con dependencias Maven

Ayudas para la codificación Cuando te haces con el manejo descubres que el editor de código de Android Studio tiene unas características únicas que facilitan considerablemente el desarrollo. La edición es más fluida, la refactorización más potente y un análisis de código que nos ayudará a mejorar considerablemente nuestro código.

Hay que decir que muchas de las características del IDE Android Studio ya estaban incluidas en IntelliJ IDEA pero de ahora en adelante hablaremos de Android Studio.

Previsualización de recursos Una de las características que más me gustan es la de poder previsualizar los recursos. Por ejemplo si estamos en un drawable, podemos poner el cursor sobre el

Page � of �31 188

Page 32: UniSubject - rodin.uca.es

identificador, pulsar Ctrl + Q (comando para ver la documentación) y visualizar de un plumazo los drawables a distintos recursos

Algo parecido ocurre con los colores en el editor XML. Si ponemos un color nos aparecerá en la parte izquierda dicho color y al pulsar sobre él se nos mostrará un selector de color.

Generación de recursos Android Studio incluye diálogos para facilitar la generación de recursos para distintas configuraciones. Uno de los mejores ejemplos es a la hora de crear un string. Podemos seleccionar el cualificador de región y se nos mostrará una lista de países que podemos ir seleccionando. Esto resulta tremendamente útil porque incorpora todos los cualifiadores con sus variantes así que no tendremos que recordarlos de memoria

Generación de recursos

Page � of �32 188

Page 33: UniSubject - rodin.uca.es

Detección de errores Este IDE incorpora de forma transparente una herramienta de análisis de código que nos ayuda a mejorar la calidad del mismo. Además se realiza de forma automática, de forma que conforme vas escribiendo te va indicando posibles fallos o mejoras que puedes corregir en el código. Métodos sin utilizar, lógica demasiado compleja o condiciones que nunca van a darse serán detectadas por el IDE y nos permitirá con un “par de clicks” corregir dichos problemas. Además este sistema de análisis lo han personalizado para que trabaje también sobre partes específicas de Android. Por ejemplo, el método getSystemService recibe un String como parámetro, así que en principio podríamos poner cualquier cadena. Si hacemos esto, el entorno nos mostrará un aviso de los posibles valores que deberían pasarse a dicho método.

Refactorización La refactorización es mucho más potente en Android Studio. Ahora podemos cambiar el nombre de una imagen y automáticamente se cambiará el nombre del identificador. A la inversa funcionaría exactamente igual. IntelliJ posee un sistema de refactorización muy avanzado y Android Studio se beneficia de eso.

Ayudas para el diseño La parte de diseño es quizás la que pueda quedarse algo más corta con respecto al IDE anterior. No obstante es una herramienta con muchas posibilidades y que en el estado actual cubre la mayoría de las opciones de las que disponíamos antes e incluye cosas que mejoran lo anterior. La previsualización de los layouts está bastante cuidada, marcando los elementos sobre los que estamos trabajando y permitiendo elegir entre distintos dispositivos, configuraciones, temas, etc.

Ayudas para el diseño

Page � of �33 188

Page 34: UniSubject - rodin.uca.es

El Global Positioning System (GPS) es un sistema de navegación por satélite basado en el espacio que proporciona la posición y la hora bajo cualquier condición climática, en cualquier lugar o periferia de la Tierra donde exista una línea de visión sin obstrucciones hasta cuatro o más satélites GPS. El sistema proporciona importantes capacidades a usuarios militares, civiles y comerciales en todo el mundo. Se trata de una red de 27 satélites que es mantenida por el gobierno de Estados Unidos y es de libre

acceso para cualquier persona con un receptor GPS. Un receptor GPS calcula su posición sincronizando de forma precisa las señales enviadas por los satélites GPS desde gran altura sobre la Tierra. Cada satélite transmite continuamente mensajes que contienen el momento en el cual el mensaje fue transmitido y la posición del satélite en el momento de la transmisión. El receptor utiliza los mensajes recibidos para determinar el tiempo de transito de cada mensaje y calcula de forma aproximada la distancia hasta cada satélite, utilizando la velocidad de la luz para realizar el cálculo. Cada una de estas distancias y posiciones de los satélites define una esfera. El receptor está en la superficie de cada una de estas esferas cuando las distancias y las posiciones de los satélites son correctas. Estas distancias y posiciones de los satélites son utilizadas para calcular la posición del receptor utilizando las ecuaciones de navegación. El receptor GPS se enlaza con un satélite y calcula la distancia 'x'. Este dato ayuda a reducir el rango de posiciones posibles del receptor, pero solo nos indica que estamos en alguna parte dentro de una esfera centrada en el satélite con un radio igual a la distancia 'x'. Muchas de estas posibles posiciones no se encuentran en la Tierra, sino en el espacio.

Google Maps Con Google Maps podemos ver los mapas de casi todo el mundo y también podemos buscar lugares y ver su ubicación: Una de las funcionalidades propias de Google Maps es poder insertar un mapa personalizado en tu sitio web o aplicación móvil . Hace falta para esto utilizar un código HTML proporcionado por la aplicación de cartografía de Google. Para las empresas, es también un medio de

comunicarse alrededor de informaciones localizadas.

Algunos de los servicios que ofrece google map:

Page � of �34 188

Page 35: UniSubject - rodin.uca.es

Visita cualquier ciudad del mundo Usa la tecnología de Satélite y Street View para volver a los sitios en los que ya hayas estado o para descubrir aquellos a los que siempre has querido ir.

Disfruta de los sitios más emblemáticos Con Art Project, podrás pasear por el Palacio de Versalles, recorrer los pasillos de la Casa Blanca, entrar en el Museo Nacional de Tokio y mucho más.

Dale un respiro a tus dedos Guarda las direcciones de casa y del trabajo en Google Maps y se rellenarán automáticamente para que puedas hacer búsquedas más rápidas. También puedes permitir que la aplicación Google Maps acceda a los contactos de Android y iPhone para consultar rápidamente las direcciones guardadas.

Comparte tus opiniones No escatimes en elogios cuando escribas una reseña sobre un sitio que te encanta, valora también aquellos que no te gusten, añade tus propias fotos y controla tu actividad en cada paso del camino.

Nosotros vamos a centrarnos en es servicio de localizar sitios en Google Map utilizando la dirección. Para no hacemos el calculo del GPS he utilizado el Google Map que ya proporciona dicha servicio. Al registrar una universidad o facultad en el sistema su dirección es solicitado por el sistema. Al proporcionarlo la aplicación hacer una solicitud al servicio Google que facilitar como respuesta las lineas de longitud y latitud que corresponde a la dirección dado. El sistema utiliza las lineas de longitud y latitud para marcar la dirección en Google Map. Así que, a simple vista el usuario puede ver el lugar donde esta situado la universidad o facultad de interés.

Figura 2 Google Map

Page � of �35 188

Page 36: UniSubject - rodin.uca.es

Capítulo 2. Planificación

En este capítulo detallaré la metodología de desarrollo empleada, las actividades que deben llevase a cabo, la estimación temporal, el calendario de desarrollo, los recursos disponibles, el estudio de los costes de dichos recursos y la gestión de los riesgos que puedan influir en el desarrollo del proyecto.

2.1 Metodologia de desarrollo

La metodología utilizada durante la elaboración del proyecto será el desarrollo iterativo e incremental, una combinación del modelo de diseño iterativo y el modelo de construcción incremental para el desarrollo de software, que consiste en agrupar un conjunto de tareas en pequeñas etapas repetitivas (iteraciones). La metodología utilizada durante la elaboración del proyecto será el desarrollo iterativo e incremental, una combinación del modelo de diseño iterativo y el modelo de construcción incremental para el desarrollo de software, que consiste en agrupar un conjunto de tareas en pequeñas etapas repetitivas (iteraciones). El modelo consta de diversas etapas de desarrollo en cada incremento, las cuales se inician con el análisis y finalizan con la instauración y aprobación del sistema.

Básicamente este modelo se basa en dos premisas: - Los usuarios nunca conocen lo que necesitan exactamente. - Durante el desarrollo, los procesos tienden a cambiar.

Los pasos claves en el proceso son comenzar con una implementación simple de los requerimientos del sistema, e iterativamente mejorar la secuencia evolutiva de versiones hasta que el sistema completo esté implementado. En cada iteración, se realizan cambios en el diseño o se agregan nuevas funcionalidades y capacidades al sistema.

El proceso se compone de los siguientes elementos:

Etapa de inicialización Se crea una versión inicial del sistema. La meta de esta etapa es crear un producto con el que el usuario pueda interactuar y retroalimentar el proceso. Debe ofrecer una muestra de los aspectos claves del problema y proveer una solución lo suficientemente simple para ser comprendida e implementada fácilmente.

Lista de control del proyecto Para guiar el proceso de iteración se crea una lista de control de proyecto, que contiene un historial de todas las tareas que necesitan ser realizadas. Incluye elementos como nuevas funcionalidades para ser implementadas y áreas de rediseño

Page � of �36 188

Page 37: UniSubject - rodin.uca.es

de la solución ya existente. Esta lista de control se revisa periódica y constantemente como resultado de la fase de análisis.

Etapa de iteración La iteración implica el rediseño e implementación de una tarea de la lista de control del proyecto, así como el análisis de la versión más reciente del sistema. La implementación de cada iteración debe ser simple, directa y modular, para soportar el rediseño o la inclusión de una tarea añadida a la lista de control del proyecto. El análisis de una iteración se basa en la retroalimentación del usuario y en el análisis de las funcionalidades disponibles del programa, así como en las dificultades encontradas durante el diseño, la codificación o las pruebas de una modificación. Se trata de un análisis de la estructura, modularidad, facilidad de uso, fiabilidad, eficiencia y cumplimiento de las metas. La lista de control del proyecto se modifica según los resultados del análisis.

Cada ciclo de la etapa de iteración se compone de las siguientes sub-fases:

Figura 2.1 - Sub-fases de la etapa de iteración

Page � of �37 188

Page 38: UniSubject - rodin.uca.es

2.2 Planificación del proyecto

2.2.1 División en tareas

Durante la realización del proyecto, se llevarán a cabo las siguientes tareas:

Tarea 1 - Adquisición de conocimientos necesarios Al comienzo del proyecto se iniciará un aprendizaje, mediante el cual el desarrollador pueda adquirir los conocimientos necesarios. Dicho aprendizaje será continuado a lo largo de todo el proceso de desarrollo.

Tarea 2 - Estudio sobre el estado actual Se analizará el estado actual del mercado y la tecnología empleada para realizar el proyecto. Se realizará una comparación entre los sistemas existentes y lo que aporta nuestro proyecto al campo en el cual compite.

Tarea 3 - Planificación Se realizará una planificación inicial, a partir de la cual se llevará a cabo la etapa de inicialización. Posteriormente, al inicio de cada iteración se realizará una nueva planificación, donde se decidirán las nuevas tareas a realizar en función de los resultados de la última evaluación del sistema. A través de la planificación se obtendrá la lista de control del proyecto.

Tarea 4 - Desarrollo de una sistema que cumpla el propósito del proyecto Se iniciará el desarrollo con la etapa de inicialización, que dará lugar a una versión temprana del sistema mediante una primera iteración. A partir de la versión inicial se irán creando versiones incrementales, añadiendo nuevas funcionalidades en cada iteración, según las tareas que compongan la lista de control del proyecto.

Tarea 5 - Evaluación de la aplicación y el grado de cumplimiento de los objetivos Al finalizar cada iteración se llevará a cabo una evaluación del sistema actual, las dificultades encontradas durante las sub-fases anteriores y los errores encontrados durante las pruebas realizadas. Cuando se alcance la versión completa del sistema se realizará una evaluación final, para comprobar el grado de cumplimiento de los objetivos del proyecto.

Tarea 6 - Redacción de la memoria A medida que se vaya avanzando en la realización del proyecto, se completará la presente memoria de forma paralela, que contendrá una explicación detallada del proceso de elaboración, las dificultades encontradas y cualquier aspecto relevante sobre el mismo.

Page � of �38 188

Page 39: UniSubject - rodin.uca.es

Tarea 7 - Preparación de la defensa Cuando el proyecto adquiera un grado de madurez suficiente para su exposición ante el tribunal, se preparará cualquier material que intervenga en la defensa, se realizarán pruebas y se ultimará cualquier detalle que influya en la entrega final.

Tarea 8 - Reuniones Durante la elaboración del proyecto se acordarán diversas reuniones con el tutor, para obtener orientación sobre los diversos aspectos que componen el trabajo a realizar. También podrían llevarse a cabo reuniones con otros profesores para solucionar dudas específicas.

2.2.2 Estimación temporal Como gran parte de las actividades de planificación, aprendizaje y evaluación se llevan a cabo durante la actividad de desarrollo, el tiempo necesario para llevar a cabo dichas partes se tratará como tiempo de dicha actividad. Así pues, para la actividad de planificación solo se tendrá en cuenta la planificación inicial, para la actividad de adquisición de conocimientos solo se tendrá en cuenta el aprendizaje previo al desarrollo y para la actividad de evaluación solo se tendrá en cuenta la evaluación final del grado de cumplimiento de los objetivos. Las partes faltantes de dichas actividades, como ya se ha indicado, se tendrán en cuenta tan solo como tiempo de la actividad desarrollo, para que no sean contabilizadas dos veces. La siguiente tabla recoge la estimación temporal para la realización del proyecto actual, dedicando 7 horas diarias a 16 días al mes al proyecto: 7 hr. x 16 días al mes = 112 hr al mes (4 días de la semana)

Tabla 2.1 - Estimación temporal

Actividad Duración Estimada en horas

Duración Real

en horas

Tarea 1 - Adquisición de conocimientos 448 672

Tarea 2 - Estudio sobre el estado actual 48 28

Tarea 3 - Planificación inicial 112 112

Tarea 4 - Desarrollo de una sistema 672 560

Tarea 5 - Evaluación de la aplicación 112 112

Tarea 6 - Redacción de la memoria 28 84

Tarea 7- Preparación de la defensa 28 28

Tarea 8 - Reuniones 28 28

Total horas 1476 1624

Page � of �39 188

Page 40: UniSubject - rodin.uca.es

2.2.3 Planificación temporal

En la siguientes páginas se muestra el diagrama de Gantt, donde se expone el tiempo de dedicación previsto para cada una de las tareas que componen la realización del proyecto. (T = Tarea)

Tabla 2.2 El Diagrama de Gantt

2.3 organización

2.3.1 Participantes Supervisor - Miembro del equipo con amplia experiencia y conocimientos que se encarga de supervisar el desarrollo del proyecto para que éste alcance un nivel adecuado de corrección y calidad.

Analista de sistemas - Miembro del equipo especializado en análisis, diseño e implementación de sistemas de información. Es el encargado de planificar el desarrollo y evaluar la idoneidad del sistema en función del resultado previsto.

Programador - Miembro del equipo que escribe, depura y mantiene el código fuente del sistema. El programador se encarga de la implementación incremental del sistema mediante diversos lenguajes de programación.

Colaboradores - Miembros externos al equipo de desarrollo que colaboran con los desarrolladores durante la fase de pruebas del sistema. Se encargan de identificar comportamientos no deseados en el sistema y notificarlos al equipo de desarrollo.

T 1 2 3 4 6 7 8 910

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

1

2

3

4

5

6 14H

14H

7

8 7H

7H

7H

7H

Page � of �40 188

Page 41: UniSubject - rodin.uca.es

2.3.2 Recursos

En este apartado se van a listar todos los recursos de hardware y software, así como las herramientas utilizadas que forman parte del inventario.

Software - Sistemas Operativos: OS X El Capiton version 10.11.3

- IDE: Android Studio. - Java 8

- Servidor: Apache 2.4

- Base de datos: MySQL 6

- Navegadores: Google Chrome, Apple Safari.

- Otros: Notes (Apple), Preview(Apple), Calendar Google, Google Map (Servicio), TextWrangler, XAMPP, Firefox, https://creately.com/

Hardware - Apple MacBook Air 13.5” - Mobil Device Samsung Galaxy Note 4 - Sistema Operativo : Android Lolipop (5.1.1) con TouchWiz UI. -Apple iPad 2nd generation (herramienta para la investigación y Adquisición de conocimientos) -Conectividad : 4G, HSPA, Bluetooth 4.0, Wi-Fi, USB 3.0, NFC, S Beam. 7,50€ hr, 60€ día, 300€ semana, 1200€ mes

2.4 Coste

En esta sección se realiza el estudio y presupuesto estimado de los costes para los recursos (humanos y materiales) necesarios para el proyecto.

Coste del Personal

Supervisor El supervisor cobrará una cantidad mensual por su supervisión y un extra por cada reunión que se realice. Este miembro cobrará 15 euros por cada hora trabajada y se estima que dedicará un 25% del tiempo necesario para realizar el proyecto en realizar su trabajo. Por lo tanto deberá trabajar 406 horas durante la elaboración del proyecto, suponiendo un coste de 6.090 euros. Su salario base mensual será de 508 euros.

Page � of �41 188

Page 42: UniSubject - rodin.uca.es

Adicionalmente, cobrará un extra de 30 euros por cada reunión que se realice. El tiempo de las reuniones se ha estimado en 24 horas durante la elaboración del proyecto, por lo tanto cobrará un extra de 720 euros, que suponen 60 euros mensuales adicionales, aumentando su salario hasta los 568 euros mensuales. El coste de la seguridad social para este miembro será el 40% de su sueldo, por lo tanto supondrá un coste de 227 euros mensuales. El coste total que supone este miembro es de 794 euros mensuales.

Analista de sistemas / Programador En nuestro proyecto, las funciones de analista de sistemas y programador las realizará la misma persona, que cuenta con las capacidades necesarias para desarrollar ambas funciones, por lo tanto no es necesaria la contratación de un segundo miembro para el equipo. Quedaría abierta la posibilidad de contratar más programadores si en un futuro la escala del proyecto aumentara, pero no lo tendremos en cuenta por el momento, al no considerarse necesario.

El miembro encargado de dichas funciones cobrará 7,50 euros por cada hora trabajada y deberá trabajar 1624 horas durante la elaboración del proyecto. Por lo tanto supondrá un coste de 12.180 euros. Su salario base mensual será de 1.015 euros, trabajando 8 horas diarias durante 12 meses.

El coste de la seguridad social para este miembro será el 40% de su sueldo, por lo tanto supondrá un coste de 406 euros mensuales. El coste total que supone este miembro es de 1.421 euros mensuales.

Colaboradores Los colaboradores no suponen un coste para la realización del proyecto, ya que se presentan voluntarios para realizar las pruebas sobre las distintas fases del sistema a cambio de ser los primeros en probarlo, sin cobrar un salario por ello.

Coste del Software Es posible realizar el proyecto utilizando únicamente software libre o gratuito, por lo tanto el software no supone coste alguno para el desarrollo del proyecto. La siguiente tabla muestra el software que podría utilizarse:

Recurso Coste

Supervisor €9528,00

Analista / Programador / Sistema Valuador €17052,00

Equipo (Ordenador Apple MacBook Air) 2.500€ / 3año = 833€ coste al proyecto

€833,00

Dispositivo Móvil 850 € / 2año = 425€ coste al proyecto €425,00

Page � of �42 188

Page 43: UniSubject - rodin.uca.es

Tabla 2.4 - Coste total del proyecto

2.5 Gestión de riesgo

En esta sección se analizan los riesgos del proyecto, indicando su posible impacto en el desarrollo y la probabilidad de ocurrencia. Una vez identificados y priorizados los riesgos, se definen los planes necesarios para reducir sus efectos o disminuir la probabilidad de que éstos ocurran.

Concepto de Riesgo El riesgo en un proyecto es un evento o condición incierta que, en caso de ocurrir, tiene un efecto positivo o negativo sobre los objetivos de dicho proyecto. Un riesgo tiene una causa y, si ocurre, una consecuencia. Los riesgos conocidos son aquellos que han sido identificados y analizados durante la planificación del proyecto. Habitualmente se gestionan los riesgos con efecto negativo, es decir, aquellos que suponen una amenaza para el éxito del proyecto.

Concepto de Gestión de Riesgos La función de la gestión de riesgos del software es identificar, estudiar y eliminar las fuentes de riesgo antes de que empiecen a amenazar la finalización satisfactoria de un proyecto software. Dependiendo del momento en que se detecta la ocurrencia del riesgo, existen cinco niveles de gestión de riesgos:

1. Control de crisis: intentar controlar los riesgos cuando ya se han convertido en problemas. 2. Arreglar cada error: reaccionar rápidamente cuando ya se ha producido el riesgo. 3. Mitigación de riesgos: planificar con antelación el tiempo que necesitaría para cubrir riesgos en caso de que ocurran, pero sin intentar eliminarlos inicialmente. 4. Prevención: crear y ejecutar, como parte del proyecto software, un plan para identificar riesgos y evitar que se conviertan en problemas. 5. Eliminación de causas principales: identificar y eliminar los factores que pueden provocar la presencia de algún tipo de riesgo.

Coste sin IVA del proyecto €27838,00

50% Ganancia para la empresa AleSoft €13919,00

Sub-Total €41757,00

21% de IVA €8768,97

Total con IVA €50525,97

Recurso Coste

Page � of �43 188

Page 44: UniSubject - rodin.uca.es

Trataremos de centrarnos en la gestión de riesgos en los dos últimos niveles, ya que los tres primeros pueden producir pérdidas para el proyecto.

Identificación de Riesgos A - Planificación - La planificación es demasiado optimista. - La planificación no incluye tareas necesarias. - El producto es más grande que el estimado y se requiere más tiempo. - Retraso en una tarea produce retrasos en cascada en las tareas dependientes.

B - Organización y gestión - El proyecto avanza con demasiada lentitud en su inicio. - Se toman decisiones técnicas que alargan la planificación.

C - Ambiente/Infraestructura de desarrollo - Las herramientas de desarrollo no proporcionan las prestaciones previstas. - Curva de aprendizaje demasiado larga para alguna herramienta utilizada.

D - Requisitos - Los requisitos varían o están mal definidos y necesitan redefinirse. - Se añaden requisitos extra que no estaban inicialmente planteados.

E - Producto - Los módulos propensos a tener errores necesitan más trabajo. - El producto no alcanza una calidad aceptable.

F - Personal - La falta de motivación y de moral reduce la productividad. - La falta de especialización necesaria requiere formación extra. - El personal trabaja más lento de lo esperado.

G - Diseño e implementación - El diseño es demasiado complejo/sencillo y debe modificarse. - Dificultad para integrar componentes desarrollados por separado.

H - Proceso - La documentación progresa más lento de lo esperado.

Análisis de Riesgos Una vez identificados los riesgos, el siguiente paso es analizar cada riesgo para determinar su impacto. Lo primero que medimos es la "exposición a riesgos", definida como la probabilidad de ocurrencia del riesgo multiplicada por la magnitud de pérdida del riesgo (impacto). Tanto la estimación de la probabilidad de ocurrencia del riesgo como de la magnitud de pérdida por la ocurrencia del riesgo se realizan de

Page � of �44 188

Page 45: UniSubject - rodin.uca.es

forma subjetiva. Sin embargo, existen varias técnicas que pueden ayudar a hacer acotar la subjetividad tanto como sea posible:

1. Solicitar la estimación de la persona más familiarizada con el sistema, o con más experiencia en proyectos parecidos. 2. Utilizar el método Delphi: varios miembros de un grupo identifican riesgos y les asignan una probabilidad de ocurrencia y una magnitud de pérdida. Estas estimaciones son discutidas por el grupo y refinadas. 3. Usar adjetivos (muy improbable, bastante improbable, improbable, probable, bastante probable, muy probable) y asignar un valor numérico a cada uno.

Para la estimación de la probabilidad del presente proyecto utilizaré la siguiente equivalencia entre adjetivos y porcentajes:

Porcentajes de probabilidades Muy improbable: 10% Bastante improbable: 30% Improbable: 40% Probable: 50% Bastante probable: 70% Muy probable: 90%

En las siguientes tablas se muestra la estimación de la exposición a riesgos:

Tipo de Riesgo

Descripción Probabilidad Magnitud(Semanal)

Exposición(Semanal)

A

La planificación es demasiado optimista.

Probable 3 1,5

La planificación no incluye tareas necesarias

Bastante improbable

2 0,6

El producto es más grande que el estimado y se requiere más tiempo

Probable 2 1

Retraso en una tarea produce retrasos en cascada en las tareas dependientes

Bastante Probable

2 1,4

B

El proyecto avanza con demasiada lentitud en su inicio.

Bastante Probable

1 0,7

Se toman decisiones técnicas que alargan la planificación.

Bastante Improbable

2 0,6

C Las herramientas de desarrollo no proporcionan las prestaciones previstas.

Muy Improbable

2 0,2

Page � of �45 188

Page 46: UniSubject - rodin.uca.es

Tabla 2.5 - Riesgos

Priorización de Riesgos Una vez identificados los riesgos, y realizada la estimación de "exposición a riesgos", el siguiente paso es priorizar los riesgos, de manera que se sepa dónde centrar el esfuerzo de la gestión de riesgos. No es preciso realizar una ordenación estricta de la lista de riesgos, ya que tal vez prefiramos priorizar algunos riesgos que producirían alguna pérdida muy grande, independientemente del lugar que ocupen en la tabla.

Curva de aprendizaje demasiado larga para alguna herramienta utilizada.

Improbable 1 0,4

D

Los requisitos varían o están mal definidos y necesitan redefinirse.

Probable 2 1

Se añaden requisitos extra que no estaban inicialmente planteados

Improbable 2 0,8

E

Los módulos propensos a tener errores necesitan más trabajo.

Probable 2 1

El producto no alcanza una calidad aceptable

Bastante Improbable

2 0,6

F

La falta de motivación y de moral reduce la productividad.

Bastante Improbable

1 0,3

La falta de especialización necesaria requiere formación extra.

Bastante Probable

2 1,4

El personal trabaja más lento de lo esperado.

Improbable 2 0,8

G

El diseño es demasiado complejo/sencillo y debe modificarse.

Probable 2 1

Dificultad para integrar componentes desarrollados por separado

Muy Improbable

1 0,1

H La documentación progresa más lento de lo esperado.

Bastante Probable

3 2,1

Tipo de Riesgo

Descripción Probabilidad Magnitud(Semanal)

Exposición(Semanal)

Page � of �46 188

Page 47: UniSubject - rodin.uca.es

Plan de Respuestas a Riesgos A continuación se construye un plan de contingencia para cada uno de los riesgos identificados en las actividades anteriores, que se han elegido como significativos para gestionarlos. El objetivo de dichos planes es minimizar la probabilidad de aparición de estos riesgos.

Riesgo 1 - La documentación progresa más lento de lo esperado. Para evitar retrasos derivados de un progreso lento en la documentación, evitaremos extendernos excesivamente en cuestiones superfluas, dedicando la mayor parte del esfuerzo a las secciones críticas para la realización del proyecto. Cuando se encuentre algún inconveniente que requiera de supervisión para ser superado, se trabajará en otras secciones mientras se espera la respuesta del supervisor, para no detener el avance de la documentación.

Se tendrán en cuenta los estándares y las recomendaciones del supervisor cuando se realice la documentación, para evitar errores que puedan producir pérdidas de tiempo o esfuerzo en repeticiones de una misma tarea.

Riesgo 2 - La planificación es demasiado optimista. La planificación se realizará de forma objetiva, llevando a cabo una estimación realista sobre el tiempo necesario para cada tarea y asumiendo las limitaciones técnicas de las herramientas utilizadas, así como las circunstancias personales de los miembros del equipo. Se deberá cumplir la planificación siempre que sea posible, para garantizar que no se produzcan retrasos, pero ésta se realizará con suficiente flexibilidad como para hacer frente a cualquier imprevisto que pudiera surgir durante el desarrollo.

Riesgo 3 - Retraso en una tarea produce retrasos en cascada en las tareas dependientes. La planificación se realizará de forma que se disponga de un tiempo extra entre la finalización del proyecto y la fecha de entrega del mismo, de forma que un retraso de este tipo no suponga un problema, siempre cuando el retraso no resulte excesivo. Adicionalmente, el tiempo diario estimado para la realización del proyecto no será demasiado elevado y podrá aumentarse temporalmente para recuperar las pérdidas derivadas de un riesgo de este tipo, sin que la carga de trabajo sea superior a las capacidades del personal.

Riesgo 4 - La falta de especialización necesaria requiere formación extra. La falta de especialización será asumida desde un primer momento, por lo cual se dedicará parte de la planificación a la "adquisición de conocimientos necesarios", que contemplará tanto el aprendizaje inicial como el adicional, que se llevará a cabo si es necesario durante el desarrollo del sistema.

Page � of �47 188

Page 48: UniSubject - rodin.uca.es

También se realizarán consultas y se organizarán reuniones con expertos de las diferentes materias que intervienen en la elaboración del proyecto o el desarrollo del sistema, para garantizar que el riesgo producido por falta de especialización no acabe por convertirse en un problema.

Riesgo 5 - El producto es más grande que el estimado y se requiere más tiempo. La metodología de desarrollo (iterativa e incremental) que será utilizada para la elaboración del proyecto cuenta con varias herramientas que permiten controlar el tamaño del producto para evitar que éste no acabe mayor de lo esperado. En primer lugar, contamos con la etapa de inicialización, que nos garantiza un punto de partida lo suficientemente simple, ya que se desarrolla la solución más básica para el problema.

La elaboración de la lista de control nos permite consultar un historial de todas las tareas que necesitan ser realizadas a continuación, así como las nuevas funcionalidades para ser implementadas y las áreas de rediseño de la solución ya existente. En todo momento podemos conocer el estado del desarrollo y comprobar si el sistema se está sobre dimensionando respecto a lo estimado. La etapa de iteración cuenta con una fase de análisis y diseño, en la cual podemos realizar los ajustes que sean necesarios y añadirlos a lista de control, siempre que detectemos algún riesgo de este tipo.

Por último, la planificación inicial se realizará de forma que se disponga de un tiempo extra entre la finalización del proyecto y la fecha de entrega del mismo, de forma que un retraso de este tipo no suponga un problema, siempre y cuando el retraso no resulte excesivo.

Riesgo 6 - El diseño es demasiado complejo/sencillo y debe modificarse. El diseño del sistema será supervisado por un experto, por lo tanto los errores de diseño serán detectados pronto y no ocasionarán pérdidas adicionales, salvo el tiempo que conllevará modificar el propio diseño.

Para evitar que se produzcan errores de diseño, se seguirán los estándares establecidos, se revisará la documentación con suficiente frecuencia y se consultará cualquier inconveniente con el supervisor. Finalmente, el rediseño de alguna parte del sistema forma parte de la etapa de iteración de la metodología utilizada y será contemplado en la lista de control del proyecto.

Riesgo 7 - Los requisitos varían o están mal definidos y necesitan redefinirse. La metodología de desarrollo iterativo e incremental contempla posibles cambios en los requisitos del sistema, ya que se basa en dos premisas: que los usuarios nunca conocen lo que necesitan exactamente para satisfacer sus necesidades y que durante el desarrollo los procesos tienden a cambiar.

Page � of �48 188

Page 49: UniSubject - rodin.uca.es

Por lo tanto, es una metodología que se adapta bien a este tipo de cambios, ya que garantiza que la implementación de cada iteración sea simple, directa y modular, para soportar el rediseño o la inclusión de una tarea añadida a la lista de control del proyecto, sin causar un impacto demasiado grande en las demás tareas.

Los requisitos podrían variar en etapas iniciales del desarrollo, no obstante, una vez establecidos y supervisados, no se esperan grandes modificaciones en los mismos, más allá de alguna pequeña modificación o ajuste que, si bien debemos considerar como un posible riesgo, es poco probable que acabe convirtiéndose en un problema para la elaboración del proyecto.

Riesgo 8 - Los módulos propensos a tener errores necesitan más trabajo. Para minimizar el impacto que puedan producir dichos errores, el proceso de desarrollo iterativo e incremental incluye en cada iteración fases de pruebas y evaluación del sistema en su versión más actualizada. De esta forma los errores se encuentran pronto y no son arrastrados a lo largo del desarrollo. De esta forma se evita que aparezcan nuevos errores, derivados de los anteriores y se reduce en gran medida el riesgo que suponen.

La lista de control también permite planificar el desarrollo de forma que se ponga especial atención cuando se desarrollen módulos propensos a errores, contando para ello con una mayor implicación de los colaboradores, que podrán realizar pruebas con el sistema para generar mayor información sobre los errores y agilizar de esta forma su corrección.

Riesgo 9 - Se añaden requisitos extra que no estaban inicialmente planteados. La inclusión de nuevos requisitos en un momento avanzado del desarrollo es poco probable, a diferencia de los ajustes que puedan realizarse en la etapa de iteración, no obstante, podrían añadirse nuevos requisitos únicamente si se ha realizado un análisis del estado del sistema en su versión más actualizada y la inclusión del nuevo requisito puede realizarse de manera modular y no supone un riesgo para los módulos que ya han sido implementados o los que aún están en la lista de control del proyecto. Adicionalmente, se dispondrá de un tiempo extra entre la fecha estimada de finalización del proyecto y la entrega del mismo, que podría ser utilizado para añadir alguna expansión al sistema, siempre bajo las condiciones anteriores.

Riesgo 10 - El personal trabaja más lento de lo esperado. Si el ritmo de trabajo se sitúa por debajo del mínimo esperado, se llevará a cabo un análisis sobre las causas que provocan el retraso para encontrar una solución a tiempo. También podría aumentarse el tiempo diario invertido en la elaboración del

Page � of �49 188

Page 50: UniSubject - rodin.uca.es

proyecto, ya que el tiempo estimado no es excesivo y puede aumentarse sin llegar a sobrecargar al personal.

Riesgo 11 - El proyecto avanza con demasiada lentitud en su inicio. Es frecuente que un proyecto avance con lentitud en su inicio, ya que el personal no está familiarizado con las nuevas herramientas, lenguajes de programación o dispositivos con los que deben trabajar. Por ello se establecerá al inicio de la elaboración del proyecto un período de aprendizaje e investigación lo suficientemente amplio, realizando una estimación realista sobre el tiempo necesario.

Se trata de un riesgo que debería reducirse por sí mismo a medida que avanza el proyecto, por lo tanto, en un estado más avanzado del desarrollo estaríamos hablando del Riesgo 10, al que hemos proporcionado respuesta anteriormente.

Riesgo 12 - El producto no alcanza una calidad aceptable. Es bastante improbable que la calidad del producto no sea la adecuada en el momento de realizar la evaluación final, ya que contaremos con varios mecanismos para evitarlo.

En primer lugar, la etapa de iteración cuenta con una fase de evaluación, que garantiza la calidad del producto en sus versión más actualizada, o en caso contrario, el módulo más reciente será añadido a la lista de control del proyecto para su revisión en futuras iteraciones. También se realizarán pruebas del producto con personal externo al equipo de desarrollo (colaboradores), que se encargarán de notificar cualquier fallo en el funcionamiento del sistema y podrán sugerir modificaciones que se tendrán en cuenta para mejorar la calidad del producto.

Finalmente, se presentarán cada cierto tiempo versiones actualizadas del producto al supervisor, que valorará la calidad del mismo y propondrá mejoras que aumenten la calidad.

Riesgo 13 - Se toman decisiones técnicas que alargan la planificación. Antes de tomar una decisión técnica se valorarán las opciones disponibles y se analizará cuales son las opciones más extendidas y que mejores resultados han proporcionado para otros sistemas existentes. Cuando la decisión sea crítica o no exista suficiente información para tomar la decisión, se llevará a cabo una consulta o reunión con algún experto que pueda proporcionar algún consejo según su experiencia. Las prácticas anteriores deberían reducir en gran medida el riesgo de tomar una decisión técnica errónea, que pueda derivar en pérdidas para el proyecto.

Riesgo 14 - La planificación no incluye tareas necesarias. La metodología de desarrollo elegida para el proyecto está muy extendida y suele proporcionar buenos resultados en los desarrollos en los que se utiliza. Es una metodología bastante completa y adaptable. Por otra parte, las actividades

Page � of �50 188

Page 51: UniSubject - rodin.uca.es

planificadas para la elaboración del proyecto serán establecidas según la guía proporcionada por la escuela y el análisis de los objetivos que se desean alcanzar mediante la realización del proyecto.

Por lo tanto, no es probable que falten tareas necesarias en la planificación, pero es algo que podría llegar a ocurrir. Si fuese necesario, podría modificarse la planificación, utilizando el tiempo extra disponible antes de la entrega final del proyecto y ampliando el número de horas diarias dedicadas al proyecto.

Riesgo 15 - La curva de aprendizaje es demasiado larga para alguna herramienta utilizada. Al inicio del proyecto se realizará junto al supervisor un análisis sobre la curva de aprendizaje de las herramientas y lenguajes de programación necesarios para el desarrollo del sistema planteado. También se establecerá al inicio de la realización del proyecto un tiempo de aprendizaje suficientemente amplio para que el personal pueda adaptarse.

Por último, en el momento de elegir las herramientas se tendrá en cuenta la similitud con otras herramientas conocidas o utilizadas previamente, para facilitar la adaptación del personal tanto al entorno de trabajo como a los nuevos lenguajes de programación.

Riesgo 16 - La falta de motivación y de moral reduce la productividad. Se establecerá un tiempo diario para el proyecto que no sea excesivo, con la posibilidad de aumentarlo si el proyecto corre algún riesgo. De esta forma el personal tendrá suficiente tiempo libre para realizar otras actividades que puedan mejorar su estado de ánimo y que ello repercuta en su productividad, siempre que el proyecto avance según lo esperado.

Riesgo 17 - Las herramientas de desarrollo no proporcionan las prestaciones previstas. Al inicio del proyecto se establecerá un período de aprendizaje, durante el cual el personal pueda adaptarse a las nuevas herramientas de trabajo. También se realizarán pruebas con las nuevas herramientas, mediante las cuales el personal pueda detectar este tipo de riesgo antes de iniciar el desarrollo. En caso de detectarse algún inconveniente con las herramientas de desarrollo, se han buscado algunas alternativas que podrían sustituir a las herramientas iniciales sin necesidad de rehacer el código realizado.

Riesgo 18: Dificultad para integrar componentes desarrollados por separado. La fase de pruebas de la etapa de iteración incluirá pruebas de integración entre los componentes presentes hasta la versión más actualizada del sistema. Los componentes del sistema se probarán de forma conjunta con suficiente frecuencia,

Page � of �51 188

Page 52: UniSubject - rodin.uca.es

detectándose cualquier riesgo de este tipo a tiempo. El personal involucrado en el desarrollo del sistema es lo suficientemente reducido como para que todos los miembros participen en la construcción de cada módulo o estén informados sobre su contenido, reduciéndose el riesgo de encontrar dificultades para integrar los componentes.

Page � of �52 188

Page 53: UniSubject - rodin.uca.es

Parte II

Desarrollo

Page � of �53 188

Page 54: UniSubject - rodin.uca.es

Capítulo 3. Analysis de Requisite

En este capítulo presentaré los requisitos del sistema. Para ello detallaré los actores que interactúan con el sistema, los requisitos funcionales, los requisitos de información, los requisitos no funcionales y las reglas de negocio. Luego describiré las diferentes alternativas tecnológicas y analizaré la brecha entre los requisitos planteados y la solución seleccionada

3.1 Catalogo de actores

En este apartado se describirán los diferentes actores que interactúan con el sistema para obtener algún beneficio por parte del mismo, incluyendo personas físicas y sistemas externos:

Usuario - Es la persona que ha instalado el sistema en su dispositivo y se registrar con un role privado. Tiene acceso limitado a la funciones del sistema y a su configuración.

Usuario con Role Admin - Es la persona que ha instalado el sistema en su dispositivo y se ha registrado con role de administrador, obteniendo un servicio por parte del mismo. Tiene acceso completo a las funciones del sistema, pero acceso limitado a su configuración.

Sistema - El propio sistema puede iniciar casos de uso de forma automática, por lo tanto consideraremos al propio sistema como actor para facilitar la elaboración y comprensión de los diagramas de casos de uso.

3.2 Requisitos funcionales A continuación se realiza una descripción completa de la funcionalidad que ofrece el sistema. Para ello se emplean casos de uso como mecanismo para representar las interacciones entre los actores y el sistema analizado.

Figura 3.1 Diagrama del Sistema Page � of �54 188

Page 55: UniSubject - rodin.uca.es

3.2.1 Diagrama de Caso de Uso

Figura 3.2 Gestión de Sesión

Figura 3.3 Gestión de Perfil

Page � of �55 188

Page 56: UniSubject - rodin.uca.es

Figura 3.4 Gestión de Universidad (con role admin)

Figura 3.5 Gestión de Universidad

Page � of �56 188

Page 57: UniSubject - rodin.uca.es

3.2.2 Descripción de caso de uso

# Registrar Usuario

Actor El usuario no esta registrado en el sistema.

Per-Condición

El usuario no esta registrado en el sistema

Escenario Principal

1 El usuario comienza a registrase en el sistema

2 El sistema muestra un formulario de registro.

3 El usuario introduzca los dato solicitado

4 El usuario selecciona la opción privado

5 El usuario selecciona el button Registrar.

6 El sistema comprobar que los datos son correctos y no falta datos

7 El sistema registrar el usuario como Usuario Privado.

Post-Condición

La sistema actualiza los bases de datos (MYSQL y SQLite)

Escenario Alternativo 6 Los datos no son correctas o falta datos.

Escenario Alternativo 6.1

El sistema notifica el error por pantalla y volver al punto 2 pero con todas los datos tal como fue introducido anteriormente y los datos incorrectas o falta se señalar.

Escenario Alternativo 4 El usuario selecciona la opción Entidad Universitaria

Escenario Alternativo 4.1 El sistema registrar el usuario como Usuario Entidad.

Escenario Alternativo 4.2 El sistema mostrar un formulario para registrar su entidad

universitario.

Escenario Alternativo 4.2 El usuario introduzca los datos solicitados.

Escenario Alternativo 4.3 El usuario pulsar el button Registrar Entidad

Escenario Alternativo 4.4 El sistema comprobar que los datos son correctos y no falta

datos

Page � of �57 188

Page 58: UniSubject - rodin.uca.es

Escenario Alternativo 4.4.1 Los datos no son correctas o falta datos.

Escenario Alternativo 4.4.2

El sistema notifica el error por pantalla y volver al punto 4.2 pero con todas los datos tal como fue introducido anteriormente y los datos incorrectas o falta se señalar.

Escenario Alternativo 4.5 Los datos introducido son correctos y no falta datos

Escenario Alternativo 4.6

El system codifica el dirección introducido por el usuario y solicita las coordenadas de longitud y latitude al servicio Google Maps.

Escenario Alternativo 4.7 La dirección no tiene coordinado por ser incorrectos

Escenario Alternativo 4.7.1

El sistema mostrar el error y volver al paso 4.2 pero con todas los datos tal como fue introducido anteriormente y los datos de dirección, country, y continentes señalizado incorrectas o falta se señalar.

Escenario Alternativo 4.8 El sistema recibe los coordinada correcto

Escenario Alternativo 4.9 El sistema registrar la entidad y actualizar el sistema.

Escenario Alternativo 4.10 El sistema mostrar un formulario para registrar su entidad

Facultad.

Escenario Alternativo 4.11 El usuario introduzca los datos solicitados.

Escenario Alternativo 4.12 El usuario pulsar el button Registrar Facultad

Escenario Alternativo 4.13 El sistema comprobar que los datos son correctos y no falta

datos

Escenario Alternativo 4.13.1 Los datos no son correctas o falta datos.

Escenario Alternativo 4.13.2

El sistema notifica el error por pantalla y volver al punto 4.10 pero con todas los datos tal como fue introducido anteriormente y los datos incorrectas o falta se señalar.

Escenario Alternativo 4.14 Los datos introducido son correctos y no falta datos

# Registrar Usuario

Page � of �58 188

Page 59: UniSubject - rodin.uca.es

Escenario Alternativo 4.15

El system codifica el dirección introducido por el usuario y solicita las coordenadas de longitud y latitude al servicio Google Maps.

Escenario Alternativo 4.16 La dirección no tiene coordinado por ser incorrectos

Escenario Alternativo 4.16.1

El sistema mostrar el error y volver al paso 4.2 pero con todas los datos tal como fue introducido anteriormente y los datos de dirección, country, y continentes señalizado incorrectas o falta se señalar.

Escenario Alternativo 4.17 El sistema recibe los coordinada correcto

Escenario Alternativo 4.18 El sistema registrar la entidad y actualizar el sistema.

Escenario Alternativo 4.19 El sistema mostrar un formulario para registrar un Major.

Escenario Alternativo 4.20 El usuario introduzca los datos solicitados.

Escenario Alternativo 4.21 El usuario pulsar el button Registrar Major

Escenario Alternativo 4.22 El sistema comprobar que los datos son correctos y no falta

datos

Escenario Alternativo 4.22.1 Los datos no son correctas o falta datos.

Escenario Alternativo 4.22.2

El sistema notifica el error por pantalla y volver al punto 4.19 pero con todas los datos tal como fue introducido anteriormente y los datos incorrectas o falta se señalar.

Escenario Alternativo 4.23 Los datos introducido son correctos y no falta datos

Escenario Alternativo 4.24 El sistema registrar la Major y actualizar el sistema.

Escenario Alternativo 4.25 El sistema mostrar un formulario para registrar una

asignatura.

Escenario Alternativo 4.26 El usuario introduzca los datos solicitados.

# Registrar Usuario

Page � of �59 188

Page 60: UniSubject - rodin.uca.es

Tabla 3.1 Registrar Usuario

Escenario Alternativo 4.27 El usuario pulsar el button Registrar Asignatura

Escenario Alternativo 4.28 El sistema comprobar que los datos son correctos y no falta

datos

Escenario Alternativo 4.28.1 Los datos no son correctas o falta datos.

Escenario Alternativo 4.28.2

El sistema notifica el error por pantalla y volver al punto 4.25 pero con todas los datos tal como fue introducido anteriormente y los datos incorrectas o falta se señalar.

Escenario Alternativo 4.29 Los datos introducido son correctos y no falta datos

Escenario Alternativo 4.30 El sistema registrar la la Asignatura y actualizar el sistema.

Escenario Alternativo 4.31

El Sistema prompt el usuario a selecciona del menu de: para registrar asignatura, registrar Major, registrar Facultad o salir de la registration.

Escenario Alternativo 4.32.1 El usuario aceptar registrar otra asignatura

Escenario Alternativo 4.32.2 El sistema volver al paso 4.25

Escenario Alternativo 4.32.3 El usuario aceptar registrar otra Major

Escenario Alternativo 4.32.4 El sistema volver al paso 4.19

Escenario Alternativo 4.32.5 El usuario aceptar registrar otra Facultad

Escenario Alternativo 4.32.6 El sistema volver al paso 4.10

Escenario Alternativo 4.32.7 El usuario aceptar salir

Escenario Alternativo 4.32.8 El sistema volver al menu principal

# Registrar Usuario

Page � of �60 188

Page 61: UniSubject - rodin.uca.es

Tabla 3.2 Iniciar Sesión

# Iniciar Sección

Actor Cualquier Usuario

Pre-Condición

El usuario esta registrado en el sistema El usuario aun no ha iniciado sección

Escenario Principal

1 El usuario introduzca los datos solicitados

2 El sistema comprueba que los datos son correctas y no falta ningún datos

3 El sección se abre para el usuario

Post-Condición

El sistema actualiza al iniciar la sección del usuario y el sistema modifica el base de datos el atributo estado del usuario como conectado.

Escenario Alternativo

2 Los datos de inicio de sesión son incorrectos.

Escenario Alternativo

2.1 El sistema notifica el error y volver al paso 1

Escenario Alternativo

3 El sistema no puede iniciar la sesión del usuario.

Escenario Alternativo

3.1 El sistema notifica el error y volver al paso 1

Escenario Alternativo

3.1.1 El usuario cancelar la sección

Nota Cuando el usuario inicia sección, la sección se queda abierta hasta que el usuario lo cierre.

# Comparación de Universidad

Actor Cual quiere usuario registrado en el sistema

Per-Condición

El usuario esta login en el sistema

1 El sistema mostrar en pantalla una lista de universidad a elegir y la opción de comparar o mostrar.

2 El usuario selección la primera universidad a comparar

3 El usuario selección la segunda universidad a comparar

Page � of �61 188

Page 62: UniSubject - rodin.uca.es

Escenario Principal

4 El usuario selecciona el button Comparar

5

El sistema cargar en pantalla los dos universidades en modo horizontal con todos los datos de los universidades y un lista de los facultades de los respectivo universidades y la opción de comparar o mostrar..

6 El usuario selección una facultad de la primera universidad a comparar

7 El usuario selección otra facultad de la segunda universidad a comparar

8 El usuario pulsar el button Comparar

9

El sistema cargar en la misma pantalla los dos facultades en modo horizontal con los datos básicas de los facultades y un lista de los majors de los respectivo facultades y la opción de comparar o mostrar..

10 El usuario selección una major de la primera facultad a comparar

11 El usuario selección otra major de la segunda facultad a comparar

12 El usuario pulsar el button Comparar

13El sistema cargar en la misma pantalla los dos majors en modo horizontal con los datos básicas de los majors y un lista de los asignaturas de los respectivo majors.

14 El usuario selección una asignatura de la primera major a comparar

15 El usuario selección otra asignatura de la segunda major a comparar

16 El usuario pulsar el button Comparar

17 El sistema cargar en la misma pantalla los dos asignatura en modo horizontal con los datos básicas de los asignatura.

18 El usuario puede abandona la operación en cualquier momento

Post-Condición

La sistema actualiza el atributo “hits” de la tupla de los selecciones del usuario a los bases de datos (MYSQL y SQLite).

# Comparación de Universidad

Page � of �62 188

Page 63: UniSubject - rodin.uca.es

Tabla 3.3 Comparación de Universidad

3.3 Requisites de información

En esta sección describiré el conjunto de datos que mi sistema debe gestionar para cumplir con sus objetivos. Para ello, he desarrollado un diagrama conceptual de clases UML, identificando las clases, atributos y relaciones que forman parte de la estructura del sistema. También incluyo un diagrama entidad/relación para la base de datos.

Escenario Alternativo

18.1 El sistema volver al paso 1

Escenario Alternativo

4 El usuario selecciona el button Ok para mostrar

Escenario Alternativo

4.1 El sistema mostrar todos los datos de la primera universidad y su position en la mapa Google.

Escenario Alternativo

8 El usuario selecciona el button Ok para mostrar

Escenario Alternativo

8.1 El sistema mostrar todos los datos de la facultad correspondiente al button Ok y su position en la mapa Google.

Escenario Alternativo

12 El usuario selecciona el button Ok para mostrar

Escenario Alternativo

12.1 El sistema mostrar todos los datos de la major correspondiente al button Ok

Escenario Alternativo

16 El usuario selecciona el button Ok para mostrar

Escenario Alternativo

16.1 El sistema mostrar todos los datos de la asignatura correspondiente al button Ok

# Comparación de Universidad

Page � of �63 188

Page 64: UniSubject - rodin.uca.es

3.3.1 Descripciones de los requisitos de información

Los requisitos de información que el sistema debe gestionar son los siguientes:

Tabla 3.4 Información sobre la sesión

Tabla 3.5 Información sobre el usuario

Information sobre la sección

Descripción El sistema debe almacenar la información correspondiente a los parámetros de inicio de sesión de cada usuario registrado

Dependencia Gestión de sesión Gestión de perfil

Datos especificados Identificador Email Contraseña Estado Role

Información sobre el usuario

Descripción El sistema debe almacenar la información correspondiente a cada usuario registrado

Dependencia Gestión de Sección Gestión de Perfil Gestión de Modificación (role admin)

Datos especificados Identificador Email User Name Contraseña Estado Role

Information sobre comparación

Descripción El sistema debe almacenar la información correspondiente a cada universidad, facultad, major y asignatura registrado en el sistema

Dependencia Gestión de Sección Gestión de Perfil Gestión de Búsqueda Gestión de Comparación

Page � of �64 188

Page 65: UniSubject - rodin.uca.es

Tabla 3.6 Información sobre comparación

3.3.2 Diagrama Entidad/Relación.

A continuación se puede encontrar una representación de la estructura conceptual de la base de datos. Para ello se ha utilizado un diagrama entidad-relación, que incluye tanto los elementos que intervienen en el problema como las relaciones que se establecen entre ellos. Pero antes identificaré las entidades y relaciones que pueden encontrarse en el diagrama.

Tabla 3.7 Entidades

Tabla 3.8 Relaciones

Datos especificados Datos de Universidad: Datos de Facultad: Datos de Major: Datos de Asignatura: Resultado de Google Map

Information sobre comparación

Entidad Descripción

User Los usuarios que están registrado en el sistema.

University Las universidad que están registrado en el sistema.Faculty Los facultad que están registrado en el sistema.

Major Los major que están registrado en el sistema.

Subject Las asignaturas que están registrado en el sistema.GalleryUni Los imagines que están registrado en el sistema.

Relación Descripción

Relationship La relación entre entidades que están registrado en el sistema.

Page � of �65 188

Page 66: UniSubject - rodin.uca.es

Diagrama de Entidad/Relación 1

Diagrama de Entidad/Relación 2

Page � of �66 188

Page 67: UniSubject - rodin.uca.es

3.4 Requisites no funcionales

A continuación se describen los requisitos que el sistema debe satisfacer para garantizar un nivel adecuado de calidad en diversos aspectos relacionados con el mismo.

3.4.1 Usabilidad e interfaz

El sistema debe poder ser utilizado por usuarios con distintos niveles de adaptación a los dispositivos móviles, por lo tanto la interfaz deberá ser ordenada e intuitiva, y el acceso a los contenidos debe ser sencillo y directo. El sistema deberá contener ayudas que los usuarios puedan consultar mientras lo utilizan y los diálogos con el usuario deben ser claros y precisos.

3.4.2 Operatividad

El sistema debe cumplir el propósito para el cual fue diseñado, ofreciendo al usuario todas las funcionalidades planeadas y el resultado esperado para cada una de ellas. El sistema deberá cumplir los objetivos expuestos al inicio de la memoria.

3.4.3 Comunicaciones

La comunicación entre las partes cliente y servidor del sistema será bastante frecuente, por lo tanto deberá garantizarse que sea lo más fluida posible, transmitiéndose solo la información necesaria para llevar a cabo la operación requerida, ya que cualquier información innecesaria podría derivar en una comunicación lenta o un consumo de datos excesivo para el usuario. Las comunicaciones se llevarán a cabo mediante el protocolo de transferencia HTTP.

3.4.4 Seguridad

El sistema deberá codificar la contraseña del usuario, de forma que quede protegida durante su comunicación y registro en la base de datos. La codificación se llevará a cabo mediante el algoritmo de reducción criptográfico md Cualquier comunicación entre el cliente y el servidor deberá ser validada por una clave privada que se generará en ambas partes y también será codificada mediante el algoritmo md5. La clave privada cambiará constantemente, de forma que la misma clave solo sea válida durante un breve periodo de tiempo. El sistema deberá evitar intrusiones mediante inyección SQL en la base de datos, para ello comprobará que las comunicaciones no contengan palabras reservadas por el SGBD.

Page � of �67 188

Page 68: UniSubject - rodin.uca.es

3.4.5 Estabilidad

Aunque el sistema desarrollado para el proyecto tendrá un carácter experimental, deberá poseer cierto nivel de estabilidad que garantice una utilización correcta. Por lo tanto el sistema debe estar libre de errores que impidan un funcionamiento correcto y debe ser capaz de identificar dichos errores en tiempo de ejecución para notificarlos al usuario o recuperarse de ellos.

3.4.6 Rendimiento y concurrencia

El sistema deberá funcionar con fluidez, realizando las operaciones en un tiempo razonable y utilizando los recursos del dispositivo móvil de forma equilibrada. Para ello se realizarán las operaciones más pesadas de forma asíncrona, para no sobrecargar el hilo principal de ejecución. El sistema deberá tener en cuenta las limitaciones de los dispositivos móviles en cuanto a capacidad de procesamiento y almacenamiento, de forma que los procesos ejecutados en la parte cliente no sean excesivamente complejos y los datos almacenados no requieran demasiado espacio. La parte servidor se encargará de realizar las partes más duras del trabajo.

3.4.7 Portabilidad

El sistema deberá poder ejecutarse en el mayor número de dispositivos móviles posible. Aunque la mayoría de los sistemas desarrollados para Android están escritos en Java, no hay una máquina virtual Java en la plataforma. El bytecode Java no es ejecutado, sino que primero se compila en un ejecutable Dalvik y corre en la Máquina Virtual Dalvik. Dalvik es una máquina virtual especializada, diseñada específicamente para Android y optimizada para dispositivos móviles que funcionan con batería y que tienen memoria y procesador limitados.

Por otra parte, Android es el sistema operativo más extendido entre los dispositivos móviles actuales, por lo tanto la portabilidad está garantizada para los dispositivos móviles con sistema operativo Android que cumplan los requerimientos mínimos del sistema.

3.4.8 Disponibilidad

El sistema debe desempeñar sus funciones en cualquier momento que el usuario lo requiera, por lo tanto la parte servidor deberá estar preparada y en constante funcionamiento para dar respuesta a las peticiones de la parte cliente. El servidor debe responder lo más rápido posible.

Page � of �68 188

Page 69: UniSubject - rodin.uca.es

3.4.9 Escalabilidad y mantenibilidad

El sistema debe tener la capacidad de cambiar su tamaño o configuración para adaptarse a las circunstancias cambiantes. El sistema deberá diseñarse e implementarse de forma modular, para facilitar su expansión mediante nuevos módulos o el rediseño de módulos existentes. El sistema utilizará un modelo cliente-servidor que facilite la adaptación a mayor carga de procesamiento y almacenamiento, encargándose el servidor de las tareas más pesadas. El sistema deberá estar preparado para ser traducido a diferentes idiomas con facilidad, en caso de que el sistema pudiera ser utilizado por usuarios de distintos lugares del mundo.

3.5 Reglas de negocio

De forma complementaria a los requisitos anteriormente descritos para el sistema , se definen a continuación una serie de restricciones adicionales que el sistema debe cumplir.

Tabla 3.4 Reglas de Negocio

Restricción Descripción

Acceso a los servicios del sistema

- Solo los usuarios registrados como usuario en el sistema tendrán acceso a los servicios. - Si el usuario no están registrado, solo tendrá acceso al servicio de registrar.

Acceso desde varios dispositivos móviles

Si el usuario tiene su sección abierto en un dispositivo móvil no puede abrir sección en otra dispositivo móvil.

Si el usuario cierra su sección en un dispositivo móvil, entonces puede abrir sección en otro dispositivo móvil

Validez para registrarse en el sistema

El email del usuario se utiliza como base de comprobación que el usuario no ya existir en el sis tema.

Reglas de eliminación Cuando el usuario decidido eliminarse del sistema todos los datos del base de datos se queda eliminado sin recuperables.

Page � of �69 188

Page 70: UniSubject - rodin.uca.es

3.6 Estudios de alternativas tecnológicas

En esta sección se estudian las diferentes alternativas tecnológicas disponibles durante la realización del proyecto, se analizan cuales permiten satisfacer los requerimientos del sistema y se comparan con los cual están elegido. el conjunto de herramientas que serán finalmente utilizadas para desarrollar el sistema fueron citadas antes en este documento. 3.6.1 Android vs. iOS

Lenguaje Las aplicaciones para Android están escritas en Java y las aplicaciones para iOS en Objective-C (con algunas excepciones). Java es un lenguaje mucho más universal, mientras que Objective-C se encuentra principalmente en el ecosistema Apple. Sin embargo, Objective-C tiene la ventaja de que generalmente es más legible que Java. Por ejemplo, tiene bloques (segmentos de código que se agrupan). También tiene categorías, mientras que java no. Por otra parte, Java tiene un mejor seguimiento de pila, por lo tanto encontrar errores aleatorios es mucho más fácil.

Experiencia de usuario iOS consigue ciertamente una gran cantidad de elogios por su interfaz y experiencia de usuario sobre Android. Además, su constructor de interfaces es una forma estupenda de integrar elementos simples de la interfaz del usuario con facilidad. Android también cuenta con una herramienta visual, pero se vuelve más complicado con los distintos tamaños de pantalla y dispositivos distintos con Android. El desarrollo de interfaces elegantes es sin duda más sencillo en iOS, , y tiene absolutamente la aprobación del mundo del diseño.

Publicación Cuando se trata de publicar una aplicación en Google Play o App Store, no hay mucho que considerar. Android es un sistema mucho más abierto, permitiendo a los desarrolladores firmar sus aplicaciones simplemente con el asistente de Eclipse, y recibiendo un archivo APK que puede ejecutarse en cualquier dispositivo. Subiendo este APK a Google Play está disponible casi de inmediato. Apple, sin embargo, tiene una serie de reglamentos y filtros que los desarrolladores deben superar antes de publicar su aplicación en el App Store.

Cuota de mercado Mientras que la cuota de mercado entre iOS y Android en Estados Unidos está cerca del 50 a 50, es completamente distinto en otras partes del mundo. En China, Android domina en un ratio de casi 4 a 1, y en Europa, más o menos existe una proporción de 3,5 a 1 . Llegar a los usuarios es el mayor objetivo cuando se desarrolla una aplicación, y la cuota de mercado en nuestra región es algo muy importante a considerar cuando se elige entre estos dos gigantes.

Page � of �70 188

Page 71: UniSubject - rodin.uca.es

Fragmentación La fragmentación es una consideración real cuando se trata de iOS o Android. En pocas palabras, iOS se ejecuta principalmente en tres tamaños de pantalla: : iPhone, iPad Mini y iPad. Android, en cambio, funciona en una aparentemente infinita gama de pantallas, desde pequeños smartphones hasta enormes tablets, y todo lo que hay en medio. El desarrollo de una aplicación para dar soporte a todos esos tamaños y la comprobación de errores en dispositivos desconocidos puede ser una tarea enorme, y de hecho puede limitar la capacidad de llegar a los usuarios en un mercado determinado.

Conclusión En base a los criterios anteriores, se ha decidido desarrollar la aplicación para Android. Teniendo en cuenta que no se tienen conocimientos previos sobre ninguno de los lenguajes anteriores, se considera más interesante aprender Java, a pesar de ser algo menos accesible, ya que reportará mayor utilidad en el futuro.

Por otra parte, la cuota de mercado de Android es significativamente mayor que la de iOS a nivel mundial, ofreciendo además una mayor libertad de publicación. Los conocimientos adquiridos durante el desarrollo del proyecto podrían utilizarse en futuras aplicaciones, que se publicarían de forma más directa, consiguiendo llegar a un mayor número de usuarios.

La fragmentación será un problema que se deberá controlar en medida de lo posible durante el desarrollo de la aplicación, así como el diseño de las interfaces, para que no se conviertan en un inconveniente. Pero se considera que el esfuerzo extra se ve compensado con los motivos anteriormente expuestos.

"

Page � of �71 188

Page 72: UniSubject - rodin.uca.es

3.6.2 Eclipse ADT

Android Development Tools (ADT) Android Development Tools es un complemento para Eclipse que proporciona un conjunto de herramientas que están integradas con el IDE Eclipse. Ofrece acceso a muchas características que ayudan a desarrollar aplicaciones Android rápidamente. ADT proporciona acceso a través de interfaz gráfica a muchas de las herramientas de línea de comandos del SDK, así como una herramienta de diseño de interfaces para la creación rápida de prototipos, diseño y construcción de la interfaz de usuario de la aplicación.

Como ADT es un complemento de Eclipse, se obtiene la funcionalidad de un IDE fuertemente establecido, junto con características específicas de Android que están incluidas en ADT. ADT integra muchas tareas del flujo de trabajo del desarrollo en Eclipse, permitiendo desarrollar y probar aplicaciones rápidamente. Muchas de las herramientas SDK están integradas en los menús de Eclipse, como perspectivas o como parte de los procesos en segundo plano ejecutados por ADT. El editor de código Java contiene características comunes de los IDE, como comprobación de la sintaxis en tiempo de compilación, autocompletado y documentación integrada para las API. ADT también proporciona editores XML personalizados que permiten editar archivos XML específicos de Android en una interfaz de usuario basada en formularios.

Es posible acceder a la documentación sobre las clases, métodos y variables simplemente pasando el puntero del ratón sobre ellos. En resumen, ADT amplía las capacidades de Eclipse permitiendo la configuración rápida de nuevos proyectos Android, el diseño de la interfaz de usuario, la adición de paquetes basados en la API de Android, la depuración de aplicaciones utilizando las herramientas del SDK de Android, e incluso exportar archivos APK firmados (o sin firmar) para distribuir la aplicación.

3.6.3 Sistemas de gestión de bases de datos (SGBD)

SQL (Structured Query Language o Lenguaje de Consulta Estructurado) [14] es un lenguaje declarativo de acceso a BBDD relacionales que permite especificar diversos tipos de operaciones sobre las mismas. Una de sus características es el manejo del álgebra y el cálculo

relacional permitiendo lanzar consultas con el fin de recuperar, de una forma sencilla, información de interés de una base de datos, así como también hacer cambios sobre la misma.

Page � of �72 188

Page 73: UniSubject - rodin.uca.es

La primera version de SQL fue desarrollada en IBM por Donald D. Chamberlin y Raymond F. Boyce a principios de los 70. Esta versión, inicialmente llamada SEQUEL, fue diseñada para manipular y recuperar datos almacenados en una BBDD relacional original de IBM (System R). IBM patentó esta versión de SQL en 1985, mientras que el lenguaje SQL no fue formalmente estandarizado hasta 1986, por el ANSI. Las siguientes versiones del estándar de SQL fueron realizadas como estándares ISO.

El lenguaje SQL se divide en varios sub-elementos • Statements – Tienen un efecto persistente en esquemas o en los datos • Queries – Retornan datos basandose en un criterio. • Expressions – Producen valores para las tablas • Predicates – Especifican condiciones que pueden ser evaluadas por SQL para

limitar los efectos de los statements o queries. • Clauses – Constituyen componentes de los statements o queries.

La operación más común en SQL es la query o petición, la cual se realiza mediante la palabra clave SELECT (ver el ejemplo bajo).

Eg. SELECT * FROM ejemplotable WHERE valor2 > 356 ORDER BY campo2;

Puntos fuertes de SQL Es un lenguaje declarativo de "alto nivel" que gracias a su orientación al manejo de conjuntos de registros, y no a registros individuales, permite una alta productividad en codificación y la orientación a objetos, pudiendo realizar en una sola sentencia varias operaciones de lenguaje de bajo nivel.

Puntos débiles de SQL SQL, al ser un lenguaje declarativo, especifica qué es lo que se quiere y no cómo conseguirlo, por lo que una sentencia no establece explícitamente un orden de ejecución. El orden de ejecución interno de una sentencia puede afectar gravemente a la eficiencia del DBMS, por lo que se hace necesario que éste lleve a cabo una optimización antes de la ejecución de la misma. Muchas veces, el uso de índices acelera una instrucción de consulta, pero ralentiza la actualización de los datos. Dependiendo del uso de la aplicación, se priorizará el acceso indexado o una rápida actualización de la información, llegando a un compromiso

Además, hay otros aspectos que afectan negativamente a SQL: • Las diferentes implementaciones de SQL son inconsistentes y normalmente,

incompatibles entre desarrolladores. • La sintaxis de SQL puede llegar a ser compleja dando lugar a peticiones

erróneas y que, por lo tanto, alteren de manera negativa la BBDD.

Page � of �73 188

Page 74: UniSubject - rodin.uca.es

SQL Server Microsoft SQL Server es un SGBDR desarrollado por Microsoft. Actualmente SQL Server ocupa el tercer puesto entre los SGBD más utilizados en todo el mundo. Existe al menos una docena de ediciones diferentes de Microsoft SQL Server destinadas a distintas audiencias y rangos de carga de trabajo desde pequeñas aplicaciones de una sola máquina hasta grandes aplicaciones orientadas a Internet con muchos usuarios concurrentes. Sus principales lenguajes de consulta son T-SQL y ANSI SQL. Entre las características de SQL Server se incluyen el soporte de transacciones, procedimientos almacenados, entorno gráfico de administración (que permite el uso de comandos DDL y DML gráficamente), compatibilidad con ACID, servicio de reportes, vistas, disparadores, cursores, sub-consultas, replicación y funciones definidas por el usuario.

Es común desarrollar completos proyectos complementando Microsoft SQL Server y Microsoft Access a través de los llamados ADP (Access Data Project). De esta forma se completa la base de datos (Microsoft SQL Server), con el entorno de desarrollo (VBA Access), a través de la implementación de aplicaciones de dos capas mediante el uso de formularios Windows. En el manejo de SQL mediante líneas de comando se utiliza el SQLCMD, osql, o PowerShell. Para el desarrollo de aplicaciones más complejas (tres o más capas), Microsoft SQL Server incluye interfaces de acceso para varias plataformas de desarrollo, entre ellas .NET, pero el servidor sólo está disponible para Sistemas Operativos. Microsoft SQL Server requiere de un sistema operativo Microsoft Windows, por lo que no puede instalarse, por ejemplo, en servidores Linux.

Oracle Oracle es un SGBDR multiplataforma con licencia privativa producido y comercializado por la Corporación Oracle. Oracle ocupa actualmente el primer puesto entre los SGBD más utilizados en todo el mundo, debido a la gran cantidad de características avanzadas que lo componen. Su dominio en el mercado de servidores empresariales ha sido casi total hasta hace poco; recientemente sufre la competencia del Microsoft SQL Server de Microsoft y de la oferta de otros SGBDR con licencia libre como PostgreSQL, MySQL o Firebird. Las últimas versiones de Oracle han sido certificadas para poder trabajar bajo GNU/Linux.

Aparte de las opciones de base de datos claramente definidas, expuestas en las alternativas anteriores, las bases de datos Oracle pueden incluir muchos otros sub-sistemas de software semiautónomos , a los cuales la Corporación Oracle a menudo se refiere como "características" en un sentido sutilmente distinto del uso normal de la palabra. Por ejemplo, Oracle Data Guard cuenta oficialmente como una "característica", pero la pila de comandos interna de SQL *Plus, aunque es una característica de usabilidad, no aparece en la lista de "características" de Oracle. Antes del lanzamiento de Oracle 9i en 2001, la Corporación Oracle adaptó sus

Page � of �74 188

Page 75: UniSubject - rodin.uca.es

productos de bases de datos a una amplia variedad de plataformas. Posteriormente la Corporación Oracle se ha consolidado en un rango menor de plataformas de sistemas operativos. En noviembre de 2011, la Corporación Oracle daba soporte a los siguientes sistemas operativos y plataformas hardware para Oracle 11g: - zLinux64 - Microsoft Windows (32-bit) - Microsoft Windows (x64) - Linux x86 - Linux x86-64 - Solaris (SPARC) - Solaris (x86-64) - HP-UX Itanium - HP-UX PA-RISC (64-bit) - AIX (PPC64) - OpenVMS (IA64) [75]

Las bases de datos Oracle responden con un rendimiento excelente en entornos exigentes, recuperándose de forma eficiente cuando se comenten errores humanos y ayudando a simplificar la gestión y administración de los procesos.

Conclusión La mejor solución en cuanto a SGBD se refiere es Oracle en la mayoría de los aspectos que se pueden requerir para un proyecto, pero por motivos de aprendizaje se ha decidido probar otras opciones que no hayan sido estudiadas durante los estudios a lo largo de la titulación. Por lo tanto se ha experimentado con las siguientes opciones más populares, que son MySQL, SQL Server y SQLite tras lo cual se ha seleccionado finalmente SQLite y MySQL como SGBD para el proyecto, debido a su licencia GPL y el mejor rendimiento experimentado durante las pruebas de carga.

Page � of �75 188

Page 76: UniSubject - rodin.uca.es

Capítulo 4. Diseño del sistema

En este capítulo se recoge la arquitectura general del sistema de información, el diseño de la interfaz de usuario, el diseño físico de datos, el diseño de componentes software y un diagrama donde se muestran los elementos que componen la estructura del sistema.

4.1 Diseño de la arquitectura

4.1.1 Arquitectura fisica

El sistema cuenta con dos partes claramente identificables, por un lado tenemos la parte cliente, que se trata del dispositivo móvil a través del cual el usuario accede al sistema, y un servidor web, donde se realizan las tareas más pesadas. La comunicación entre ambas partes se realiza mediante protocolo HTTP/HTTPS. A continuación se detallan las características de cada una de las partes que componen la estructura física del sistema.

Cliente Se trata de un dispositivo móvil con sistema operativo Android 2.3 (Gingebread) o superior, que dispone de capacidad de localización por satélite (GPS/AGPS), conexión a Internet (Wi-Fi, 3G, 4G, etc.), cámara de fotos y OpenGL ES 2.0. El cliente almacena información de forma local mediante una base de datos SQLite y ciertos contenidos multimedia en el sistema de carpetas de la tarjeta SD del dispositivo. Dicho dispositivo móvil constituye la parte del sistema con la cual el usuario puede interactuar.

Servidor Es la parte del sistema encargada de alojar el servicio web que proporciona los contenidos a la aplicación y la base de datos donde se almacena la información. Ambas partes se comunican a través de Internet mediante protocolo HTTP/HTTPS.

4.1.2 Arquitectura lógico

Modelo cliente-servidor El modelo cliente-servidor es una estructura de aplicación distribuida que reparte las tareas o cargas de trabajo entre los proveedores de un recurso o servicio, llamados servidores y los solicitantes de dichos servicios, llamados clientes. A menudo los clientes y servidores se encuentran separados en distintos hardware y se comunican a través de la red, pero ambos pueden formar parte del mismo sistema.

Un servidor ejecuta uno o más programas de servidor que comparten sus recursos con los clientes. Un cliente no comparte ninguno de sus recursos, pero solicita funciones

Page � of �76 188

Page 77: UniSubject - rodin.uca.es

de contenido o servicio del servidor. Por lo tanto, son los clientes quienes inician sesiones de comunicación con los servidores, los cuales esperan peticiones entrantes. En el nivel lógico del presente proyecto, la aplicación Android instalada en dispositivo móvil realiza la función de cliente. La función de servidor la realiza un servicio web, que proporciona contenido y servicios a la aplicación móvil, repartiendo de esta forma la carga de trabajo y permitiendo además compartir información entre distintos clientes a través de los servicios ofrecidos por el servidor. Protocolo HTTP (Hypertext Transfer Protocol)

La conexión entre las partes cliente y servidor que componen la estructura física del sistema se realiza a través de Internet mediante protocolo HTTP, utilizándose un formato propio para los mensajes durante la comunicación, con el objetivo de garantizar un nivel aceptable de fluidez.

HTTP es un protocolo de aplicación para sistemas de información hipermedia, colaborativos y distribuidos. HTTP es el fundamento de la comunicación de datos para la World Wide Web. El hipertexto es texto estructurado que utiliza enlaces lógicos (hipervínculos) entre nodos que contienen texto. HTTP es el protocolo para el intercambio o transferencia de hipertexto.

HTTP funciona como un protocolo de petición-respuesta en el modelo de computación cliente-servidor. El cliente envía un mensaje de petición HTTP al servidor. El servidor, que provee recursos y contenidos, o realiza otras funciones en nombre del cliente, retorna un mensaje de respuesta al cliente. La respuesta contiene información sobre el estado de finalización de la petición y también contener el contenido solicitado en el cuerpo del mensaje.

Una sesión HTTP es una secuencia de operaciones petición-respuesta en la red. Un Cliente inicia una petición estableciendo una conexión TCP a un puerto en particular de un servidor. Un servidor HTTP escuchando en este puerto espera el mensaje de petición del cliente. Al recibir la petición, el servidor envía de vuelta una línea de estado, y el mensaje en sí mismo. El cuerpo del mensaje es normalmente el recurso solicitado, a pesar de que un mensaje de error u otra información también puede ser devuelta.

Google Services Google ofrece una variedad de servicios que ayudan a los desarrolladores a construir nuevas fuentes de ingresos, gestionar la distribución de la aplicación, registrar el uso de la aplicación, y mejorar la aplicación con características como mapas, registros y mensajería en la nube. Aunque estos servicios no están incluídos en la plataforma Android, son soportados por la mayoría de los dispositivos Android. Cuando se utilizan estos servicios, es posible distribuir la aplicación en Google Play para todos los dispositivos que ejecutan Android 2.3 o una versión superior, y algunos servicios incluso dan soporte para más dispositivos.

Page � of �77 188

Page 78: UniSubject - rodin.uca.es

La aplicación desarrollada durante el presente proyecto utiliza el servicio Google Maps (Google Maps Android API v2) para cumplir su objetivo de mostrar la ubicación de las universidades y facultades en la mapa, El servicio de Google Maps puede activarse desde la consola de desarrolladores de Google (Google Developers Console), donde se obtiene una API KEY, que debe ser incluida en el código de la aplicación, a su vez, el desarrollador debe registrar sus aplicaciones en la consola mediante su huella SHA1 y el nombre del paquete principal de la aplicación. Actualmente Google Maps tiene una cuota de uso ilimitada.

Android Asynchronous Http Client Desarrollada por el desarrollador británico James Smith, y lanzada bajo la licencia de software libre Apache 2.0, Android Asynchronous Http Client es un cliente asíncrono basado en la devolución de llamadas para Android, construido sobre las librerías HttpClient de Apache. Todas las llamadas son realizadas fuera del hilo principal de la UI, pero cualquier lógica de devolución de llamada es ejecutada en el mismo hilo en el que la devolución de llamada fue creada, utilizando el paso de mensajes del Hanlder de Android. También es posible utilizarla en un servicio o hilo en segundo plano, la biblioteca detectará automáticamente en qué contexto se está ejecutando. Se trata de una biblioteca ampliamente utilizada en la producción de aplicaciones de gran nivel y por desarrolladores relevantes. Entre las miles de aplicaciones que utilizan actualmente esta biblioteca destacan Instagram, Pinterest, Frontline Commando, Heyzap o Pose.

El cliente del sistema, la aplicación móvil desarrollada durante el proyecto, utilizará esta biblioteca para realizar las peticiones al servidor de forma asíncrona, evitando de esta manera las sobrecargas en el hilo principal de la UI para mejorar el rendimiento.

En el desarrollo utilizamos el cliente HTTPURLCONNECTION del Cliente al Servidor La clase HttpUrlConnection del paquete java.net.* permite a nuestros dispositivos android asumir las características de un cliente HTTP ligero. Su funcionamiento está condicionado a las versiones superiores a Gingerbread. Para versiones anteriores debes usar el cliente HttpClient de Apache.

Con esta clase podremos recibir y enviar información a través de la web, lo que potenciará nuestras aplicaciones Android. A continuación se muestran los pasos que se deben realizar para establecer una conexión exitosa.

Page � of �78 188

Page 79: UniSubject - rodin.uca.es

Comprobar si la conexión a la red es posible Antes de iniciar el cliente Http debes comprobar si la conexión del dispositivo está habilitada, ya que puede ser posible que el Wi-fi no esté disponible o simplemente la conexión de red está fuera del rango. Para comprobar el estado de conexión usaremos los métodos getActiveNetworkInfo() e isConnected():

Se ha usado la clase ConnectivityManager para obtener las características actuales de la conexión. Esta información la guardamos en un elemento del tipo NetworkInfo con el método getActiveNetworkInfo(). Luego comprobamos si se retornó algún dato y si además el dispositivo está conectado con isConnected().

Abrir la conexión hacia el servidor El primer paso para iniciar la comunicación es abrir la conexión hacia el recurso alojado en el servidor. Para ello se usa el método openConnection() de la clase URL. El resultado que se obtenga debe ser casteado a HttpUrlConnection para que el cliente sea instanciado:

Obtener datos con el método GET Si deseas descargar datos desde la URL especificada simplemente usas el método getIntpuStream() para obtener el flujo de datos asociado al recurso que se encuentra en esa dirección:

Es importante que al finalizar tus operaciones de conexión liberes la memoria asociada a la instancia de la conexión realizada. Para ello usa el método disconnect(), el cual pone a disposición de nuevo una futura reconexión.

Recuerda que un tipo InputStream debe ser decodificado para interpretar su contenido, ya sea texto plano, imagen, JSON, audio, etc. Dependiendo del objetivo así mismo debes usar los métodos y técnicas correspondientes.

Posterior información con el método POST Si deseas publicar información en un servidor debes abrir la conexión al igual que con GET. Luego se indica a la conexión que se permite el envío de datos hacia el servidor con el método setDoOutput().

Seguidamente se declaran los datos que se enviarán al destino, para los cuales debes declarar el tamaño que ocuparán para ser transmitidos por el flujo.

Si su tamaño es fijo, entonces usa el método setFixedLengthStreamingMode(), quién recibe como parámetro la cantidad de bytes.

Si el tamaño es incierto (normalmente esta situación se da en transmisiones Streaming), entonces usa setChunkedStreamingMode().

Page � of �79 188

Page 80: UniSubject - rodin.uca.es

Reuniendo todas estas características, Monstalkers hace su publicación de comentarios de la siguiente forma:

Subir un archivo hacia un servidor con el método POST En la sección anterior se usó el tipo de contenido application/x-www-form-urlencoded para enviar datos atómicos hacia el servidor, pero… ¿Qué hacer para subir un archivo?

Una de las formas es usar el tipo de contenido multipart/form-data del estándar W3C para enviar datos binarios de gran tamaño. Pero la verdad me resulta complicado preparar todas las sentencias de texto requeridas para dirigir el flujo de información.

En su lugar puedes publicar el archivo directamente como bytes puros a través de getOutputStream() de la siguiente forma:

Establecer peticiones HTTP en segundo plano usando Asynctask El tiempo que tarda la transmisión de datos en la red depende de muchos factores, como el tamaño de la información a intercambiar, los tiempos de latencia, la congestión del servidor o incluso la ejecución de múltiples tareas distintas en el sistema operativo. Cualquiera de estas situaciones puede prolongar el tiempo de una petición indefinidamente.

Pero como tú ya sabes, las tareas asíncronas nos auxilian en estas situaciones. Solo debemos crear una nueva instancia de la clase AsyncTask e incluir la petición al servidor en el método doInBackground() y luego actualizar los resultados visuales en onPostExecute().

Lee también Uso de Hilos y tareas asíncronas (AsyncTask) en Android

Por ejemplo, la obtención de todos los comentarios que se han guardado en el servidor de monstalker ha sido encapsulada en una clase llamada GetCommentsTask:

Aplicación Android Como se ha comentado con anterioridad en la presente memoria, la aplicación móvil será el elemento a través del cual los usuarios interactúen con el sistema, por lo tanto, dicha aplicación representará el papel de la parte cliente en el modelo cliente-servidor. La aplicación realizará las peticiones al servicio web de la parte servidor mediante el protocolo HTTP, utilizando la biblioteca Android Asynchronous HTTPURLCONNECTION. El cliente también será capaz de interpretar las respuestas del servidor, que seguirán una estructura propia que garantiza una comunicación suficientemente fluida entre ambas parte

Page � of �80 188

Page 81: UniSubject - rodin.uca.es

4.1.3 Arquitectura de diseño

Capa de presentación La capa de presentación del sistema está formada por el conjunto de actividades, estilos y recursos que componen la interfaz de usuario de la aplicación móvil. Así pues, el sistema cuenta con una serie de documentos XML que definen la estructura y el estilo visual de cada pantalla, una colección de elementos gráficos, y en un nivel inferior un conjunto de actividades Android, escritas en Java, que se encargan de ofrecer funcionalidad a los elementos de dichas pantallas, permitiendo la obtención de los datos de entrada proporcionados por el usuario y la representación de los datos de salida resultantes.

Capa de negocio La capa de negocio incluye a todos aquellos elementos que realizan las operaciones principales del sistema, utilizando los datos proporcionados por los usuarios en la Capa de presentación para generar resultados y devolverlos de nuevo al usuario a través de la interfaz de usuario. En la parte cliente de esta capa podemos encontrar un conjunto de clases Java que representan a los elementos que intervienen en la resolución del problema, así como las operaciones que pueden realizarse sobre ellos. En la parte servidor se encuentra el conjunto de scripts PHP que realizan operaciones con los datos enviados por la parte cliente.

Capa de acceso a datos Esta capa la componen los elementos encargados de realizar las tareas intermedias entre la Capa de negocio y las bases de datos. Por lo tanto, se encuentran en esta capa todos los elementos que pueden acceder directamente a los datos para proporcionarlos a la capa superior. En la parte cliente del sistema esta tarea la realizan una serie de clases Java encargadas de gestionar la entrada y salida de datos en la base de datos local SQLite.

En la parte servidor podemos encontrar dos tipos de elementos que realizan esta tarea, por un lado tenemos una clase escrita en PHP que contiene métodos específicos para el acceder a la base de datos MySQL y un conjunto de rutinas almacenadas en la propia base de datos, que pueden ser invocadas desde la Capa de negocios para que realicen operaciones a partir de los datos almacenados y proporcionen el resultado.

Page � of �81 188

Page 82: UniSubject - rodin.uca.es

4.1.4 Diagrama de Arquitectura

Diagrama de arquitectura

1 - El cliente envía una solicitud mediante protocolo HTTP 2 - El servicio web consulta la base de datos MySQL mediante script PHP3 - La base de datos MySQL devuelve la información 4 - El servicio web procesa, formatea y devuelve la información mediante script PHP5 - El cliente interpreta y muestra la información 6 - El cliente almacena la información más utilizada localmente en SQLite para agilizar futuras consultas

Page � of �82 188

Page 83: UniSubject - rodin.uca.es

4.1.5 Diagrama de estructura en capas

Diagrama de estructura en capas

Page � of �83 188

Page 84: UniSubject - rodin.uca.es

4.2 Diseño de la interface usuario

En esta sección se especifican las interfaces entre el sistema y el usuario, detallando el aspecto y el comportamiento de las diferentes pantallas del sistema, de acuerdo con el entorno tecnológico definido anteriormente. Para cada pantalla se incluye una breve descripción, un prototipo de su aspecto y el conjunto de acciones disponibles para los elementos que las componen. Finalmente, se incluye un diagrama de navegación, que refleja la secuencia de pantallas a las que tienen acceso el usuario y la conexión que existe entre éstas.

4.2.1 Iniciar sesión

Descripción Es la primera pantalla que aparecerá cuando se lance la aplicación y no exista ninguna sesión iniciada en el dispositivo móvil. Su función principal será precisamente permitir que un usuario registrado pueda iniciar sesión en el sistema para acceder al mismo. El usuario puede registrarse o iniciar sesión en el sistema.

Page � of �84 188

Page 85: UniSubject - rodin.uca.es

Acciones disponibles

El usuario podrá introducir sus parámetros de inicio de sesión (e-mail y contraseña) en los campos de texto habilitados para ello, y en caso de que dichos parámetros sean correctos, podrá acceder al sistema pulsando el botón Iniciar sesión. Si el usuario se equivoca puede pulsar el botón CLEAR para borrar los datos de los campos y empieza de nuevo.

Si el usuario no esta registrado en el sistema o ha introducido los datos incorrectos, el sistema le notifica y muestra el opción a registrarse en el sistema como usuario nuevo pulsando el enlace Registrarse, que le llevará a la pantalla Registrar usuario

Page � of �85 188

Page 86: UniSubject - rodin.uca.es

4.2.2 | Registrar usuario

Descripción Es la pantalla a través de la cual el usuario llevará a cabo su proceso de registro en el sistema. El usuario podrá acceder a esta pantalla desde la pantalla Iniciar sesión también. El usuaria introducir sus datos en los campos habilitado. No es necesario datos personales para registrarse en el sistema. En el diseño del sistema se toma en consideración the sencillas y eficaz para ahorrar tiempo para el usuario.

Al introducir el email, nombre de usuario y contraseña y pulsa el botón REGISTRAR si el formato de email es correcto y el usuario no estado registrado anteriormente en el sistema con dicha email o nombre de usuario, el usuario se queda registrado en el sistema. Ya como usuario registrado se puede hacer uso a los servicios del sistema.

.

Page � of �86 188

Page 87: UniSubject - rodin.uca.es

4.2.3 | Registrar una universidad

Un usuario puede registrarse en el sistema como una entidad universitaria con el fin de hacer su universidad ser visto por los usuarios del sistema. El sistema solicita los siguientes datos sobre la universidad:

•Nombre de la universidad •Año de establecimiento •El numero de población de estudiante •Numero de teléfono •Email de la oficina de contacto •Dirección •Pais •Continente •Una descripción de la universidad •Una descripción de una linea •Pagina web

Al verifica los datos por el sistema la universidad se queda registrado en el sistema. En el siguiente pantalla el sistema solicita que el usuario registra al menos una facultad de la universidad solicitando los siguientes datos: •Nombre de la facultad •El numero de población de estudiante •Numero de teléfono •Email de la oficina de contacto •Dirección •Una descripción de la universidad •Una descripción de una linea •Pagina web

Al verifica los datos por el sistema la facultad se queda registrado en el sistema. En el siguiente pantalla el sistema solicita que el usuario registra al menos un major de la facultad registrado anteriormente.

Page � of �87 188

Page 88: UniSubject - rodin.uca.es

El sistema solicita los siguiente datos del major a registrar: • El nombre del major • Un imagen • Una pagina web • El nombre de la faculte a que pertenece

Al verifica los datos por el sistema el major se queda registrado en el sistema. En el siguiente pantalla el sistema solicita que el usuario registra las asignaturas que pertenece a dicha major. El sistema solicita los siguiente datos del major a registrar:

• Nombre de asignatura • Descripción • El nombre del major a que pertenece

Al verifica los datos por el sistema la asignatura se queda registrado en el sistema.

Al finalizado este secuencia de registraron el usuario puede publicar su entidad al publico y así todos los usuarios del sistema lo puede consulta.

4.2.4 | Modificación del perfil de usuario

Para modificar el perfil de usuario el usuario tiene que iniciar session como miembro del sistema y dueño del perfil a modifica. al elegir la opción para modificar el sistema cargar los datos almacenado en los campos a la deposición a ser cambiado. Al terminar las modificaciones el usuario pulsa el botón update. El sistema comprobar los datos y se queda modificado.

Dicha proceso es equal para el perfil de universidad, facultad, major y asignatura.

Page � of �88 188

Page 89: UniSubject - rodin.uca.es

El usuario puede optar en eliminar cualquier de su perfil pero con los siguiente constrain:

• Si el usuario elimina su perfil personal, todas las otras perfiles que pertenece a dicha usuario se quedan eliminado permanente.

• Si el usuario elimina su perfil universidad todos los perfiles de facultad, major y asignaturas se quedan eliminados permanente .

• Si el usuario elimina una de sus perfiles facultad, solo las majors y asignatura que pertenece a dicha facultad se quedan eliminados permanentes.

• Si el usuario elimina una de sus perfiles major, solo las asignaturas que pertenece a dicha major se quedan eliminados permanentes.

• El usuario puede eliminar una de sus perfiles asignatura de cualquier de sus majors pero un major no puede quedar sin asignatura.

• Si un major esta sin asignatura se queda en modo inactivo y no puedesre visto por los usuarios del sistema.

• Si un facultad no tiene al menos un major se queda como inactivo en el sistema. • Si una universidad no tiene al menos un facultad se queda inactiva.

4.2.5 | Consultar su perfil

El usuario registrado en el sistema y haber iniciado sesión en el sistema puede consultar su perfil personal y los perfiles de su universidad, facultad, major y asignatura. Para acceder al perfil de una asignatura el usuario tiene que seguir los siguientes pasos: •Iniciar sesión en el sistema. •Elige de un menu la universidad, •Elige la facultad del drop down menu •Elige el major del drop down menu •Elige la asignatura del drop down menu

Page � of �89 188

Page 90: UniSubject - rodin.uca.es

En el perfil de la universidad se encuentra los datos básicas sobre la universidad para poder ponerse en contacto, visitar el pagina web, escribirles un email, ver su ubicación en el google map, su lista de facultades, según la facultad que elige de la lista puede ver su datos y ubicación en google map y su lista de majors. Al elegir cualquier major se muestra su perfil y una lista de asignatura que pertenece a dicha major. Estos secuencia se puede repetir tantas veces como quiere.

Hay un botón LIST que muestran una lista con todas las universidades registrado en el sistema.

El botón HOME te lleva al pantalla principal de servicios.

El botón GALLERY abre la galleria.

4.2.6 | Listar todos los perfiles de las universidades

El la lista de universidades se muestra datos como un link a la pagina web de la universidad y datos de contacto, sera por teléfono p email.

Al pulsar cualquier universidad se abrir su perfil detallada y sus facultades, majors y asignaturas.

El botón HOME te lleva al pantalla principal de servicios.

Page � of �90 188

Page 91: UniSubject - rodin.uca.es

4.2.6 | La pantalla principal de servicios

Un usuario al iniciar sesión se abrir la pantalla principal “Compare University Studies” Aparece la mapa de google con todas las universidades registrada en el sistema señalizada. La hacer un tap sobre la marcadora se muestra una pequeña de sc r ipc ión sob re l a universidad y al hacer un tap en la pantalla se cierra la pequeño ventana. Si haz doble tap en la mapa se zoom in .

La primera opción de servicio es elegir una universidad de la lista desplegable. luego tiene la opción a ver su ubicación en la mapa pulsando el botón MAP. La otra servicio sobre la universidad elegido es ver su perfil pulsando el botón CLICK FOR MORE INFO.

A continuación tiene la opción a elegir 2 universidades a comparar pero puede ver su ubicación en el mapa de google

antes que hacer la comparación lo cual es opcional. Al pulsar el botón COMPARAR UNIVERSITIES una pantalla se abre en modo horizontal con el perfil de los 2 universidades uno al lado de la otra. Lo cual aporta una visual estupendo para la comparación de la ubicación, la lista de facultad, de los diferentes majors y de las a asignatura.

Page � of �91 188

Page 92: UniSubject - rodin.uca.es

4.2.6 | Compare estudios universitarios

Page � of �92 188

Page 93: UniSubject - rodin.uca.es

4.3 Diseño de datos

En esta sección se define la estructura física de datos que utilizará el sistema, a partir del modelo de conceptual de clases realizado durante el proceso de análisis del sistema, de manera que teniendo presente los requisitos establecidos para el sistema de información y las particularidades del entorno tecnológico (MySQL), se consiga un acceso eficiente de los datos almacenados.

4.3.1 Esquema EER de la base de datos

Page � of �93 188

Page 94: UniSubject - rodin.uca.es

Page � of �94 188

Page 95: UniSubject - rodin.uca.es

Capítulo 5. Implementation del sistema

Este capítulo trata sobre todos los aspectos relacionados con la implementación del sistema en código, haciendo uso de un determinado entorno tecnológico.

5.1 Entorno tecnología

Android Studio es el entorno oficial de desarrollo integrado (IDE) para el desarrollo de la plataforma Android. Se anunció el 16 de mayo de 2013 a la conferencia Google I / O. Android Studio está disponible libremente bajo la licencia Apache 2.0. Android estudio fue a principios de la etapa de acceso previsualización partir de la versión 0.1 en mayo de 2013, después entró en fase beta a partir de

la versión 0.8 que fue lanzado en junio de 2014. La primera versión estable fue lanzado en diciembre de 2014, a partir de la versión 1.0.

• Android Studio es el IDE oficial para el desarrollo de aplicaciones para Android, basado en IntelliJ IDEA . Además de las capacidades que esperamos de IntelliJ, Android Studio lo ofrece:

• Sistema de construcción a base de Gradle Flexible • Construir variantes y múltiples apk generación de archivos • plantillas de código para ayudarle a construir características de la aplicación

comunes • editor de diseño rico con soporte para la edición de arrastrar y soltar el tema • herramientas para la captura de rendimiento, facilidad de uso, compatibilidad de

versiones, y otros problemas • ProGuard capacidades y la aplicación de firma • El soporte integrado para Cloud Platform Google, por lo que es fácil de integrar

Google Cloud Mensajería y App Engine • Y mucho más

Si eres nuevo en Android Studio o la interfaz de IntelliJ IDEA, específicamente Android Studio hay documentación en su pagina web y consulte las páginas en el flujo de trabajo de la sección, como la gestión de proyectos desde Android estudio y la creación y ejecución de Android Studio .

Estructura del proyecto y Archivo

Android vista de proyecto De forma predeterminada, Android Studio muestra los archivos del proyecto en el Android vista del proyecto. Esta vista muestra una versión aplanada de la estructura del proyecto que proporciona un acceso rápido a los archivos de código fuente clave de los proyectos de Android y le ayuda a trabajar con el sistema de construcción

Page � of �95 188

Page 96: UniSubject - rodin.uca.es

basado en Gradle . El androide vista del proyecto:

• Muestra los directorios de origen más importantes en el nivel superior de la jerarquía módulo.

• Grupos Los archivos de creación para todos los módulos en una carpeta común.

• Grupos todos los archivos de manifiesto para cada módulo en una carpeta común.

• Muestra los archivos de recursos de todos los conjuntos de código Gradle.

• Grupos de recursos archivos para diferentes lugares, orientaciones y tipos de pantalla en un solo grupo por tipo de recurso.

Figura 5.1 Muestra la vista del proyecto Android.

Figura 5.2 Mostrar archivos de generación de proyectos.

Page � of �96 188

Page 97: UniSubject - rodin.uca.es

El androide vista de proyecto muestra todos los archivos de creación en el nivel superior de la jerarquía del proyecto bajo Scripts Gradle . Cada módulo de proyecto aparece como una carpeta en el nivel superior de la jerarquía del proyecto y contiene estos cuatro elementos en el nivel superior:

• java / - archivos fuente del módulo.• manifiestos / - Los archivos de manifiesto para el módulo.• res / - Archivos de recursos para el módulo.• Scripts Gradle / - Gradle construir y archivos de propiedades.

Por ejemplo, Android grupos vista del proyecto todas las instancias de la ic_launcher.png recurso para diferentes densidades de pantalla bajo el mismo elemento.

Otras Vistas de Android Studio Cuando se utiliza la vista de Proyecto en Android Studio, Nos da cuenta que la estructura del proyecto aparece diferente de lo que estamos acostumbrado en Eclipse. Cada instancia de Android Studio contiene un proyecto con uno o más módulos de la aplicación. Cada carpeta módulo de aplicación contiene los conjuntos de fuente completo para ese módulo, incluyendo src / main / y src / androidTest / directorios, recursos, archivos de construir y el manifiesto de Android. En la mayor parte, tendremos que modificar los archivos bajo de cada módulo src / main / directorio para actualizaciones de código fuente, el archivo gradle.build para la especificación de construcción y los archivos bajo src / androidTest / directorio para la creación de casos de prueba

Figura 5.3 Vista Android Estudio Proyecto estructura

Page � of �97 188

Page 98: UniSubject - rodin.uca.es

Sistema Build Android El sistema de construcción Android es el conjunto de herramientas que utiliza para construir, probar, ejecutar y empaquetar sus aplicaciones. Este sistema de construcción reemplaza el sistema Ant utilizado con Eclipse ADT. Puede funcionar como una herramienta integrada en el menú Android Estudio e independientemente de la línea de comandos. Puede utilizar las características del sistema de construcción de:

• Personalizar, configurar y ampliar el proceso de construcción. • Crea varios archivos APK para su aplicación con diferentes funciones

utilizando el mismo proyecto y los módulos. • La reutilización de código y recursos a través de conjuntos de origen.

La flexibilidad del sistema de construcción Android le permite lograr todo esto sin necesidad de modificar los archivos de origen del núcleo de su aplicación.

Depuración y rendimiento Android Studio ofrece una serie de mejoras para ayudarle a depurar y mejorar el rendimiento de su código, incluyendo una mejora de la gestión de dispositivo virtual, la depuración en línea y herramientas de análisis de rendimiento.

Dispositivo virtual Android (AVD) Administrador Administrador de AVD ha actualizado pantallas con enlaces para ayudarle a seleccionar las configuraciones de los dispositivos, los tamaños de pantalla más populares y resoluciones para tus vistas previas de aplicaciones.

El Administrador AVD viene con emuladores para Nexus 6 y Nexus 9 dispositivos y también apoya la creación de pieles de dispositivos Android personalizado basado en las propiedades del emulador específicos y asignando esas pieles a los perfiles de hardware. Android Estudio instala el Intel® x86 hardware acelerado Ejecución Manager (HAXM) acelerador emulador y crea un emulador por defecto para la aplicación rápida de prototipos.

Depuración en línea Utilice la depuración en línea para mejorar sus códigos paseos virtuales en la vista depurador con la verificación en línea de referencias, expresiones y valores de las variables. Información de depuración en línea incluye:

• Valores de variables en línea • Objetos referencia que hacen referencia a un objeto seleccionado • Valores de retorno Método • Lambda y expresiones de operador • los valores punta de la herramienta

Page � of �98 188

Page 99: UniSubject - rodin.uca.es

La memoria y la CPU del monitor Android Studio proporciona una vista de la memoria y la CPU del monitor para que pueda controlar más fácilmente el rendimiento y uso de memoria de su aplicación para rastrear el uso de la CPU, encontrar objetos desasignado, localizar fugas de memoria, y un seguimiento de la cantidad de memoria del dispositivo conectado está utilizando. Con su aplicación se ejecuta en un dispositivo o emulador, haga clic en el Android pestaña en la esquina inferior izquierda de la ventana de tiempo de ejecución para iniciar la ventana de tiempo de ejecución de Android. Haga clic en la memoria o CPU pestaña.

Figura 5.4 memoria del monitor y el uso de la CPU.

Volcado Montón Cuando se va a monitorear el uso de memoria en Android Studio puede, al mismo tiempo, iniciar la recolección de basura y volcar el montón de Java a una instantánea de pila en un archivo de formato binario HPROF-Android específica. El visor muestra HPROF clases, instancias de cada clase, y un árbol de referencia para ayudarle a rastrear el uso de memoria y encontrar pérdidas de memoria

Figura 5.5 espectador HPROF con volcado de pila. Page � of �99 188

Page 100: UniSubject - rodin.uca.es

Rrastreador de asignación Android Studio permite realizar un seguimiento de la asignación de memoria, ya que monitorea el uso de memoria. El seguimiento de la asignación de memoria le permite monitorear el que los objetos se asignan al realizar determinadas acciones. Conociendo estas asignaciones permite ajustar las llamadas a métodos relacionados con esas acciones para optimizar el rendimiento y el uso de memoria de la aplicación.

"

Figura 5.6 rastreador de asignación.

Page � of �100 188

Page 101: UniSubject - rodin.uca.es

Realice los siguientes pasos para realizar un seguimiento y analizar las asignaciones: 1 Haga clic en el icono de Seguimiento de Asignación Start / Stop() en el

monitor de memoria. Android Estudio comienza seguimiento asignaciones de memoria.

2 Realizar las tareas cuya mallocs desea realizar un seguimiento. 3 Haga clic en el icono de Seguimiento de Asignación de inicio / parada de nuevo. Android Studio detiene mallocs seguimiento y guarda los datos en un archivo denominado Asignación-aaaa.mm.dd-hh.mm.ss.alloc . El archivo resultante aparece en la Captura ficha. 4 Haga doble clic en el archivo para abrirlo en el visor de la asignación.

El visor de asignación le permite ver y analizar las asignaciones de su aplicación mientras se ejecuta

Acceso a los archivos de datos Las herramientas de SDK de Android, como Systrace, Logcat y Traceview, generan datos de rendimiento y de depuración para el análisis detallado de aplicaciones. Para ver los archivos de datos generados disponibles, haga clic en Captura en la esquina izquierda de la ventana de tiempo de ejecución. En la lista de los archivos generados, haga doble clic en un archivo para ver los datos. Haga clic derecho en cualquier .hprof archivos para convertirlos a un estándar .hprof formato de archivo

Inspecciones de código En Android Studio, el configurada hilo y otras inspecciones IDE se ejecutan automáticamente cada vez que se compila el programa. Además de los configurados c hilo cheques adicionales inspecciones de código IntelliJ y anotación de validación plazo para agilizar la revisión de código.

Android Studio permite a varios hilo comprobaciones para asegurar: • Cipher.getInstance () se usa con valores seguros • En vistas personalizadas, la declare-styleable asociado para la vista

personalizada utiliza el mismo nombre base que el nombre de la clase • Control de seguridad para inyección fragmento • Dónde asignación de propiedad alguna vez ya no funciona como se esperaba • Versión del plugin Gradle es compatible con el SDK • Derecho a la validación izquierda • versión de la API requerida • muchos otros

Al pasar por encima de un error de inspección muestra la edición en línea explicación completa para facilitar la resolución de errores. También hay un hipervínculo útil al final del mensaje de error para la información de error adicional. Con Android de estudio, también puede ejecutar el hilo de inspecciones para construir una variante específica, o para todos construir variantes. Puede configurar las hilo

Page � of �101 188

Page 102: UniSubject - rodin.uca.es

inspecciones que se ejecutan mediante la adición de un lintOptions (Opción de hilo) lintOptions propiedad a la configuración de Android en el build.gradle archivo.

También puede administrar perfiles de inspección y configurar las inspecciones dentro de Android Studio. Elija Archivo> Configuración> , ampliar las Editor de opciones y seleccione Inspecciones . La configuración de Inspección página aparece con las inspecciones compatibles.

Figura 5.7 inspecciones Configurar

Nota: Para cambiar el comportamiento de las notificaciones de inspección específicas, cambiar el grado de inspección, por ejemplo de advertencia de error . Para ejecutar manualmente inspecciones en Android de estudio, elija Analizar-> Inspeccionar Código.

Page � of �102 188

android     {lintOptions {// establecidas en true para apagar el progreso de análisis de informes por pelusa               tranquila verdadera        // si es cierto, detener la Gradle construir si se encuentran errores        abortOnError falsa        // si es cierto, solamente reportar errores        ignoreWarnings     verdadera}

Page 103: UniSubject - rodin.uca.es

Anotaciones en Android Studio Android Studio es compatible con anotaciones para las variables, parámetros y valores de retorno para ayudar a capturar errores, como excepciones de puntero nulo y los conflictos de tipo de recursos. El SDK de Android Manager empaqueta el Anotaciones - biblioteca en el Repositorio de Soporte Android para su uso con Android Studio. Android Studio valida las anotaciones configura durante la inspección de código.

Para añadir anotaciones a su código de Android de estudio, primero agregar una dependencia para el Apoyo a las anotaciones de biblioteca: 1 Seleccione Archivo> Estructura del proyecto . 2 En la estructura del proyecto de diálogo, seleccione el módulo deseado, haga

clic en el Dependencias ficha. 3 Haga clic en el " icono para incluir una dependencia Biblioteca. 4 En el Elija Biblioteca Dependencia de diálogo, seleccione support-anotaciones

y haga clic en OK . El build.gradle archivo se actualiza con el apoyo de las anotaciones - dependencia. También puede agregar manualmente esta dependencia a la archivo build.gradle, como se muestra en el siguiente ejemplo.

Nullabilidad inferir (Inferring nullability) Un escaneo de la análisis de nullabilidad los contratos a lo largo de las jerarquías de método en su código para detectar:

• Llamadas a métodos que pueden devolver nulo • Los métodos que no debe devolver null • Variables, tales como campos, variables locales y parámetros, que pueden ser

nulos • Variables, tales como campos, variables locales y parámetros, que no puede

contener un valor nulo

Page � of �103 188

dependencias {     compilan fileTree ( dir : 'libs' , include : [ '*.jar' ])     compile 'com.android.support:appcompat-v7:22.0.0'     compile 'com.android.support:support-annotations:22.0.0' }

Page 104: UniSubject - rodin.uca.es

El análisis a continuación, inserta automáticamente las anotaciones nulos adecuadas en los lugares detectados.

Para ejecutar un análisis de nullabilidad en Android Studio, seleccione la Analizar> Infer Nulidad opción de menú. Android Studio inserta el Android Nullable y NonNull anotaciones en lugares detectados en su código. Después de ejecutar un análisis nula, es una buena práctica para verificar las anotaciones inyectados.

Validación de anotaciones También puede agregar manualmente nullabilidad, recursos y anotaciones enumerados a través de su código para realizar validaciones para una variedad de valores de referencia, tales como R.string recursos, Drawable recursos, color recursos y enumeró constantes. Ejecutar Analizar> inspeccionar el código para validar las anotaciones configuradas.

Para obtener una lista completa de las anotaciones compatibles, o bien utilice la función de autocompletar para mostrar las opciones disponibles para el android.support.annotation importación declaración o ver el contenido de la Ayuda-Anotaciones biblioteca.

Mensajes de registro Cuando se construye y ejecuta su aplicación con Android Studio, puede ver los mensajes de registro BAD y de dispositivo (Logcat) haciendo clic en Android en la parte inferior de la ventana. Si desea depurar su aplicación con el Android Debug Monitor, puede iniciar haciendo clic monitor " en la barra de herramientas. El Monitor de depuración es donde se puede encontrar el conjunto completo de DDMS herramientas para perfilar su aplicación, el control de los comportamientos de dispositivos, y más. También incluye las herramientas del visor de Jerarquía para ayudar a optimizar sus diseños .

XAMPP 5.6.8 es un multi-plataforma de servidor web paquete de pila de soluciones de código libre y abierto desarrollado por Apache Friends, que consiste principalmente en la base de datos del Servidor Apache HTTP, MariaDB, e intérpretes de scripts escritos en el PHP y lenguajes de programación Perl. XAMPP es sinónimo de varias plataformas (X), Apache (A), MariaDB (M), PHP (P) y Perl (P). Es

una distribución simple, ligero Apache que hace que sea extremadamente fácil para los desarrolladores crear un servidor web local para realizar pruebas.

Page � of �104 188

Page 105: UniSubject - rodin.uca.es

Apple Notes es una aplicación desarrollada por Apple. Ésta se realiza en sus iOS y en los sistemas operativos OS X, esta última partida con OS X 10.8 Mountain Lion. Funciona como un servicio para hacer notas de texto cortos, que se puede sincronizar entre dispositivos que utilizan el servicio iCloud de Apple. La aplicación utiliza una interfaz similar en iOS y OS X, con un fondo con textura

de papel para notas y los iconos de color amarillo claro, lo que sugiere un lápiz o crayón.

TextWrangler / BBEdit es el editor de texto HTML y profesional líder para Macintosh. En concreto elaborado en respuesta a las necesidades de los autores web y desarrolladores de software, este premiado producto proporciona una gran cantidad de características de alto rendimiento para la edición, la búsqueda y manipulación de texto. Una interfaz inteligente proporciona un fácil acceso a las

características mejores de su clase de BBEdit, incluyendo grep coincidencia de patrones, búsqueda y reemplazo en varios archivos, herramientas de definición del proyecto, la navegación función y sintaxis coloreada para numerosos lenguajes de código fuente, plegado de código, FTP y SFTP abierta y guardar, AppleScript, Mac OS X Unix soporte de script, texto y código de finalización, y por supuesto, un conjunto completo de robustas herramientas de marcado HTML.

Con TextWrangler / BBEdit, se puede ... • El ejercicio de control total sobre texto • Su forma de trabajo • Archivos de comandos, carpetas, discos y servidores • Pruebas disfrutar de la Omnipotencia • Altura de los estándares • Integrarse sin problemas en flujos de trabajo existentes

Page � of �105 188

Page 106: UniSubject - rodin.uca.es

5.2 Código Fuente del Cliente (Aplicación Android)

5.2.1 | Estructura de directorios de un Proyecto Android

Carpeta /app/ La carpeta app es la que contiene todo lo relacionado con tu proyecto, dentro de ella se encuentran tres carpetas que son :

• manifest • java • res

Carpetas principales Estas carpetas contienen cada una de ellas archivos especificos para el funcionamiento de nuestro proyecto,las explicaremos cada una de ellas.

Page � of �106 188

Page 107: UniSubject - rodin.uca.es

Carpeta /app/manifest En esta carpeta podremos encontrar el archivo xml llamado "AndroidManifest.xml" el cual es un archivo XML que contiene nodos descriptivos sobre las características de una aplicación Android. Características como los building blocks existentes, la versión de SDK usada, los permisos necesarios para ejecutar algunos servicios.

Carpeta /app/src/main/java Esta carpeta contendrá todo el código fuente de la aplicación, clases extras, y en general todas las clases de java.Por defecto Android Studio nos crea en su interior el archivo "MainActivity.java"

Carpeta /app/src/main/res/ Contiene todos los recursos "imágenes, layouts, cadenas de texto,iconos" necesarios para el proyecto, Estos recursos se encuentran en distintas carpetas mostradas y explicadas a continuación.

Page � of �107 188

Page 108: UniSubject - rodin.uca.es

Ruta/Carpeta Descripción

Contiene los ficheros de definición XML de las diferentes p a n t a l l a s d e l a i n t e r f a z g r á f i c a . P a r a d e f i n i r distintos layouts dependiendo de la orientación del dispositivo se puede dividir también en subcarpetas:

/layout (vertical) /layout-land (horizontal)

Contiene la definición XML de los menús de la aplicación.

Contiene las imágenes [y otros elementos gráficos] usados en por la aplicación. Para poder definir diferentes recursos dependiendo de la resolución y densidad de la pantalla del dispositivo se suele dividir en varias subcarpetas:

/mipmap (recursos independientes de la densidad) /mipmap-mdpi (densidad media) /mipmap-hdpi (densidad alta) /mipmap-xhdpi (densidad muy alta) /mipmap-xxhdpi (densidad aun mas alta)

Contiene otros ficheros XML de recursos de la aplicación, como por ejemplo cadenas de texto (strings.xml), estilos (styles.xml), colores (colors.xml), arrays de valores (arrays.xml), tamaños (dimens.xml), etc.

Carpeta que contendrá los archivos de dimensión.

Contiene ficheros XML de definición de estilos y colores. style.xml(v21) es el archivo que funcionara para api 21 en adelante(Android L)

/res/values/dimens/

"

/res/mipmap/

"

/res/layout/

"

/res/values/styles/

"

/res/values/ "

/res/menu/

"

Page � of �108 188

Page 109: UniSubject - rodin.uca.es

Ahora nos enfocaremos a algunos de los principales e importantes archivos de nuestro proyecto.

dimens.xml : Archivo XML que define las dimensiones, tanto alturas como tamaños de fuentes de la interfaz de usuario. strings.xml : Archivo XML que define cadenas de texto usadas en la aplicación. lo que colocamos en botones,labels,titulos y otros. styles.xml : Archivo XML que define los estilos usados en la aplicación. Estos estilos pueden ser aplicados a los elementos de la interfaz de usuario, de modo que separamos la plantilla de las funcionalidades,asi tambien se podra ver un archivo similar(v21) el cual nos indica que esos estilos seran aplicados por defecto en dispositivos mayores a la api 21 la cual corresponde a Android L.

Page � of �109 188

Page 110: UniSubject - rodin.uca.es

5.2.2 Actividades

Una actividad es un componente de la aplicación que proporciona una pantalla con la cual los usuarios pueden interactuar para realizar alguna acción, como marcar un número de teléfono, tomar una foto, enviar un e-mail o ver un mapa. La ventana normalmente ocupa toda la pantalla, pero puede ser más pequeña que la pantalla y flotar sobre otras ventanas.

Una aplicación normalmente consiste en múltiples actividades que están más o menos ligadas entre sí. Por lo general, una de las actividades de la aplicación es especificada como la actividad "principal", que es presentada al usuario cuando lanza la aplicación por primera vez. Cada actividad puede iniciar a otra actividad para realizar diferentes acciones. Cada vez que se llama a una actividad la anterior es detenida, pero el sistema la conserva en una pila (la pila de retorno). Cuando una nueva actividad comienza, es introducida en la pila de retorno y toma la atención del usuario. La pila de retorno cumple el mecanismo "el último que entra es el primero que sale" de las pilas, por lo tanto, cuando el usuario ha acabado con la actividad actual y pulsa el botón de retorno, dicha actividad es eliminada de la pila (y destruida) y la actividad anterior se reanuda.

Page � of �110 188

Page 111: UniSubject - rodin.uca.es

Algunas de las actividades que componen la aplicación del presente proyecto :

Al iniciar sesión con el Main Activity

Page � of �111 188

package lbs.uca.es.lbs;import android.app.Activity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.content.Intent;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import java.util.ArrayList;import java.util.List;public class MainActivity extends Activity { public static int status = 0; public static UserDataDAO userDataDAO; public static UniversityDAO universityDAO; public static University university; public static FacultyDAO facultyDAO; public static MajorDAO majorDAO; public static SubjectDAO subjectDAO; public static GenericDataDAO galleryDAO; public static UserData userData; public static ArrayList<UserData> users ; public static boolean isUserLogedIn = false; public static GenericDataDAO genericDataDAO; public static List<University> universitiesUpToDate; public static University selectedUniversity = null; public static String myTable; public static ArrayList<String> myColumns; public static ArrayList<String> myValors; public static MyDataFactory myDataFactory; BackgroundTask backgroundTask; TextView txtLogin, txtRegister, txtUpdate, txtUnsubscribe; LinearLayout linearLayout; ImageView imageView; EditText edtUserName, edtPassword; TextView txtUserName, txtPassword; Button btnLogin, btnClear; String name, pass; //CONTINUA EN LA SIGUIENTE PÁGINA

Page 112: UniSubject - rodin.uca.es

Page � of �112 188

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); linearLayout = (LinearLayout)findViewById(R.id.lenLayPg1); imageView = (ImageView)findViewById(R.id.imgViewAleSoft); txtLogin = (TextView)findViewById(R.id.textViewLoginPg1); txtRegister = (TextView)findViewById(R.id.textViewRegisterPg1); txtUpdate = (TextView)findViewById(R.id.textViewUpdatePg1); txtUnsubscribe = (TextView)findViewById(R.id.textViewUnsubscribePg1); edtUserName = (EditText) findViewById(R.id.editTextPg9UserName); edtPassword = (EditText) findViewById(R.id.editTextPg9Password); txtUserName = (TextView) findViewById(R.id.textViewPg9UserName); txtPassword = (TextView) findViewById(R.id.textViewPg9Password); backgroundTask = new BackgroundTask(this); genericDataDAO = new GenericDataDAO(getApplicationContext()); userDataDAO = new UserDataDAO(getApplicationContext()); universityDAO = new UniversityDAO(getApplicationContext()); facultyDAO = new FacultyDAO(getApplicationContext()); majorDAO = new MajorDAO(getApplicationContext()); subjectDAO = new SubjectDAO(getApplicationContext()); galleryDAO = new GenericDataDAO(getApplicationContext()); userData = new UserData(); university = new University(); universitiesUpToDate = new ArrayList<University>(); users = new ArrayList<UserData>(); //Register screen click activities and act accordingly linearLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (userData != null) { if (userData.getUniAppUserStatus().equals("connect")) //Goto the principal activity startActivity(new Intent(MainActivity.this,MapsActivity.class)); else //Goto the login activity startActivity(new Intent(MainActivity.this, LoginActivity.class)); } } }); //On click the link Register, goto the registration activity txtRegister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MainActivity.userData = null; startActivity(new Intent(MainActivity.this, RegistrationActivity.class)); } }); //On click the link Login, goto the login activity txtLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { status = 0; startActivity(new Intent(MainActivity.this, LoginActivity.class)); } }); //CONTINUA EN LA SIGUIENTE PÁGINA }

Page 113: UniSubject - rodin.uca.es

Page � of �113 188

@Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //no inspection Simplificable If Statement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); }}

Page 114: UniSubject - rodin.uca.es

Login en el sistema através la Login Actividad

Page � of �114 188

package lbs.uca.es.lbs;import android.app.Activity;import android.content.Intent;import android.graphics.Color;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import java.util.ArrayList;public class LoginActivity extends Activity implements AsyncResponse { public static MyDataFactory myDataUserFactory; public static String myTable; public static University university; public static GenericDataDAO genericDataDAO; public static ArrayList<UserData> users ; public static ArrayList<String> myColumns; public static ArrayList<String> myValors; EditText edtUserName, edtPassword; TextView txtUserName, txtPassword, txtRegister; Button btnLogin, btnClear; String name, pass, method; BackgroundTask backgroundTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); edtUserName = (EditText) findViewById(R.id.editTextPg9UserName); edtPassword = (EditText) findViewById(R.id.editTextPg9Password); txtUserName = (TextView) findViewById(R.id.textViewPg9UserName); txtPassword = (TextView) findViewById(R.id.textViewPg9Password); txtRegister = (TextView) findViewById(R.id.textViewPg9Register); btnLogin = (Button) findViewById(R.id.btnPg9Register); btnClear = (Button) findViewById(R.id.btnPg9Clear); genericDataDAO = new GenericDataDAO(getApplicationContext()); myTable = "userdatas"; method = "login"; users = new ArrayList<UserData>(); myColumns = new ArrayList<String>(); myValors = new ArrayList<String>(); backgroundTask = new BackgroundTask(this); btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { loginUser(); } }); btnClear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clearTextEditor(); } }); txtRegister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(LoginActivity.this, RegistrationActivity.class)); } });} //CONTINUA EN LA SIGUIENTE PÁGINA

Page 115: UniSubject - rodin.uca.es

Page � of �115 188

public void loginUser() { //iniciate name and pass with the user written username and password name = edtUserName.getText().toString(); pass = edtPassword.getText().toString(); //Check for empty space if (name.isEmpty() || pass.isEmpty()) { if (name.isEmpty()) txtUserName.setTextColor(Color.RED); if (pass.isEmpty()) txtPassword.setTextColor(Color.RED); Toast.makeText(getBaseContext(), "You have one or more unfilled data. ", Toast.LENGTH_LONG).show(); return; } //set the delegate of the task as this activity backgroundTask.delegate = this; backgroundTask.execute(method, myUrlFactory.login_url, myTable, "id", "email", "uniAppUserName", "uniAppUserPassword", "uniAppUserRole", "uniAppUserStatus", "1", name, name, pass, "0", "0");} public void goAHead(){ if(!myColumns.isEmpty()) myColumns.clear(); if(!myValors.isEmpty()) myValors.clear(); if(MainActivity.userData.getUniAppUserPassword() != null) { myColumns.addAll(MyDataFactory.setMyColumn(myTable)); myValors.addAll(MyDataFactory.setValueForColumns("UserData", MainActivity.userData)); boolean sw = false; sw = genericDataDAO.updateData(myColumns, myValors); //ubdate the local database with user information txtRegister.setVisibility(View.INVISIBLE); if (MainActivity.userData.getUniAppUserRole() == 1) { if (MainActivity.status == 1 || MainActivity.status == 2) { //The user would like to update his account Toast.makeText(getBaseContext(), MainActivity.userData.getUniAppUserName() +", you have signed in as Admin and all changes you make will be unchangeable. ", Toast.LENGTH_LONG).show(); startActivity(new Intent(LoginActivity.this, AdminSelection.class)); } else { Toast.makeText(getBaseContext(),"Admin " + MainActivity.userData.getUniAppUserName() +", WELCOME BACK. ", Toast.LENGTH_LONG).show(); startActivity(new Intent(LoginActivity.this, MapsActivity.class)); } }else { if(MainActivity.status == 1 || MainActivity.status == 2) { Toast.makeText(getBaseContext(), MainActivity.userData.getUniAppUserName() +", you are about to edit your profile. ", Toast.LENGTH_LONG).show(); startActivity(new Intent(LoginActivity.this, UpdateUserActivity.class)); }else { Toast.makeText(getBaseContext(), MainActivity.userData.getUniAppUserName() +", WELCOME BACK. ", Toast.LENGTH_LONG).show(); startActivity(new Intent(LoginActivity.this, MapsActivity.class)); } } }else {

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 116: UniSubject - rodin.uca.es

Page � of �116 188

}else { Toast.makeText(getBaseContext(), " Your user name or password is incorrect. ", Toast.LENGTH_LONG).show(); clearTextEditor(); txtRegister.setVisibility(View.VISIBLE); } //return all colours to black in case it was changed to red txtUserName.setTextColor(Color.BLACK); txtPassword.setTextColor(Color.BLACK); } public void clearTextEditor(){ edtUserName.setText(""); edtPassword.setText(""); } //This method receive the results from the AsyncResponse query (Results from the database )@Overridepublic void processFinish(ArrayList<ArrayList<String>> output) { MainActivity.userData = null; //check to see if there was an AsyncResponse result if (!output.isEmpty()) { MainActivity.userData = (UserData) MyDataFactory.createAnObject("UserData", output.get(0)); if(MainActivity.userData.getUniAppUserRole() == 1){ MainActivity.university.setEmail(MainActivity.userData.uniAppUserEmail); } //This method will use the data the AsyncResponse delivers goAHead(); Toast.makeText(getBaseContext(), MainActivity.userData.getUniAppUserName() + ", WELCOME. From Login", Toast.LENGTH_LONG).show(); } else { Toast.makeText(getBaseContext(), "User name or password incorrect", Toast.LENGTH_LONG).show(); txtRegister.setVisibility(View.VISIBLE); } } @Override public void secondProcessFinish(ArrayList<String> secondOutputs){ } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_login, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //no inspection Simplifiable If Statement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); }}

Page 117: UniSubject - rodin.uca.es

Registrar en el sistema usando la Registrar Actividad

Page � of �117 188

package lbs.uca.es.lbs;import android.app.Activity;import android.content.Intent;import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import android.graphics.Color;import java.util.ArrayList;public class RegistrationActivity extends Activity implements AsyncResponse{ public static GenericDataDAO userDataDAO; public static ArrayList<UserData> users ; public static String myTable; public static ArrayList<String> myColumns; public static ArrayList<String> myValors; public static MyDataFactory myDataUserFactory; EditText edtUserName, edtPassword, edtConfirmPassword, edtEmail; TextView txtUserName, txtPassword, txtConfirmPassword, txtEmail; Button btnRegister, btnClear; String email, name, pass, method, confirmpass, role, status; BackgroundTask backgroundTask = new BackgroundTask(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_registration); edtUserName = (EditText) findViewById(R.id.editTextPg8UserName); edtPassword = (EditText) findViewById(R.id.editTextPg8Password); edtConfirmPassword = (EditText) findViewById(R.id.editTextPg8RPassword); edtEmail = (EditText) findViewById(R.id.editTextPg8Email); txtUserName = (TextView) findViewById(R.id.textViewPg8UserName); txtPassword = (TextView) findViewById(R.id.textViewPg8Password); txtConfirmPassword = (TextView) findViewById(R.id.textViewPg8RPassword); txtEmail = (TextView) findViewById(R.id.textViewPg8Email); btnRegister = (Button) findViewById(R.id.btnPg8Register); btnClear = (Button) findViewById(R.id.btnPg8Clear); userDataDAO = new GenericDataDAO(getApplicationContext()); myTable = "userdatas"; method = "register"; users = new ArrayList<UserData>(); myColumns = new ArrayList<String>(); myValors = new ArrayList<String>(); btnRegister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { registerUser(); } }); btnClear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clearTextEditor(0); } }); }

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 118: UniSubject - rodin.uca.es

Page � of �118 188

public void registerUser() { email = edtEmail.getText().toString(); name = edtUserName.getText().toString(); pass = edtPassword.getText().toString(); confirmpass = edtConfirmPassword.getText().toString(); role = "2"; status = "disconnect"; //Check for empty space if (name.isEmpty() || pass.isEmpty() || confirmpass.isEmpty()) { if (name.isEmpty()) txtUserName.setTextColor(Color.RED); if (pass.isEmpty()) txtPassword.setTextColor(Color.RED); if (confirmpass.isEmpty()) txtConfirmPassword.setTextColor(Color.RED); if (email.isEmpty()) txtEmail.setTextColor(Color.RED); Toast.makeText(getBaseContext(), "You have one or more unfilled data. ", Toast.LENGTH_LONG).show(); return; } if (pass.equals(confirmpass)) { //set the delegate of the task as this activity backgroundTask.delegate = this; backgroundTask.execute(method, myUrlFactory.reg_url, myTable, "id", "email", "uniAppUserName", "uniAppUserPassword", "uniAppUserRole", "uniAppUserStatus", "0", email, name, pass, role, status); clearTextEditor(1); }else { Toast.makeText(getBaseContext(), "The passwords do not match. ", Toast.LENGTH_LONG).show(); clearTextEditor(1); }} public void goAHead() { myColumns.addAll(MyDataFactory.setMyColumn(myTable)); myValors.addAll(MyDataFactory.setValueForColumns("UserData", MainActivity.userData)); boolean gb = false; gb = userDataDAO.saveData(myColumns, myValors); if (gb) { Toast.makeText(getBaseContext(), "Wellcome, " + MainActivity.userData.getUniAppUserName() + ".\n You have registered successfully.", Toast.LENGTH_LONG).show(); startActivity(new Intent(RegistrationActivity.this, RegisterUniversityActivity.class)); } else { Toast.makeText(getBaseContext(), "This user already exist. ", Toast.LENGTH_LONG).show(); clearTextEditor(0); } //return all colours to black in case it was changed to red txtEmail.setTextColor(Color.BLACK); txtUserName.setTextColor(Color.BLACK); txtPassword.setTextColor(Color.BLACK); txtConfirmPassword.setTextColor(Color.BLACK);}

public void clearTextEditor(int num){ if(num == 0) edtUserName.setText(""); edtPassword.setText(""); edtConfirmPassword.setText("");}

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 119: UniSubject - rodin.uca.es

Page � of �119 188

@Override public void processFinish(ArrayList<ArrayList<String>> output) { MainActivity.userData = null; if(!output.isEmpty()) { MainActivity.userData = (UserData) MyDataFactory.createAnObject("UserData" , output.get(0)); goAHead(); // Toast.makeText(getBaseContext(), MainActivity.userData.getUniAppUserName()+", WELCOME ... ", Toast.LENGTH_LONG).show(); }else{ Toast.makeText(getBaseContext(), "check your email or username", Toast.LENGTH_LONG).show(); } finish(); } @Override public void secondProcessFinish(ArrayList<String> secondOutputs){ } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_registration, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); }}

Page 120: UniSubject - rodin.uca.es

Consultar Perfil

Page � of �120 188

package lbs.uca.es.lbs;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;public class UserProfile extends AppCompatActivity { TextView txtEmail, txtUsername, txtRole; Button btnBack; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_user_profile); txtEmail = (TextView) findViewById(R.id.textViewPg25Email); txtUsername = (TextView) findViewById(R.id.textViewPg25userName); txtRole = (TextView) findViewById(R.id.textViewPg25Role); btnBack = (Button) findViewById(R.id.btnPg25Back); if(!MainActivity.userData.getUniAppUserEmail().equals(null)) { txtEmail.setText("Email: " + MainActivity.userData.getUniAppUserEmail()); txtUsername.setText("User Name: " + MainActivity.userData.getUniAppUserName()); if (MainActivity.userData.getUniAppUserRole() == 1) txtRole.setText("User role: Public"); else txtRole.setText("User role: Private"); } btnBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(UserProfile.this, AdminSelection.class)); } }); }}

Page 121: UniSubject - rodin.uca.es

Consultar University Profile

Page � of �121 188

package lbs.uca.es.lbs;import android.net.Uri;import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.ImageView;import android.widget.Spinner;import android.widget.TextView;import android.content.Intent;import android.view.View;import android.widget.Toast;import com.google.android.gms.maps.CameraUpdateFactory;import com.google.android.gms.maps.GoogleMap;import com.google.android.gms.maps.SupportMapFragment;import com.google.android.gms.maps.model.Marker;import com.google.android.gms.maps.model.MarkerOptions;import java.util.ArrayList;import java.util.List;public class UniDesptActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener { //represent the id for the menu items private static final int EDIT=0, DELETE=1; public static final String TAG = "UniDesptActivity"; private GoogleMap mMap; TextView txtMinDescription, txtAcronym, txtYear, txtUrl, txtAddress, txtPopul, txtInfoSubject, txtMajorIntro; TextView txtPhone, txtEmail, txtCountry, txtContinent, txtUniName, txtDescription, txtInfoMajor, txtSubject, txtMajor; Button btnPrivious, btnHome, btnAcronym, btnSubjects , btnSelectMajors, btnSelectFaculty, btnMoreFacultyInfo; ImageView imgLogo; ImageView imageImgViewUpload; Uri imageUri; int longClickedItemIndex; MapsActivity mapsActivity; SubjDesptActivity subjDesptActivity; UniversityListActivity universityListActivity; FacultyActivity facultyActivity; private Marker markerForHideShow; private MarkerOptions markerOptionsForHideShow; private boolean status = true; int requestCode; //this int is used in the request from the other activity Bundle bundleToSendDataToOtherActivity; //object to send data to other activity Spinner subjectSpinner, majorSpinner, facultySpinner; public static int spinnerSubjectItemSelectPosition, spinnerMajorItemSelectPosition, spinnerFacultyItemSelectPosition; int spinnerItemSelectPosition; List<String> majorNames, subjectNames, facultyNames; //CONTINUA EN LA SIGUIENTE PÁGINA

Page 122: UniSubject - rodin.uca.es

Page � of �122 188

public static List<Subject> subjectsTemp; public static List<Major> majorsTemp; public static List<Faculty> facultiesTemp = new ArrayList<Faculty>(); ArrayAdapter<University> unversityAdapter; public static University tempUniversity; String subs=" “; List<University> universities; List<Faculty> faculties; List<Major> majors; List<Subject> subjects; Subject subj = new Subject(); Faculty facul = new Faculty();@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_uni_despt); universities = new ArrayList<>(); universities.addAll( MainActivity.universityDAO.universitiesUpToDate) ; faculties = MainActivity.facultyDAO.facultiesUpToDate; majors = MainActivity.majorDAO.majorsUpToDate; subjects = MainActivity.subjectDAO.subjectsUpToDate; longClickedItemIndex = universityListActivity.longClickedItemIndex; subjDesptActivity = new SubjDesptActivity(); facultyActivity = new FacultyActivity(); txtSubject = (TextView)findViewById(R.id.textViewSubjects); txtInfoSubject = (TextView)findViewById(R.id.txtVPg4SemesterPrint); txtInfoMajor = (TextView)findViewById(R.id.txtVPg4facultyPrint); txtDescription = (TextView)findViewById(R.id.txtVPg4DestPrint); txtMajorIntro = (TextView)findViewById(R.id.txtVPg4Major); txtMajor = (TextView)findViewById(R.id.textViewMajors); txtDescription.setText(universities.get(longClickedItemIndex).getDescription()); txtUniName = (TextView)findViewById(R.id.txtVPg4Head); txtUniName.setText(universities.get(longClickedItemIndex).getNameUni()); txtMinDescription = (TextView)findViewById(R.id.txtVPg4HeadInfo4); txtMinDescription.setText("Description: "+universities.get(longClickedItemIndex).getInfo()); txtYear = (TextView)findViewById(R.id.txtVPg4EstbPrint); txtYear.setText("Established: "+universities.get(longClickedItemIndex).getYear()); txtUrl = (TextView)findViewById(R.id.txtVPg4UrlPrint); txtUrl.setText(universities.get(longClickedItemIndex).getWebURI().toString()); txtAddress = (TextView)findViewById(R.id.txtVPg4AddressPrint); txtAddress.setText("Address: "+universities.get(longClickedItemIndex).getAddress()); txtPopul = (TextView)findViewById(R.id.txtVPg4PopulPrint); txtPopul.setText("Population of: "+universities.get(longClickedItemIndex).getPopulation()); txtPhone = (TextView)findViewById(R.id.txtVPg4PhonePrint); txtPhone.setText("Phone: "+universities.get(longClickedItemIndex).getPhone()); txtEmail = (TextView)findViewById(R.id.txtVPg4EmailPrint); txtEmail.setText("Email: "+universities.get(longClickedItemIndex).getEmail()); txtCountry = (TextView)findViewById(R.id.txtVPg4CountryPrint); txtCountry.setText("Country: "+universities.get(longClickedItemIndex).getCountry()); txtContinent = (TextView)findViewById(R.id.txtVPg4ContinentPrint); txtContinent.setText("Continent: "+universities.get(longClickedItemIndex).getContinente()); imgLogo = (ImageView) findViewById(R.id.imgVPg4); imgLogo.setImageResource(universities.get(longClickedItemIndex).getImageUni());

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 123: UniSubject - rodin.uca.es

Page � of �123 188

imageImgViewUpload = (ImageView) findViewById(R.id.imgVPg4Upload);btnPrivious = (Button) findViewById(R.id.btnPg4Privious); btnHome = (Button) findViewById(R.id.btnPg4Home);btnAcronym = (Button) findViewById(R.id.btnPg4UniLink); btnSubjects = (Button) findViewById(R.id.btnSeeSubject); btnSelectMajors = (Button) findViewById(R.id.btnOKMajorPg4);btnSelectFaculty = (Button) findViewById(R.id.btnOKFacultyPg4);btnMoreFacultyInfo = (Button) findViewById(R.id.btnInfoFacultyPg4);imageId = R.drawable.picture; subjectSpinner = (Spinner)findViewById(R.id.spinnerPg4Semester);majorSpinner = (Spinner)findViewById(R.id.spinnerPg4Major);facultySpinner = (Spinner)findViewById(R.id.spinnerPg4Faculty);mapsActivity = new MapsActivity(); //to use this injection de codigo to get the information of the spinnersuniversityListActivity = new UniversityListActivity();facultyNames = new ArrayList<String>();majorNames = new ArrayList<String>();subjectNames = new ArrayList<String>();subjectsTemp = new ArrayList<Subject>();majorsTemp = new ArrayList<Major>();btnPrivious.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(UniDesptActivity.this, UniversityListActivity.class)); }});btnHome.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(UniDesptActivity.this, MapsActivity.class)); }});

btnAcronym.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(UniDesptActivity.this, GalleryActivity.class)); } }); btnSelectFaculty.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spinnerFacultyItemSelectPosition = facultySpinner.getSelectedItemPosition(); setFacultySpinner(); Toast.makeText(majorSpinner.getContext(), "You have selected : " + facultySpinner.getItemAtPosition(spinnerFacultyItemSelectPosition).toString()+" liks "+facultiesTemp.get(spinnerFacultyItemSelectPosition).getHits(), Toast.LENGTH_LONG).show(); } }); btnSelectMajors.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setMajorBtn(); } }); //CONTINUA EN LA SIGUIENTE PÁGINA

Page 124: UniSubject - rodin.uca.es

Page � of �124 188

btnMoreFacultyInfo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spinnerFacultyItemSelectPosition = facultySpinner.getSelectedItemPosition(); // MainActivity.facultyDAO.updateFacultyHits(facultiesTemp.get(spinnerFacultyItemSelectPosition)); if(!facultiesTemp.isEmpty()) { facul = facultiesTemp.get(spinnerFacultyItemSelectPosition); MainActivity.facultyDAO.updateFacultyHits(facul); Toast.makeText(facultySpinner.getContext(), " There are " + facultiesTemp.size() + " faculty . Faculty name is " + facul.getNameFaculty()+" liks "+facultiesTemp.get(spinnerFacultyItemSelectPosition).getHits(), Toast.LENGTH_LONG).show(); // facultyActivity.loadMajorInfo(); startActivity(new Intent(UniDesptActivity.this, FacultyActivity.class)); } } }); btnSubjects.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spinnerSubjectItemSelectPosition = subjectSpinner.getSelectedItemPosition(); if(!subjectsTemp.isEmpty()) { subj = subjectsTemp.get(spinnerSubjectItemSelectPosition); MainActivity.subjectDAO.updateSubjectHits(subj, 1); Toast.makeText(majorSpinner.getContext(), " There are " + subjectsTemp.size() + " subjects. University name " + subj.getMajor().getFaculty().getUniversity().getNameUni()+" LIKES "+subj.getMajor().getFaculty().getUniversity().getHits()+ " Faculty name "+subj.getMajor().getFaculty().getNameFaculty()+" LIKES "+subj.getMajor().getFaculty().getHits()+ " Major name "+subj.getMajor().getNameMajor()+" LIKES "+subj.getMajor().getHits()+ " Subject name "+subj.getNameSubject()+ " LIKES "+subj.getHits(), Toast.LENGTH_LONG).show(); subjDesptActivity.loadSubjectInfo(subj); startActivity(new Intent(UniDesptActivity.this, SubjDesptActivity.class)); } } }); //this allows you to click on the image to upload a image from a source file imageImgViewUpload.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //we create an Intent object which we are going to use to manage the image Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); //here we get back the url of the image startActivityForResult(Intent.createChooser(intent, " Select Contact Image"), 1); //here the result code is 1 } });}

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 125: UniSubject - rodin.uca.es

Page � of �125 188

//Here we check the intent and assign the image the user chosepublic void onActivityResult(int reqCode, int resCode, Intent data){ if (resCode == RESULT_OK) { if (reqCode == 1) { //if the result code is the same 1 as we have in the startActivityForResult, that means everything is ok imageUri = data.getData(); imageImgViewUpload.setImageURI(data.getData()); //here we ser the content image the user chose } }} public void setMajorBtn(){ spinnerMajorItemSelectPosition = majorSpinner.getSelectedItemPosition(); subjectsTemp.clear(); subjectNames.clear(); subs = "The Subjects: \n"; String majorName1 = majorNames.get(spinnerMajorItemSelectPosition); for (Subject subject : subjects) { if (subject.getMajor().getNameMajor().trim().equals(majorName1.trim())) { subjectNames.add(subject.getNameSubject()); subjectsTemp.add(subject); subs += subject.getNameSubject() +" "+subject.getHits() + " \n"; } } txtSubject.setText(subs); addItemsOnidInfoSpinner(subjectSpinner); if(majorsTemp.size() != 0) MainActivity.majorDAO.updateMajorHits(majorsTemp.get(spinnerMajorItemSelectPosition)); if (subjectNames.size() != 0) { spinnerSubjectItemSelectPosition = subjectSpinner.getSelectedItemPosition(); btnSubjects.setVisibility(View.VISIBLE); txtInfoSubject.setVisibility(View.VISIBLE); txtSubject.setVisibility(View.VISIBLE); subjectSpinner.setVisibility(View.VISIBLE); Toast.makeText(majorSpinner.getContext(), "You have selected : " + majorSpinner.getItemAtPosition(spinnerMajorItemSelectPosition).toString()+" liks "+majorsTemp.get(spinnerMajorItemSelectPosition).getHits() + " and " + subjectSpinner.getItemAtPosition(spinnerSubjectItemSelectPosition).toString()+" like "+subjectsTemp.get(spinnerSubjectItemSelectPosition).getHits(), Toast.LENGTH_LONG).show(); } else { spinnerSubjectItemSelectPosition = 0; Toast.makeText(majorSpinner.getContext(), subjects.size() + " Thereare no subjects for this major: " + majorSpinner.getItemAtPosition(spinnerMajorItemSelectPosition).toString(), Toast.LENGTH_SHORT).show(); }

} //CONTINUA EN LA SIGUIENTE PÁGINA

Page 126: UniSubject - rodin.uca.es

Page � of �126 188

// add items into spinner dynamicallypublic void addItemsOnidInfoSpinner(Spinner theSpinner) { ArrayAdapter<String> dataAdapter; if(theSpinner == facultySpinner){ dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, facultyNames); }else if(theSpinner == majorSpinner) { dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, majorNames); }else { dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, subjectNames); } dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); theSpinner.setAdapter(dataAdapter);} public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) { spinnerItemSelectPosition = (int)parent.getItemAtPosition(pos); Toast.makeText(parent.getContext(), "Major Selected : " + parent.getItemAtPosition(pos).toString() + " " + spinnerItemSelectPosition, Toast.LENGTH_LONG).show();} @Overridepublic void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub} @Overrideprotected void onResume() { super.onResume(); loadUniInfo(); setUpMapIfNeeded();} private void setUpMapIfNeeded() { // Do a null check to confirm that we have not already instantiated the map. if (mMap == null) { // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.Pg4Map)).getMap(); mMap.setMyLocationEnabled(true); // Check if we were successful in obtaining the map. if (mMap != null) { setUpMap(); } }}

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 127: UniSubject - rodin.uca.es

Page � of �127 188

/** * This is where we can add markers or lines, add listeners or move the camera. In this case, we * just add a marker near Africa. * <p/> * This should only be called once and when we are sure that {@link #mMap} is not null. */private void setUpMap() { //Set markers on the map mMap.addMarker(new MarkerOptions().position(mapsActivity.getMapInfoses().get(longClickedItemIndex).getCordinate()). title(MapsActivity.mapInfoses.get(longClickedItemIndex).getName()). snippet(MapsActivity.mapInfoses.get(longClickedItemIndex).getInfo() + "\n" + mapsActivity.getMapInfoses().get(longClickedItemIndex).getWebUrl())); //para zoom in en la locacion mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(MapsActivity.mapInfoses.get(longClickedItemIndex).getCordinate(), 15));} public void loadUniInfo(){ subs=""; facultiesTemp.clear(); facultyNames.clear(); for (Faculty faculty : faculties) { if (faculty.getUniversity().getNameUni().toString().trim().equals(universities.get(longClickedItemIndex).getNameUni().toString().trim())){ facultyNames.add(faculty.getNameFaculty()); facultiesTemp.add(faculty); } } addItemsOnidInfoSpinner(facultySpinner); //lets create the views for our different items and set the text to be displaied}

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 128: UniSubject - rodin.uca.es

Page � of �128 188

public void setFacultySpinner() { majorsTemp.clear(); majorNames.clear(); subjectsTemp.clear(); subjectNames.clear(); String maj = "The Majors: \n"; String facultyName1 = facultyNames.get(spinnerFacultyItemSelectPosition); for (Major major : majors) { if (major.getFaculty().getNameFaculty().trim().equals(facultyName1.trim())) { majorNames.add(major.getNameMajor()); majorsTemp.add(major); maj += major.getNameMajor() +" HITS "+ major.getHits()+ " \n"; } } if(facultiesTemp.size() != 0) MainActivity.facultyDAO.updateFacultyHits(facultiesTemp.get(spinnerFacultyItemSelectPosition)); txtMajor.setText(maj); addItemsOnidInfoSpinner(majorSpinner); if (majorNames.size() != 0) { spinnerMajorItemSelectPosition = majorSpinner.getSelectedItemPosition(); btnSelectMajors.setVisibility(View.VISIBLE); txtInfoMajor.setVisibility(View.VISIBLE); txtMajorIntro.setVisibility(View.VISIBLE); majorSpinner.setVisibility(View.VISIBLE); txtMajor.setVisibility(View.VISIBLE); } else { spinnerMajorItemSelectPosition = 0; Toast.makeText(facultySpinner.getContext(), majors.size() + " There are no majors for this faculty: " + facultySpinner.getItemAtPosition(spinnerFacultyItemSelectPosition).toString(), Toast.LENGTH_SHORT).show(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_uni_despt, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } //A wrapper so that we don’t have to type this every time private void _(String s){ Log.d(TAG, s); }}

Page 129: UniSubject - rodin.uca.es

Page � of �129 188

package lbs.uca.es.lbs;import android.app.Activity;import android.support.v4.app.FragmentActivity;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.MotionEvent;import android.view.View;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.Spinner;import android.widget.Toast;import com.google.android.gms.maps.CameraUpdateFactory;import com.google.android.gms.maps.GoogleMap;import com.google.android.gms.maps.SupportMapFragment;import com.google.android.gms.maps.model.BitmapDescriptorFactory;import com.google.android.gms.maps.model.LatLng;import com.google.android.gms.maps.model.Marker;import com.google.android.gms.maps.model.MarkerOptions;import android.widget.AdapterView.OnItemSelectedListener;import java.util.ArrayList;import java.util.List;public class MapsActivity extends FragmentActivity implements AsyncResponse, OnItemSelectedListener { public static final String TAG = "MapsActivity"; public static int spannerItemPosoion = 0; public static int spannerItemPosoion1 = 0; public static int spannerItemPosoion2 = 0; public static University university = null; public static University university1 = null; public static University university2 = null; public static GenericDataDAO genericDataDAO; public static ArrayList<String> myColumns; public static ArrayList<String> myValors; public static MyDataFactory myDataUserFactory; public static GalleryActivity galleryActivity; BackgroundTask backgroundTask; String myTable = "universities"; String method = "user"; public static ArrayList<ArrayList<String>> universityDataCollection; //to temporary place university datapublic static List<LatLng> coordinates = new ArrayList<LatLng>();private static List<University> universities; private boolean sw = true; private GoogleMap mMap; // Might be null if Google Play services APK is not available.UniversityListActivity universityListActivity; private Button btnLogout, btnHome, btnNext, btnMoreInfo, btnCompare; private Button btnMapView, btnMapView1, btnMapView2; private Marker markerForHideShow; private MarkerOptions markerOptionsForHideShow; private boolean status = true; int requestCode; //this int is used in the request from the other activityBundle bundleToSendDataToOtherActivity; //object to send data to other activitypublic static Spinner infoSpinner, infoSpinner1, infoSpinner2; public static List<MapInfos> mapInfoses = new ArrayList<MapInfos>();public static List<String> coordinatesInfos = new ArrayList<String>();

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 130: UniSubject - rodin.uca.es

Page � of �130 188

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); infoSpinner = (Spinner)findViewById(R.id.spinnerPg2UniInfo); infoSpinner1 = (Spinner)findViewById(R.id.spinnerPg2UniInfo1); infoSpinner2 = (Spinner)findViewById(R.id.spinnerPg2UniInfo2); //The buttons for the heather btnLogout = (Button) findViewById(R.id.btnPg2btnLogout); btnHome = (Button) findViewById(R.id.btnPg2Home); btnNext = (Button) findViewById(R.id.btnPg2UniLink); btnMoreInfo = (Button) findViewById(R.id.btnPg2UniInfo); btnCompare = (Button) findViewById(R.id.btnPg2Compare2); btnMapView = (Button) findViewById(R.id.btnPg2MapView); btnMapView1 = (Button) findViewById(R.id.btnPg2MapView1); btnMapView2 = (Button) findViewById(R.id.btnPg2MapView2); universityListActivity = new UniversityListActivity(); universities = new ArrayList<University>(); genericDataDAO = new GenericDataDAO(getApplicationContext()); universityDataCollection = new ArrayList<ArrayList<String>>(); myColumns = new ArrayList<String>(); myValors = new ArrayList<String>(); backgroundTask = new BackgroundTask(this); galleryActivity = new GalleryActivity(); updateUniversityDataBase(); if(MainActivity.userData.uniAppUserRole == 1){ btnHome.setVisibility(View.VISIBLE); } btnLogout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MainActivity.userData.setUniAppUserStatus("disconnect"); startActivity(new Intent(MapsActivity.this, MainActivity.class)); } }); btnHome.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MapsActivity.this, AdminSelection.class)); } });

btnNext.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(UniDesptActivity.this, AdminUniversityMgtActivity.class)); startActivity(new Intent(MapsActivity.this, UniversityListActivity.class)); updateDataBase(); } });

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 131: UniSubject - rodin.uca.es

Page � of �131 188

btnMoreInfo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spannerItemPosoion = infoSpinner.getSelectedItemPosition(); universityListActivity.longClickedItemIndex = infoSpinner.getSelectedItemPosition(); university = MainActivity.universitiesUpToDate.get(spannerItemPosoion); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mapInfoses.get( universityListActivity.longClickedItemIndex).getCordinate(), 15)); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mapInfoses.get(spannerItemPosoion).getCordinate(), 15)); MainActivity.universityDAO.updateUniversityHits(university); Toast.makeText(infoSpinner.getContext(), "You Have Selected : " + university.getNameUni()+" with " + university.getHits()+" Hits. ", Toast.LENGTH_LONG).show(); startActivity(new Intent(MapsActivity.this, UniDesptActivity.class)); }});

btnCompare.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spannerItemPosoion1 = infoSpinner1.getSelectedItemPosition(); spannerItemPosoion2 = infoSpinner2.getSelectedItemPosition(); university1 = MainActivity.universitiesUpToDate.get(spannerItemPosoion1); university2 = MainActivity.universitiesUpToDate.get(spannerItemPosoion2); Toast.makeText(infoSpinner1.getContext(), "You Have Selected : " + university1.getNameUni()+" with " + university1.getHits()+" Hits and "+ university2.getNameUni()+" with " + university2.getHits()+" Hits.", Toast.LENGTH_LONG).show(); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mapInfoses.get(spannerItemPosoion1).getCordinate(), 15)); startActivity(new Intent(MapsActivity.this, CompareActivity.class)); }});

btnMapView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // startActivity(new Intent(MapsActivity.this, UniDesptActivity.class)); spannerItemPosoion = infoSpinner.getSelectedItemPosition(); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mapInfoses.get(spannerItemPosoion).getCordinate(), 15)); }});

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 132: UniSubject - rodin.uca.es

Page � of �132 188

btnMapView1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // startActivity(new Intent(MapsActivity.this, UniDesptActivity.class)); spannerItemPosoion1 = infoSpinner1.getSelectedItemPosition(); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mapInfoses.get(spannerItemPosoion1).getCordinate(), 15)); } }); btnMapView2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // startActivity(new Intent(MapsActivity.this, UniDesptActivity.class)); spannerItemPosoion1 = infoSpinner2.getSelectedItemPosition(); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mapInfoses.get(spannerItemPosoion1).getCordinate(), 15)); } });}

//to sync Mysql database and Msqlite public void updateUniversityDataBase(){ //set the delegate of the task as this activity backgroundTask.delegate = this; backgroundTask.execute(method, myUrlFactory.getUse_url, myTable, "id", "nameUni", "year", "population", "phone", "email", "address", "country", "continente", "description", "info", "longitude", "latitude", "webUri", "imageUni", "hits", "1", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"); Log.e(TAG, "**++++++++++++++++++++++++++++++++++++ From updateUniversityDataBase +++++++++++++++++++++++++ universityDataCollection.size() = " + universityDataCollection.size()); } //Add all the university to the local database public void convertDataToUniobject(){ if(!myColumns.isEmpty()) myColumns.clear(); if (!MainActivity.universitiesUpToDate.isEmpty()) MainActivity.universitiesUpToDate.clear(); //set the column names myColumns.addAll(MyDataFactory.setMyColumn(myTable)); int numberofDataCollected = universityDataCollection.size(); int i = 0; //convert the data collected to objects (University) while (i < numberofDataCollected) { MainActivity.universitiesUpToDate.add((University) MyDataFactory.createAnObject("University", universityDataCollection.get(i))); boolean gb = false;

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 133: UniSubject - rodin.uca.es

Page � of �133 188

gb = genericDataDAO.saveData(myColumns, universityDataCollection.get(i)); //check if data was saved successfully if(!gb) { //if data was not successfully saved then update it genericDataDAO.updateData(myColumns, universityDataCollection.get(i)); } i++; } int numberOfLocallySaveduniversity = genericDataDAO.getDatasCount(myTable); Log.e(TAG, numberOfLocallySaveduniversity +" Saved Locally ********************* From universitiesUpToDate size is = "+ MainActivity.universitiesUpToDate.size());} // add items into spinner dynamicallypublic void addItemsOnIdInfoSpinner(Spinner theSpinner) { ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, coordinatesInfos); dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); theSpinner.setAdapter(dataAdapter);} public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) { mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mapInfoses.get(pos).getCordinate(), 15)); universityListActivity.longClickedItemIndex = pos; Toast.makeText(parent.getContext(), "You have Selected here: " + parent.getItemAtPosition(pos).toString()+" the item select number is "+ universityListActivity.longClickedItemIndex, Toast.LENGTH_LONG).show();} @Overridepublic void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub}

@Overrideprotected void onResume() { super.onResume(); //updateUniversityDataBase(); loadUniInfo(); Log.e(TAG, genericDataDAO.getDatasCount(myTable) + " = genericDataDAO.getDatasCount(myTable size **&&&&&&&&&&&&&&&&&&& After onResume universityDataCollection size is = " + universityDataCollection.size()); setUpMapIfNeeded();}

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 134: UniSubject - rodin.uca.es

Page � of �134 188

public List<MapInfos> getMapInfoses() { return mapInfoses; } /** * Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly * installed) and the map has not already been instantiated.. This will ensure that we only ever * call {@link #setUpMap()} once when {@link #mMap} is not null. * <p/> * If it isn't installed {@link SupportMapFragment} (and * {@link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to * install/update the Google Play services APK on their device. * <p/> * A user can return to this FragmentActivity after following the prompt and correctly * installing/updating/enabling the Google Play services. Since the FragmentActivity may not * have been completely destroyed during this process (it is likely that it would only be * stopped or paused), {@link #onCreate(Bundle)} may not be called again so we should call this * method in {@link #onResume()} to guarantee that it will be called. */private void setUpMapIfNeeded() { // Do a null check to confirm that we have not already instantiated the map. if (mMap == null) { // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap(); mMap.setMyLocationEnabled(true); // Check if we were successful in obtaining the map. if (mMap != null) { setUpMap(); } }} /** * This is where we can add markers or lines, add listeners or move the camera. In this case, we * just add a marker near Africa. * <p/> * This should only be called once and when we are sure that {@link #mMap} is not null. */private void setUpMap() { //add a marker to the map and make it draggable and change the icon mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker").draggable(true).icon(BitmapDescriptorFactory.fromResource(R.drawable.edit_icon))); // mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mapInfoses.get(0).getCordinate(), 15)); //Set markers on the map for(MapInfos mpInfo : mapInfoses){ mMap.addMarker(new MarkerOptions().position(mpInfo.getCordinate()).title(mpInfo.getName()).snippet(mpInfo.getInfo() + "\n" + mpInfo.getWebUrl())); } Toast.makeText(getBaseContext(), universities.size()+" From MapsActivity. ", Toast.LENGTH_LONG).show(); } private void cleareMyCollections(){ if(!universities.isEmpty()) universities.clear(); if(!mapInfoses.isEmpty()) mapInfoses.clear(); if(!coordinatesInfos.isEmpty()) coordinatesInfos.clear(); if(!myColumns.isEmpty()) myColumns.clear();} //CONTINUA EN LA SIGUIENTE PÁGINA

Page 135: UniSubject - rodin.uca.es

Page � of �135 188

//asign the elements to the array for further use in the development of the spinners and map markerspublic void loadUniInfo(){ cleareMyCollections(); myColumns.addAll(MyDataFactory.setMyColumn(myTable)); ArrayList<String> tempValue = new ArrayList<String>(); ArrayList<ArrayList<String>> uniDataFromLocalDatabase = new ArrayList<ArrayList<String>>(); tempValue.add("1"); //get the data from local database and place it in memory uniDataFromLocalDatabase.addAll(genericDataDAO.getAllData(myColumns, tempValue)); int t = 0; int tamm = uniDataFromLocalDatabase.size(); while (t < tamm){ universities.add((University) MyDataFactory.createAnObject("University", uniDataFromLocalDatabase.get(t))); t++; } for (University uni : universities) { mapInfoses.add(new MapInfos(addCoordinates(uni.getLongitude(), uni.getLatitude()), uni.getNameUni(), uni.getInfo(), uni.getWebURI())); coordinatesInfos.add(uni.getNameUni() +" "+ uni.getHits()); } addItemsOnIdInfoSpinner(infoSpinner); addItemsOnIdInfoSpinner(infoSpinner1); addItemsOnIdInfoSpinner(infoSpinner2);} //Create the cordinates, store them in the list coordinates and return the cordinate just createdpublic LatLng addCoordinates(double longitude, double latitude){ LatLng coordinate = new LatLng(longitude, latitude); return coordinate;}

@Overridepublic void processFinish(ArrayList<ArrayList<String>> output) { if(!output.isEmpty()) { if(!universityDataCollection.isEmpty()){ universityDataCollection.clear(); } universityDataCollection.addAll(output); convertDataToUniobject(); loadUniInfo(); Toast.makeText(getBaseContext(), "From processFinish ", Toast.LENGTH_LONG).show(); }else{ Toast.makeText(getBaseContext(), "User name or password incorrect ", Toast.LENGTH_LONG).show(); Log.e(TAG, "**&&&&&&&&&&&&&&&&&&& From output size is = " + output.size()); }}

//CONTINUA EN LA SIGUIENTE PÁGINA

Page 136: UniSubject - rodin.uca.es

Page � of �136 188

@Override public void secondProcessFinish(ArrayList<String> secondOutputs){ } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_maps, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); }}

Page 137: UniSubject - rodin.uca.es

Campare Universidades, Faculdades, Majors y Asignatura con Compare Activity

Page � of �137 188

package lbs.uca.es.lbs;import android.content.Intent;import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.ImageView;import android.widget.Spinner;import android.widget.TextView;import android.widget.Toast;import com.google.android.gms.maps.CameraUpdateFactory;import com.google.android.gms.maps.GoogleMap;import com.google.android.gms.maps.SupportMapFragment;import com.google.android.gms.maps.model.Marker;import com.google.android.gms.maps.model.MarkerOptions;import java.util.ArrayList;import java.util.List;public class CompareActivity extends ActionBarActivity implements AdapterView.OnItemSelectedListener{ private GoogleMap mMap1, mMap2; TextView txtUrl1, txtUniName1, txtMajorName1, txtSubjects1, txtInfoSubject1, txtSubjDispt1, txtMajorIntro1, txtMajor1, txtFaculty1; TextView txtUrl2, txtUniName2, txtMajorName2, txtSubjects2, txtInfoSubject2, txtSubjDispt2, txtMajorIntro2, txtMajor2, txtFaculty2; Button btnPrivious, btnHome, btnAcronym, btnSubjects1, btnSelectMajor1, btnMoreFacultyInfo1, btnSelectFaculty1; Button btnSubjects2, btnSelectMajor2, btnMoreFacultyInfo2, btnSelectFaculty2; ImageView imgLogo1, imgLogo2; MapsActivity mapsActivity1, mapsActivity2; SubjDesptActivity subjDesptActivity; FacultyActivity facultyActivity; UniDesptActivity uniDesptActivity; private Marker markerForHideShow1, markerForHideShow2; private MarkerOptions markerOptionsForHideShow1, markerOptionsForHideShow2; private boolean status1 = true; private boolean status2 = true; Spinner subjectSpinner1, subjectSpinner2, majorSpinner1, majorSpinner2, facultySpinner1, facultySpinner2; public static int spinnerSubjectItemSelectPosition1, spinnerMajorItemSelectPosition1, spinnerFacultyItemSelectPosition1; public static int spinnerSubjectItemSelectPosition2, spinnerMajorItemSelectPosition2, spinnerFacultyItemSelectPosition2; int spinnerItemSelectPosition; University university1, university2; MapsActivity mapsActivity; UniversityListActivity universityListActivity1, universityListActivity12; int requestCode; //this int is used in the request from the other activity Bundle bundleToSendDataToOtherActivity; //object to send data to other activity//CONTINUA EN LA SIGUIENTE PÁGINA

Page 138: UniSubject - rodin.uca.es

Page � of �138 188

// public static int majorElectedId1, majorElectedId2, majorPos1, majorPos2, subjectPos1, subjectPos2; String facultyToBeLister1 = ""; String facultyToBeLister2 = ""; String majorToBeLister1 = ""; String majorToBeLister2 = ""; String subjectsToBeListed1 = ""; String subjectsToBeListed2 = ""; public static List<Subject> subjectsTemp1, subjectsTemp2; public static List<Major> majorsTemp1, majorsTemp2; public static List<Faculty> facultiesTemp1, facultiesTemp2; public List<String> subjectsName1, majorsName1 , facultyNames1; public List<String> subjectsName2, majorsName2, facultyNames2; public static University tempUniversity; public static UniversityDAO universityDAO; public static FacultyDAO facultyDAO; public static MajorDAO majorDAO; public static SubjectDAO subjectDAO; // public static DatabaseHandler dbHandler;int imageId1; int imageId2; String subjDispt2 = ""; String subjDispt1 = ""; Subject subj = new Subject();Faculty facul = new Faculty();ArrayAdapter<University> unversityAdapter; List<University> universities = new ArrayList<University>();List<Major> majors = new ArrayList<Major>();List<Subject> subjects = new ArrayList<Subject>();List<Faculty> faculties = new ArrayList<Faculty>();@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_compare); universityDAO = new UniversityDAO(getApplicationContext()); majorDAO = new MajorDAO(getApplicationContext()); subjectDAO = new SubjectDAO(getApplicationContext()); facultyDAO = new FacultyDAO(getApplicationContext()); uniDesptActivity = new UniDesptActivity(); subjDesptActivity = new SubjDesptActivity(); facultyActivity = new FacultyActivity(); university1 = universityDAO.getUniversity(MapsActivity.spannerItemPosoion1+1) ; university2 = universityDAO.getUniversity(MapsActivity.spannerItemPosoion2+1) ; mapsActivity1 = new MapsActivity(); //to use this injection de codigo to get the information of the spinners mapsActivity2 = new MapsActivity(); //to use this injection de codigo to get the information of the spinners subjDesptActivity = new SubjDesptActivity();

majorsTemp1 = new ArrayList<Major>();majorsTemp2 = new ArrayList<Major>();subjectsTemp1 = new ArrayList<Subject>();subjectsTemp2 = new ArrayList<Subject>();facultiesTemp1 = new ArrayList<Faculty>();facultiesTemp2 = new ArrayList<Faculty>();majorsName1 = new ArrayList<String>();majorsName2 = new ArrayList<String>();subjectsName1 = new ArrayList<String>();subjectsName2 = new ArrayList<String>();facultyNames1 = new ArrayList<String>();facultyNames2 = new ArrayList<String>();majors.addAll(majorDAO.getAllMAJORS());subjects.addAll(subjectDAO.getAllSUBJECTS());faculties.addAll(facultyDAO.getAllFACULTIES()); //CONTINUA EN LA SIGUIENTE PÁGINA

Page 139: UniSubject - rodin.uca.es

Page � of �139 188

btnPrivious = (Button) findViewById(R.id.btnPg6Privious); btnHome = (Button) findViewById(R.id.btnPg6Home);btnAcronym = (Button) findViewById(R.id.btnPg6Next);btnSubjects1 = (Button) findViewById(R.id.btnSeeSubjectPg6L);btnSubjects2 = (Button) findViewById(R.id.btnSeeSubjectPg6R);btnSelectMajor1 = (Button) findViewById(R.id.btnOKMajorPg6);btnSelectMajor2 = (Button) findViewById(R.id.btnOKMajorPg6R);btnMoreFacultyInfo2 = (Button) findViewById(R.id.btnInfoFacultyPg6R);btnMoreFacultyInfo1 = (Button) findViewById(R.id.btnInfoFacultyPg6);btnSelectFaculty1 = (Button) findViewById(R.id.btnSeeFacultyPg6L);btnSelectFaculty2 = (Button) findViewById(R.id.btnSeeFacultyPg6R);//Information for the first university electedtxtUniName1 = (TextView)findViewById(R.id.txtVPg6Name);txtUniName1.setText(university1.getNameUni());txtMajorName1 = (TextView)findViewById(R.id.txtVPg6Acronym1);txtMajorName1.setText("Description: " + university1.getInfo());txtUrl1 = (TextView)findViewById(R.id.txtVPg6Url1);txtUrl1.setText(university1.getWebURI().toString());txtSubjects1 = (TextView)findViewById(R.id.textViewSubjectsPg6);txtInfoSubject1 = (TextView)findViewById(R.id.txtVPg6SubjectPrint1);imgLogo1 = (ImageView) findViewById(R.id.imgVPg6);imgLogo1.setImageResource(university1.getImageUni());txtSubjDispt1 = (TextView)findViewById(R.id.textViewSubjectsDisptPg6L);txtMajorIntro1 = (TextView)findViewById(R.id.txtVPg6Major);txtMajor1 = (TextView) findViewById(R.id.textViewMajorsPg6);txtFaculty1 = (TextView) findViewById(R.id.textViewFacultiesPg6);//Information for the second university electedtxtUniName2 = (TextView)findViewById(R.id.txtVPg6Name2); txtUniName2.setText(university2.getNameUni());txtMajorName2 = (TextView)findViewById(R.id.txtVPg6Acronym2);txtMajorName2.setText("Description: " + university2.getInfo());txtUrl2 = (TextView)findViewById(R.id.txtVPg6Url2);txtUrl2.setText(university2.getWebURI().toString());txtSubjects2 = (TextView)findViewById(R.id.textViewSubjectsPg6R);txtInfoSubject2 = (TextView)findViewById(R.id.txtVPg6SubjectPrint2);imgLogo2 = (ImageView) findViewById(R.id.imgVPg6logo2);imgLogo2.setImageResource(university2.getImageUni());txtSubjDispt2 = (TextView)findViewById(R.id.textViewSubjectsDisptPg6R);txtMajorIntro2 = (TextView)findViewById(R.id.txtVPg6MajorR);txtMajor2 = (TextView) findViewById(R.id.textViewMajorsPg6R);txtFaculty1 = (TextView) findViewById(R.id.textViewFacultiesPg6R); subjectSpinner1 = (Spinner)findViewById(R.id.spinnerPg6Subject1); subjectSpinner2 = (Spinner)findViewById(R.id.spinnerPg6Subject2); majorSpinner1 = (Spinner)findViewById(R.id.spinnerPg6Major); majorSpinner2 = (Spinner)findViewById(R.id.spinnerPg6MajorR); facultySpinner1 = (Spinner)findViewById(R.id.spinnerPg6Faculty1); facultySpinner2 = (Spinner)findViewById(R.id.spinnerPg6Faculty2);btnPrivious.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(CompareActivity.this, UniversityListActivity.class)); }});btnHome.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(CompareActivity.this, MapsActivity.class)); }});

//CONTINUA EN LA SIGUIENTE PÁGIN

Page 140: UniSubject - rodin.uca.es

Page � of �140 188

btnSelectFaculty1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spinnerFacultyItemSelectPosition1 = facultySpinner1.getSelectedItemPosition(); int type = 1; setFacultyButtonAction(type); startActivity(new Intent(UniDesptActivity.this, SubjectActivity.class)); } });btnSelectFaculty2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spinnerFacultyItemSelectPosition2 = facultySpinner2.getSelectedItemPosition(); int type = 2; setFacultyButtonAction(type); startActivity(new Intent(UniDesptActivity.this, SubjectActivity.class)); } });btnSelectMajor1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spinnerMajorItemSelectPosition1 = majorSpinner1.getSelectedItemPosition(); //Clear all former faculties int type = 1; txtSubjDispt1.setText(""); setMajorButtonAction(type); }});btnSelectMajor2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spinnerMajorItemSelectPosition2 = majorSpinner2.getSelectedItemPosition(); //Clear all former faculties int type = 2; txtSubjDispt2.setText(""); setMajorButtonAction(type); }});btnSubjects1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { UniDesptActivity.spinnerSubjectItemSelectPosition = subjectSpinner1.getSelectedItemPosition(); subjDispt1 = ""; if(!subjectsTemp1.isEmpty()) { Subject subj = subjectsTemp1.get(subjectSpinner1.getSelectedItemPosition()); txtSubjDispt1.setText("Subject: \n "+ subj.getNameSubject()+"\nDescription: \n "+ subj.getDescription()); txtSubjDispt1.setVisibility(View.VISIBLE); } }});

//CONTINUA EN LA SIGUIENTE PÁGIN

Page 141: UniSubject - rodin.uca.es

Page � of �141 188

btnSubjects2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { UniDesptActivity.spinnerSubjectItemSelectPosition = subjectSpinner2.getSelectedItemPosition(); subjDispt2 = ""; if(!subjectsTemp2.isEmpty()) { Subject subj = subjectsTemp2.get(subjectSpinner2.getSelectedItemPosition()); txtSubjDispt2.setText("Subject: \n "+ subj.getNameSubject()+"\nDescription: \n "+ subj.getDescription()); txtSubjDispt2.setVisibility(View.VISIBLE); } } }); btnMoreFacultyInfo1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spinnerFacultyItemSelectPosition1 = facultySpinner1.getSelectedItemPosition(); UniDesptActivity.spinnerFacultyItemSelectPosition = facultySpinner1.getSelectedItemPosition(); //If the array of faculty for the university is not emptythen clear it if(!UniDesptActivity.facultiesTemp.isEmpty()) UniDesptActivity.facultiesTemp.clear(); UniDesptActivity.facultiesTemp.addAll(facultiesTemp1); if(!facultiesTemp1.isEmpty()) { facul = facultiesTemp1.get(spinnerFacultyItemSelectPosition1); Toast.makeText(facultySpinner1.getContext(), " There are " + facultiesTemp1.size() + " faculty . Faculty name is " + facul.getNameFaculty(), Toast.LENGTH_LONG).show(); startActivity(new Intent(CompareActivity.this, FacultyActivity.class)); } } }); btnMoreFacultyInfo2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spinnerFacultyItemSelectPosition2 = facultySpinner2.getSelectedItemPosition(); UniDesptActivity.spinnerFacultyItemSelectPosition = facultySpinner2.getSelectedItemPosition(); //If the array of faculty for the university is not emptythen clear it if(!UniDesptActivity.facultiesTemp.isEmpty()) UniDesptActivity.facultiesTemp.clear(); UniDesptActivity.facultiesTemp.addAll(facultiesTemp2); if(!facultiesTemp2.isEmpty()) { facul = facultiesTemp2.get(spinnerFacultyItemSelectPosition2); Toast.makeText(facultySpinner2.getContext(), " There are " + facultiesTemp2.size() + " faculty . Faculty name is " + facul.getNameFaculty(), Toast.LENGTH_LONG).show(); // facultyActivity.loadMajorInfo(); startActivity(new Intent(CompareActivity.this, FacultyActivity.class)); } } });}

//CONTINUA EN LA SIGUIENTE PÁGIN

Page 142: UniSubject - rodin.uca.es

Page � of �142 188

btnMoreFacultyInfo2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spinnerFacultyItemSelectPosition2 = facultySpinner2.getSelectedItemPosition(); UniDesptActivity.spinnerFacultyItemSelectPosition = facultySpinner2.getSelectedItemPosition(); //If the array of faculty for the university is not emptythen clear it if(!UniDesptActivity.facultiesTemp.isEmpty()) UniDesptActivity.facultiesTemp.clear(); UniDesptActivity.facultiesTemp.addAll(facultiesTemp2); if(!facultiesTemp2.isEmpty()) { facul = facultiesTemp2.get(spinnerFacultyItemSelectPosition2); Toast.makeText(facultySpinner2.getContext(), " There are " + facultiesTemp2.size() + " faculty . Faculty name is " + facul.getNameFaculty(), Toast.LENGTH_LONG).show(); // facultyActivity.loadMajorInfo(); startActivity(new Intent(CompareActivity.this, FacultyActivity.class)); } } });} // add items into spinner dynamicallypublic void addItemsOnidInfoSpinner(Spinner theSpinner) { ArrayAdapter<String> dataAdapter; if(theSpinner == facultySpinner2) { dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, facultyNames2); }else if(theSpinner == facultySpinner1) { dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, facultyNames1); }else if(theSpinner == majorSpinner1) { dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, majorsName1); }else if(theSpinner == majorSpinner2) { dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, majorsName2); }else if(theSpinner == subjectSpinner1) { dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, subjectsName1); }else { dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, subjectsName2); } dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); theSpinner.setAdapter(dataAdapter);} public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) { spinnerItemSelectPosition = (int)parent.getItemAtPosition(pos); Toast.makeText(parent.getContext(), "Major Selected : " + parent.getItemAtPosition(pos).toString() + " " + spinnerItemSelectPosition, Toast.LENGTH_LONG).show();} @Overridepublic void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub} //CONTINUA EN LA SIGUIENTE PÁGIN

Page 143: UniSubject - rodin.uca.es

Page � of �143 188

@Overrideprotected void onResume() { super.onResume(); loadUniInfo(); setUpMapIfNeeded();} public void loadUniInfo() { resetAllItems(); for (Faculty faculty : faculties) { if (faculty.getUniversity().getNameUni().toString().trim().equals(university1.getNameUni().toString().trim())) { facultyNames1.add(faculty.getNameFaculty()); facultiesTemp1.add(faculty); facultyToBeLister1 += faculty.getNameFaculty(); } if (faculty.getUniversity().getNameUni().toString().trim().equals(university2.getNameUni().toString().trim())) { facultyNames2.add(faculty.getNameFaculty()); facultiesTemp2.add(faculty); facultyToBeLister2 += faculty.getNameFaculty(); } } addItemsOnidInfoSpinner(facultySpinner1); addItemsOnidInfoSpinner(facultySpinner2); //lets create the views for our different items and set the text to be displaied} private void resetAllItems(){ facultiesTemp1.clear(); facultyNames1.clear(); majorsName1.clear(); majorsTemp1.clear(); subjectsName1.clear(); subjectsTemp1.clear(); facultiesTemp2.clear(); facultyNames2.clear(); majorsName2.clear(); majorsTemp2.clear(); subjectsName2.clear(); subjectsTemp2.clear(); majorToBeLister1 = ""; subjectsToBeListed1 = ""; facultyToBeLister1 =""; majorToBeLister2 = ""; subjectsToBeListed2 = ""; facultyToBeLister2 =""; }

private void setUpMapIfNeeded() { // Do a null check to confirm that we have not already instantiated the map. if (mMap1 == null && mMap2 == null) { // Try to obtain the map from the SupportMapFragment. mMap1 = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.Pg6Map1)).getMap(); mMap1.setMyLocationEnabled(true); mMap2 = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.Pg6Map2)).getMap(); mMap2.setMyLocationEnabled(true); // Check if we were successful in obtaining the map. if (mMap1 != null && mMap2 != null) { setUpMap(); } }} //CONTINUA EN LA SIGUIENTE PÁGIN

Page 144: UniSubject - rodin.uca.es

Page � of �144 188

/** * This is where we can add markers or lines, add listeners or move the camera. In this case, we * just add a marker near Africa. * <p/> * This should only be called once and when we are sure that {@link #mMap1} is not null * This should only be called once and when we are sure that {@link #mMap2} is not null. */private void setUpMap() { //Set markers on the map1 mMap1.addMarker(new MarkerOptions().position(MapsActivity.mapInfoses.get(MapsActivity.spannerItemPosoion1).getCordinate()). title(MapsActivity.mapInfoses.get(MapsActivity.spannerItemPosoion1).getName()). snippet(MapsActivity.mapInfoses.get(MapsActivity.spannerItemPosoion1).getInfo() + "\n" + MapsActivity.mapInfoses.get(MapsActivity.spannerItemPosoion1).getWebUrl())); //para zoom in en la locacion mMap1.moveCamera(CameraUpdateFactory.newLatLngZoom(MapsActivity.mapInfoses.get(MapsActivity.spannerItemPosoion1).getCordinate(), 15)); //Set markers on the map2 mMap2.addMarker(new MarkerOptions().position(MapsActivity.mapInfoses.get(MapsActivity.spannerItemPosoion2).getCordinate()). title(MapsActivity.mapInfoses.get(MapsActivity.spannerItemPosoion2).getName()). snippet(MapsActivity.mapInfoses.get(MapsActivity.spannerItemPosoion2).getInfo() + "\n" + MapsActivity.mapInfoses.get(MapsActivity.spannerItemPosoion2).getWebUrl())); //para zoom in en la locacion mMap2.moveCamera(CameraUpdateFactory.newLatLngZoom(MapsActivity.mapInfoses.get(MapsActivity.spannerItemPosoion2).getCordinate(), 15));} public void setFacultyButtonAction(int type) { //fill a collection of the faculties that these universities have if (type == 1) { majorsTemp1.clear(); majorsName1.clear(); subjectsTemp1.clear(); subjectsName1.clear(); majorToBeLister1 = ""; subjectsToBeListed1 = ""; majorToBeLister1 = "The List of Majors: \n"; String facultyName1 = facultyNames1.get(spinnerFacultyItemSelectPosition1); int t=1; for (Major major : majors) { if (major.getFaculty().getNameFaculty().trim().equals(facultyName1.trim())) { majorsName1.add(major.getNameMajor()); majorsTemp1.add(major); majorToBeLister1 += t+". "+ major.getNameMajor() + " \n\n"; t++; } } txtMajor1.setText(majorToBeLister1); addItemsOnidInfoSpinner(majorSpinner1); if (majorsName1.size() != 0) { spinnerMajorItemSelectPosition1 = majorSpinner1.getSelectedItemPosition(); btnSelectMajor1.setVisibility(View.VISIBLE); txtMajorIntro1.setVisibility(View.VISIBLE); majorSpinner1.setVisibility(View.VISIBLE); txtMajor1.setVisibility(View.VISIBLE); } else { spinnerMajorItemSelectPosition1 = 0; Toast.makeText(facultySpinner1.getContext(), majors.size() + " There are no majors for this faculty: " + facultySpinner1.getItemAtPosition(spinnerFacultyItemSelectPosition1).toString(), Toast.LENGTH_SHORT).show(); } } //CONTINUA EN LA SIGUIENTE PÁGIN

Page 145: UniSubject - rodin.uca.es

Page � of �145 188

if (type == 2) { majorsTemp2.clear(); majorsName2.clear(); subjectsTemp2.clear(); subjectsName2.clear(); majorToBeLister2 = ""; subjectsToBeListed2 = ""; majorToBeLister2 = "The List of Majors: \n"; String facultyName2 = facultyNames2.get(spinnerFacultyItemSelectPosition2); int i=1; for (Major major : majors) { if (major.getFaculty().getNameFaculty().trim().equals(facultyName2.trim())) { majorsName2.add(major.getNameMajor()); majorsTemp2.add(major); majorToBeLister2 += i+". "+major.getNameMajor() + " \n\n"; i++; } } txtMajor2.setText(majorToBeLister2); addItemsOnidInfoSpinner(majorSpinner2); if (majorsName2.size() != 0) { spinnerMajorItemSelectPosition2 = majorSpinner2.getSelectedItemPosition(); btnSelectMajor2.setVisibility(View.VISIBLE); txtMajorIntro2.setVisibility(View.VISIBLE); majorSpinner2.setVisibility(View.VISIBLE); txtMajor2.setVisibility(View.VISIBLE); } else { spinnerMajorItemSelectPosition2 = 0; Toast.makeText(facultySpinner2.getContext(), majors.size() + " There are no majors for this faculty: " + facultySpinner2.getItemAtPosition(spinnerFacultyItemSelectPosition2).toString(), Toast.LENGTH_SHORT).show(); } }} public void setMajorButtonAction(int type) { if (type == 1) { subjectsTemp1.clear(); subjectsName1.clear(); subjectsToBeListed1 = "The List of Subjects: \n"; String majorName1 = majorsName1.get(spinnerMajorItemSelectPosition1); int t=1; for (Subject subject : subjects) { if (subject.getMajor().getNameMajor().trim().equals(majorName1.trim())) { subjectsName1.add(subject.getNameSubject()); subjectsTemp1.add(subject); subjectsToBeListed1 += t +". "+subject.getNameSubject() + " \n\n"; t++; } } txtSubjects1.setText(subjectsToBeListed1); addItemsOnidInfoSpinner(subjectSpinner1);

//CONTINUA EN LA SIGUIENTE PÁGIN

Page 146: UniSubject - rodin.uca.es

Page � of �146 188

if (subjectsName1.size() != 0) { spinnerSubjectItemSelectPosition1 = subjectSpinner1.getSelectedItemPosition(); btnSubjects1.setVisibility(View.VISIBLE); txtInfoSubject1.setVisibility(View.VISIBLE); txtSubjects1.setVisibility(View.VISIBLE); subjectSpinner1.setVisibility(View.VISIBLE); txtSubjDispt1.setVisibility(View.VISIBLE); } else { spinnerSubjectItemSelectPosition1 = 0; Toast.makeText(majorSpinner1.getContext(), subjects.size() + " Thereare no subjects for this major: " + majorSpinner1.getItemAtPosition(spinnerMajorItemSelectPosition1).toString(), Toast.LENGTH_SHORT).show(); } startActivity(new Intent(UniDesptActivity.this, SubjectActivity.class)); } if (type == 2) { subjectsTemp2.clear(); subjectsName2.clear(); subjectsToBeListed2 = "The List of Subjects: \n"; String majorName2 = majorsName2.get(spinnerMajorItemSelectPosition2); int i=1; for (Subject subject : subjects) { if (subject.getMajor().getNameMajor().trim().equals(majorName2.trim())) { subjectsName2.add(subject.getNameSubject()); subjectsTemp2.add(subject); subjectsToBeListed2 += i +". "+subject.getNameSubject() + " \n\n"; i++; } } txtSubjects2.setText(subjectsToBeListed2); addItemsOnidInfoSpinner(subjectSpinner2); if (subjectsName2.size() != 0) { spinnerSubjectItemSelectPosition2 = subjectSpinner2.getSelectedItemPosition(); btnSubjects2.setVisibility(View.VISIBLE); txtInfoSubject2.setVisibility(View.VISIBLE); txtSubjects2.setVisibility(View.VISIBLE); subjectSpinner2.setVisibility(View.VISIBLE); txtSubjDispt2.setVisibility(View.VISIBLE); } else { spinnerSubjectItemSelectPosition2 = 0; Toast.makeText(majorSpinner2.getContext(), subjects.size() + " Thereare no subjects for this major: " + majorSpinner2.getItemAtPosition(spinnerMajorItemSelectPosition2).toString(), Toast.LENGTH_SHORT).show(); } startActivity(new Intent(UniDesptActivity.this, SubjectActivity.class)); } } }

Page 147: UniSubject - rodin.uca.es

5.2.4 Clases

La idea fundamental que subyace tras el paradigma de la orientación a objetos es la de organizar el sistema que se está desarrollando en torno a los objetos que intervienen en él. Estos objetos se abstraen en clases. Mientras que un objeto es una entidad que posee un conjunto de datos y de operaciones, una clase es una descripción general que permite representar un conjunto de objetos similares.

Por definición, todos los objetos que existen dentro de una clase comparten los mismos datos y operaciones,. La clase encapsula las abstracciones de datos y operaciones necesarias para describir un cierto tipo de entidades del mundo real. En la terminología de la programación orientada a objetos, a los datos de una clase se les llama atributos y a sus operaciones, métodos. Los atributos pueden ocultarse de manera que la única forma de operar sobre ellos sea a través de alguno de los métodos que proporciona la clase. Esto permite ocultar los detalles de implementación, facilita el mantenimiento y favorece la reutilización.

A continuación se detallan algunas de las clases que forman parte de la aplicación del presente proyecto:

El clase de usuario

Page � of �147 188

package lbs.uca.es.lbs;import java.io.Serializable;/** * Created by ale on 06/07/15. */public class UserData implements Serializable { int id, uniAppUserRole; String uniAppUserEmail, uniAppUserName, uniAppUserPassword; String uniAppUserStatus; public UserData(){} public UserData(int id, String email, String uniAppUserName, String uniAppUserPassword) { this.id = id; this.uniAppUserEmail = email; this.uniAppUserName = uniAppUserName; this.uniAppUserPassword = uniAppUserPassword; this.uniAppUserRole = 2; this.uniAppUserStatus = "disconnect"; }

Page 148: UniSubject - rodin.uca.es

Page � of �148 188

public UserData(int id, String email, String uniAppUserName, String uniAppUserPassword, int uniAppUserRole) { this.id = id; this.uniAppUserEmail = email; this.uniAppUserName = uniAppUserName; this.uniAppUserPassword = uniAppUserPassword; this.uniAppUserRole = uniAppUserRole; this.uniAppUserStatus = "disconnect"; } public UserData(int id, String email, String uniAppUserName, String uniAppUserPassword, int uniAppUserRole, String uniAppUserStatus) { this.id = id; this.uniAppUserEmail = email; this.uniAppUserName = uniAppUserName; this.uniAppUserPassword = uniAppUserPassword; this.uniAppUserRole = uniAppUserRole; this.uniAppUserStatus = uniAppUserStatus; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUniAppUserEmail() { return uniAppUserEmail; } public void setUniAppUserEmail(String email) { this.uniAppUserEmail = email; } public int getUniAppUserRole() { return uniAppUserRole; } public void setUniAppUserRole(int uniAppUserRole) { this.uniAppUserRole = uniAppUserRole; } public String getUniAppUserName() { return uniAppUserName; } public void setUniAppUserName(String uniAppUserName) { this.uniAppUserName = uniAppUserName; } public String getUniAppUserPassword() { return uniAppUserPassword; } public void setUniAppUserPassword(String uniAppUserPassword) { this.uniAppUserPassword = uniAppUserPassword; } public String getUniAppUserStatus() { return uniAppUserStatus; } public void setUniAppUserStatus(String uniAppUserStatus) { this.uniAppUserStatus = uniAppUserStatus; }}

Page 149: UniSubject - rodin.uca.es

Clase de la univarsidad

Page � of �149 188

package lbs.uca.es.lbs;import android.net.Uri;import java.io.Serializable;/** * Created by ale on 11/06/15. */public class University implements Serializable { private int id , imageUni, hits; private String nameUni, year, population, phone, email, address, country, continente, description, info; private double longitude, latitude; private Uri webUri; private Boolean hitStatus = false; public University(int id, String nameUni, String year, String population, String phone, String email, String address, String country, String continente, String description, String infos, double longitude, double latitude, Uri webURI, int imageUni) { this.id = id; this.nameUni = nameUni; this.year = year; this.population = population; this.phone = phone; this.email = email; this.address = address; this.country = country; this.continente = continente; this.description = description; this.info = infos; this.longitude = longitude; this.latitude = latitude; this.webUri = webURI; this.imageUni = imageUni; this.hits = 0; } public University(int id, String nameUni, String year, String population, String phone, String email, String address, String country, String continente, String description, String infos, double longitude, double latitude, Uri webURI, int imageUni, int hit) { this.id = id; this.nameUni = nameUni; this.year = year; this.population = population; this.phone = phone; this.email = email; this.address = address; this.country = country; this.continente = continente; this.description = description; this.info = infos; this.longitude = longitude; this.latitude = latitude; this.webUri = webURI; this.imageUni = imageUni; this.hits = hit; } public University(){} public University(int id, String nameUni){ this.id = id; this.nameUni = nameUni; } public University(int id){ this.id = id; } public Uri getWebURI() { return webUri; } public void setWebURI(Uri webURI) { this.webUri = webURI; } public int getId() { return id; }

Page 150: UniSubject - rodin.uca.es

Page � of �150 188

public void setId(int id) { this.id = id; } public String getNameUni() { return nameUni; } public void setNameUni(String nameUni) { this.nameUni = nameUni; } public String getYear() { return year; } public void setYear(String year) { this.year = year; } public String getPopulation() { return population; } public void setPopulation(String population) { this.population = population; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getContinente() { return continente; } public void setContinente(String continente) { this.continente = continente; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getInfo() { return info; }

Page 151: UniSubject - rodin.uca.es

Clase de las asignaturas

Page � of �151 188

package lbs.uca.es.lbs;import java.io.Serializable;/** * Created by ale on 22/06/15. */public class Subject implements Serializable { int id, hits, like, dislike; String nameSubject, description; Major major; private Boolean hitStatus = false; private Boolean likeStatus = false; private Boolean dislikeStatus = false; public Subject(){} public Subject(int id){ this.id = id; } public Subject(int id, String nameSubject, String description, Major major) { this.id = id; this.nameSubject = nameSubject; this.description = description; this.major = major; this.hits = 0; this.like = 0; this.dislike = 0; } public Subject(int id, String nameSubject, String description, Major major, int hits, int like, int dislike) { this.id = id; this.nameSubject = nameSubject; this.description = description; this.major = major; this.hits = hits; this.like = like; this.dislike = dislike; } public int getId() { return id; } public void setId(int id) { this.id = id;} public String getNameSubject() { return nameSubject; } public void setNameSubject(String nameSubject) { this.nameSubject = nameSubject;} public String getDescription() { return description; } public void setDescription(String description) { this.description = description;}

Page 152: UniSubject - rodin.uca.es

Page � of �152 188

public void setDescription(String description) { this.description = description; } public Major getMajor() { return major; } public void setMajor(Major major) { this.major = major; } public int getHits() { return hits; } public void setHits(int hits) { this.hits = hits; } public int getLike() { return like; } public void setLike(int like) { this.like = like; } public int getDislike() { return dislike; } public void setDislike(int dislike) { this.dislike = dislike; } public Boolean getHitStatus() { return hitStatus; } public void setHitStatus(Boolean hitStatus) { this.hitStatus = hitStatus; } public Boolean getLikeStatus() { return likeStatus; } public void setLikeStatus(Boolean likeStatus) { this.likeStatus = likeStatus; } public Boolean getDislikeStatus() { return dislikeStatus; } public void setDislikeStatus(Boolean dislikeStatus) { this.dislikeStatus = dislikeStatus; }}

Page 153: UniSubject - rodin.uca.es

5.2.5 Clases de apoyo

Las siguientes clases no representan a entidades del mundo real, sino que proporcionan mecanismos de apoyo para el correcto funcionamiento de las clases y actividades anteriores. A continuación se detallan algunas de las clases de apoyo que forman parte de la aplicación del presente proyecto:

Clase que crear los objeto que contiene la ruta del php script

Page � of �153 188

package lbs.uca.es.lbs;/** * Created by ale on 15/12/15. */public class myUrlFactory { public final static String reg_url = "http://192.168.1.10/unimanager/umregister.php"; public final static String login_url = "http://192.168.1.10/unimanager/umlogin.php"; public final static String getUse_url = "http://192.168.1.10/unimanager/umalluniversity.php"; public final static String unSub_url = "http://192.168.1.10/unimanager/umeliminateuser.php"; public final static String edit_url = "http://192.168.1.10/unimanager/umedituser.php"; public final static String regUniversity_url = "http://192.168.1.10/unimanager/umuniversityregister.php"; public final static String regGallery_url = "http://192.168.1.10/unimanager/umgalleryregister.php"; public final static String getAllGallery_url = "http://192.168.1.10/unimanager/allgallery.php"; public final static String getAUniversity_url = "http://192.168.1.10/unimanager/umgetauniversity.php"; public final static String deleteAUniversity_url = "http://192.168.1.10/unimanager/umeliminateuniversity.php"; public final static String editAUniversity_url = "http://192.168.1.10/unimanager/umedituniversity.php"; }

Page 154: UniSubject - rodin.uca.es

5.2.6 Servicios

Un servicio es un componente de la aplicación que puede realizar operaciones de larga ejecución en segundo plano y no proporciona una interfaz de usuario. Otro componente de la aplicación puede comenzar un servicio y continuará ejecutándose en segundo plano incluso si el usuario cambia a otra aplicación. Adicionalmente, un componente puede enlazarse a un servicio para interactuar con él e incluso realizar comunicación entre procesos (IPC). Por ejemplo, un servicio puede manejar transacciones de redes, reproducir música, realizar entrada y salida de archivos, o interactuar con un proveedor de contenidos, todo desde un segundo plano. A continuación se detallan algunas de las clases de servicio que forman parte de la aplicación del presente proyecto:

Servicio que conectar con el base se datos

Page � of �154 188

package lbs.uca.es.lbs;import android.app.AlertDialog;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.net.Uri;import android.os.AsyncTask;import android.provider.ContactsContract;import android.util.Base64;import android.util.Log;import android.widget.Toast;import org.json.JSONException;import org.json.JSONObject;import org.json.JSONArray;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.net.URLEncoder;import java.util.ArrayList;import java.util.List;/** * Created by ale on 02/12/1

Page 155: UniSubject - rodin.uca.es

Page � of �155 188

public class BackgroundTask extends AsyncTask<String,Void,String>{ public static final String TAG = "BackgroundTask"; /** public final static String reg_url = "http://192.168.1.8/unimanager/umregister.php"; public final static String login_url = "http://192.168.1.8/unimanager/umlogin.php"; public final static String getUse_url = "http://192.168.1.8/unimanager/umgetalluser.php"; public final static String unSub_url = "http://192.168.1.8/unimanager/umeliminateuser.php"; public final static String edit_url = "http://192.168.1.8/unimanager/umedituser.php";**/ public static String methods = ""; public static String theMessageFromDB = ""; public static String id = ""; Bitmap bitmap1; String image_str=""; public static String email = ""; public static String uniAppUserName = ""; public static String uniAppUserPassword = ""; public static String uniAppUserRole = ""; public static String uniAppUserStatus = ""; public static ArrayList<Object> theUsers = new ArrayList<Object>(); public final static ArrayList<String> theColumns = new ArrayList<String>(); public static ArrayList<String> singleArys = new ArrayList<String>(); public static ArrayList<ArrayList<String>> manyArys = new ArrayList<ArrayList<String>>(); public static ArrayList<String> columnNames; public static ArrayList<String> columnValues; private String theTable; public static UserData usd; public static boolean isUserLogedIn = false; public static String uName =""; public static String uPass =""; public static int ide ; //declare a delegate with type of protocol declared in this task public AsyncResponse delegate = null; public AsyncResponse secondDelegate = null; String response=""; String respon = ""; String myMeg = ""; String data, myUrl; AlertDialog alertDialog; Context ctx; URL url; HttpURLConnection httpURLConnection; OutputStream OS; InputStream IS; BufferedWriter bufferedWriter; BufferedReader bufferedReader; JSONArray usrs = null; StringBuffer stringBuffer = new StringBuffer(); int firstColum, lastColum, firstValue, lastValue; BackgroundTask(Context ctx) { this.ctx =ctx; } //before we execute we create an alertDialog object and set its title @Override protected void onPreExecute() { alertDialog = new AlertDialog.Builder(ctx).create(); alertDialog.setTitle("Updating app ..."); }

Page 156: UniSubject - rodin.uca.es

Page � of �156 188

public void openConnection(){ try { url = new URL(myUrl); httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setRequestMethod("POST"); httpURLConnection.setDoOutput(true); httpURLConnection.setDoInput(true); OS = httpURLConnection.getOutputStream(); httpURLConnection.connect(); bufferedWriter = new BufferedWriter(new OutputStreamWriter(OS, "UTF-8")); }catch(MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }} public void closeConnectionToWrite(){ try{ bufferedWriter.write(data); bufferedWriter.flush(); bufferedWriter.close(); OS.close(); IS = httpURLConnection.getInputStream(); bufferedReader = new BufferedReader(new InputStreamReader(IS, "iso-8859-1")); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }} public void openConnectionToRead() throws IOException { url = new URL(myUrl); httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.connect(); IS = httpURLConnection.getInputStream(); // bufferedReader = new BufferedReader(new InputStreamReader(stream)); bufferedReader = new BufferedReader(new InputStreamReader(IS, "iso-8859-1"));}

public void closeConnectionToRead(){ try{ bufferedReader.close(); IS.close(); httpURLConnection.disconnect(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }}

Page 157: UniSubject - rodin.uca.es

Page � of �157 188

//method, url, tableName,id, name, ....values id, name, numeroDeColumna = (Tam-3) /2, i=3, imax = numeroDeColumna +3, t=imax, tmax = tam// private void setEntryDatas(ArrayList<String> colmNames, ArrayList<String> colmValues){private void setEntryDatas(ArrayList<String> theDatas){ columnNames = new ArrayList<String>(); columnValues = new ArrayList<String>(); myUrl = theDatas.get(1); //the uri of the php file theTable = theDatas.get(2); //the table name as in the database lastValue = theDatas.size(); firstColum = 3; lastColum = ((lastValue - firstColum) / 2) + firstColum; //calculate the position of the last column name in the list. firstValue = lastColum; int i=firstColum; //Add the name of the columns in the column colection while(i<lastColum){ this.columnNames.add(theDatas.get(i)); i++; } int t=firstValue; //Add the name of the values in the value colection while(t<lastValue){ this.columnValues.add(theDatas.get(t)); t++; } ide = Integer.parseInt(columnValues.get(0));} public void setMyStringBuffer() throws IOException { String line = ""; while ((line = bufferedReader.readLine()) != null) { stringBuffer.append(line); }} //convert all the json data from the external database stringbuffer to a simple array of array stringsprivate void convertJsonToStrings() throws IOException, MalformedURLException { setMyStringBuffer(); try{ int i=0; //add the content of the string buffer to a local string myStr JSONObject jsonObject3 = new JSONObject(stringBuffer.toString()); JSONObject jsonObject2 = new JSONObject(stringBuffer.toString()); int numberOfJsonObject = jsonObject2.getInt("success"); //get the number of json objects theMessageFromDB = ""; theMessageFromDB = jsonObject3.getString("message"); //get the message from the database if(!manyArys.isEmpty()){ manyArys.clear(); } int tam = columnValues.size(); while (i < numberOfJsonObject) { ArrayList<String> arys = new ArrayList<String>(); JSONObject jsonObject = new JSONObject(stringBuffer.toString()); JSONArray jsonArray = jsonObject.getJSONArray("profiles"); JSONObject finalJsonObject = jsonArray.getJSONObject(i); int t=0; while(t<tam) { arys.add(finalJsonObject.getString(columnNames.get(t))); t++; } manyArys.add(arys); i++; } } catch (JSONException e) { e.printStackTrace(); }}

Page 158: UniSubject - rodin.uca.es

Page � of �158 188

//put all the data from the array of array strings in a simple stringprivate String convertManyArrayToString(){ if(!manyArys.isEmpty()) { int numberOfRecords = manyArys.size(); int recordSize = manyArys.get(0).size(); int i = 0, j = 0; String str = ""; while (i < numberOfRecords) { j = 0; while (j < recordSize) { str += manyArys.get(i).get(j) + " "; j++; } str += "\n\n"; i++; } return str; }else{ myMeg += " No Profile found "; return myMeg; }} //save the data given by the user to the external databasepublic String registerUser () throws IOException { openConnection(); int i =0; int t =0; //tam has the number of columns in the given table int tam = columnValues.size(); data = ""; while( i<tam-1){ data += URLEncoder.encode(columnNames.get(i), "UTF-8") + "=" + URLEncoder.encode(columnValues.get(i), "UTF-8") +"&"; i++; } data += URLEncoder.encode(columnNames.get(i), "UTF-8") + "=" + URLEncoder.encode(columnValues.get(i), "UTF-8"); closeConnectionToWrite(); setMyStringBuffer(); String res = ""; //convert the data in the stringbuffer to a simple string res += stringBuffer.toString(); //if the database result was successful we convert the json format to String if(!res.equals("0")){ convertJsonToStrings(); res += " - Registration Success..."; }else{ res += "user already exist"; } closeConnectionToRead(); // return "Registration Success..."; return res;}

Page 159: UniSubject - rodin.uca.es

Page � of �159 188

public String getSingleData () throws IOException { openConnection(); data =""; data += URLEncoder.encode(columnNames.get(0), "UTF-8") + "=" + URLEncoder.encode(columnValues.get(0), "UTF-8") + "&" + URLEncoder.encode(columnNames.get(5), "UTF-8") + "=" + URLEncoder.encode(columnValues.get(5), "UTF-8"); closeConnectionToWrite(); // openConnectionToRead(login_url); respon = ""; //call the method to transfer the json result to a shared multi array convertJsonToStrings(); //call the method to transfer the result in the shared multi array to a string respon += convertManyArrayToString(); closeConnectionToRead(); return respon; } public String loginUser () throws IOException { openConnection(); data =""; data += URLEncoder.encode(columnNames.get(1), "UTF-8") + "=" + URLEncoder.encode(columnValues.get(1), "UTF-8") + "&" + URLEncoder.encode(columnNames.get(3), "UTF-8") + "=" + URLEncoder.encode(columnValues.get(3), "UTF-8"); closeConnectionToWrite(); // openConnectionToRead(login_url); respon = ""; //call the method to transfer the json result to a shared multi array convertJsonToStrings(); //call the method to transfer the result in the shared multi array to a string respon += convertManyArrayToString(); closeConnectionToRead(); return respon; } public String getAllTheUsers () throws IOException { openConnectionToRead(); respon = ""; //call the method to transfer the json result to a shared multi array convertJsonToStrings(); //call the method to transfer the result in the shared multi array to a string respon += convertManyArrayToString(); closeConnectionToRead(); return respon; }

Page 160: UniSubject - rodin.uca.es

Page � of �160 188

public String unSubscribe () throws IOException { openConnection(); data = URLEncoder.encode(columnNames.get(0), "UTF-8") + "=" + URLEncoder.encode(columnValues.get(0), "UTF-8") ; closeConnectionToWrite(); // openConnectionToRead(reg_url); respon = ""; //call the method to transfer the json result to a shared multi array setMyStringBuffer(); respon += stringBuffer.toString(); closeConnectionToRead(); // return "Registration Success..."; return respon; } public String getLatitudeAndLongitude() throws IOException, JSONException { openConnectionToRead(); setMyStringBuffer(); if(!singleArys.isEmpty()){ singleArys.clear(); } JSONObject jsonObject = new JSONObject(stringBuffer.toString()); double lng = ((JSONArray) jsonObject.get("results")).getJSONObject(0) .getJSONObject("geometry").getJSONObject("location") .getDouble("lng"); singleArys.add("" + lng); double lat = ((JSONArray) jsonObject.get("results")).getJSONObject(0) .getJSONObject("geometry").getJSONObject("location") .getDouble("lat"); singleArys.add(""+lat); closeConnectionToRead(); String st = stringBuffer.toString(); return st;}

Page 161: UniSubject - rodin.uca.es

Page � of �161 188

//save the data given by the user to the external databasepublic String registerGallery () throws IOException { openConnection(); int i =0; int t =0; //tam has the number of columns in the given table int tam = columnValues.size(); data = ""; while( i<tam-1){ data += URLEncoder.encode(columnNames.get(i), "UTF-8") + "=" + URLEncoder.encode(columnValues.get(i), "UTF-8") +"&"; i++; } data += URLEncoder.encode(columnNames.get(i), "UTF-8") + "=" + URLEncoder.encode(columnValues.get(i), "UTF-8"); closeConnectionToWrite(); convertJsonToStrings(); String res = ""; //convert the data in the stringbuffer to a simple string res += convertManyArrayToString(); closeConnectionToRead(); return res;} //The method that execute everything in the background. It receives the parameters in an array@Overrideprotected String doInBackground(String... params) { methods=params[0]; ArrayList<String> myParams = new ArrayList<String>(); for(String pa : params){ myParams.add(pa); } //call to create and set the a collection of the data of the given table setEntryDatas(myParams); switch (methods) { case "register" :{ //to add a new user profile try { respon =""; respon += registerUser(); return respon; } catch (IOException e) { e.printStackTrace(); } }break; case "editing" :{ //to update the user account try { respon =""; respon += registerUser(); return respon; } catch (IOException e) { e.printStackTrace(); } }break;

Page 162: UniSubject - rodin.uca.es

Page � of �162 188

case "login" :{ //to login user try { String st=""; st += loginUser(); return st; } catch (IOException e) { e.printStackTrace(); } } break; case "user" : { //to get all user profile try { getAllTheUsers(); return "updating ..."; } catch (IOException e) { e.printStackTrace(); } }break; case "unsubscribe": { //to eliminate profile try { return unSubscribe(); } catch (IOException e) { e.printStackTrace(); } }break; case "getAData": { //to get a data try { return getSingleData(); } catch (IOException e) { e.printStackTrace(); } }break; case "latAndLng": { //to eliminate profile try { return getLatitudeAndLongitude(); } catch (IOException e) { e.printStackTrace(); }catch (JSONException e) { e.printStackTrace(); } }break; case "registerGallery" :{ //to add a new user profile try { //create the byte representation of the image ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); respon =""; respon += registerGallery(); return respon; } catch (IOException e) { e.printStackTrace(); } catch(Exception e){ e.getMessage(); } }break; default: respon += "Error"; } return respon + " del final"; }

Page 163: UniSubject - rodin.uca.es

Page � of �163 188

@Override protected void onProgressUpdate(Void... values) { super.onProgressUpdate(values); } @Override protected void onPostExecute(String result) { int sw = 0; if (methods.equals("latAndLng")){ if (secondDelegate != null) { //return success or fail to activity secondDelegate.secondProcessFinish(singleArys); } // Toast.makeText(ctx, singleArys.get(0).toString() + " = lng and lat = " + singleArys.get(1).toString(), Toast.LENGTH_LONG).show(); }else { if (delegate != null) { //return success or fail to activity delegate.processFinish(manyArys); } Toast.makeText(ctx, theMessageFromDB +" from onPostExecute this is the message from the database "+result, Toast.LENGTH_LONG).show(); Log.e(TAG, theMessageFromDB + " = this is the message from the database. from onPostExecute result = "+result); } } }

Page 164: UniSubject - rodin.uca.es

5.2.7 Gestores de datos

Las siguientes clases proporcionan acceso simplificado a los datos almacenados de forma persistente en la base de datos local (SQLite). Los gestores de datos componen la capa de acceso a datos de la aplicación y proporcionan contenidos a la capa de negocio.

Page � of �164 188

package lbs.uca.es.lbs;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.util.Log;import java.util.ArrayList;import java.util.List;/** * Created by ale on 15/12/15. */public class GenericDataDAO { public static final String TAG = "GenericDataDAO"; private Context uContext; public static List<String> columnNames; public List<String> columnValues; private String theTable; private int id ; public OpenCloseDB openCloseDB; public GenericDataDAO(Context context) { this.uContext = context; openCloseDB = new OpenCloseDB(context); columnNames = new ArrayList<String>(); columnValues = new ArrayList<String>(); } private void setEntryDatas(ArrayList<String> colmNames, ArrayList<String> colmValues){ if(!columnNames.isEmpty()) columnNames.clear(); if(!columnValues.isEmpty()) columnValues.clear(); this.columnNames.addAll(colmNames); this.columnValues.addAll(colmValues); this.theTable =""; this.theTable += columnNames.get(0); this.id = Integer.parseInt(colmValues.get(0)); }

Page 165: UniSubject - rodin.uca.es

Page � of �165 188

boolean saveData(ArrayList<String> colmNames, ArrayList<String> colmValues){ setEntryDatas(colmNames, colmValues); ArrayList<String> temp = new ArrayList<String>(); if(!temp.isEmpty()) temp.clear(); temp.addAll(findByIdData(colmNames, colmValues)); long t=0; boolean resul=false; if(temp.size() == 0) { if(! isDataExist(colmNames, colmValues)) { //call the method open() to crear el tipo de base de datos (en este caso un writable) openCloseDB.openW(); //crear un objeto ContentValues values para guardar los atributes del objeto university (parece una mapa) ContentValues values = new ContentValues(); values = addValuesForData(values); //al final invoke the method assValues to insertar the university values in the table t = openCloseDB.uDatabase.insert(theTable, null, values); openCloseDB.close(); } } if (t > 0) { // Log.e(TAG, colmValues.get(1) + " IS SAVED ********************* " ); resul = true; } return resul;} boolean updateData (ArrayList<String> colmNames, ArrayList<String> colmValues){ setEntryDatas(colmNames, colmValues); openCloseDB.openW(); //el ContentValues values tendra los datos del UserData, es como un array o una mapa ContentValues values = new ContentValues(); values = addValuesForData(values); //para modificar el objecto se pasa el string que tienes el nombre de la tabla, TABLE_SUBJECTS, //luego los valores que estan guardado en values y se reemplasar //el where statement con solo el string que tiene el nombre del columna y la data del where statement int result = openCloseDB.uDatabase.update(theTable, values, colmNames.get(1) + "=?", new String[]{String.valueOf(id)}); openCloseDB.close(); if(result != 0) { // Log.e(TAG, colmValues.get(1) + " IS UPDATED ********************* " ); return true; }else { // Log.e(TAG, colmValues.get(1) + " I S N T UPDATED ********************* " ); return false; }

Page 166: UniSubject - rodin.uca.es

Page � of �166 188

boolean deleteData(ArrayList<String> colmNames, ArrayList<String> colmValues){ setEntryDatas(colmNames, colmValues); openCloseDB.openW(); int result = openCloseDB.uDatabase.delete(theTable, colmNames.get(1) + "=?", new String[]{String.valueOf(id)}); openCloseDB.close(); if(result != 0) { // Log.e(TAG, colmValues.get(1) + " IS DELETED ********************* "); return true; }else { return false; }} ArrayList<String> findByIdData (ArrayList<String> colmNames, ArrayList<String> colmValues){ setEntryDatas(colmNames, colmValues); ArrayList<String> results = new ArrayList<String>(); openCloseDB.openR(); Cursor cursor = openCloseDB.uDatabase.query(theTable, setAllColumns(), colmNames.get(1) + "=?", new String[]{String.valueOf(colmValues.get(0))}, null, null, null, null); // Log.e(TAG, cursor.getPosition() + " = cursor.getPosition() ********************* data =" + cursor.getCount()); //comprueba si has encontrar el university con dicha id if (cursor.getCount() != 0) { cursor.moveToFirst(); //This, Uri.parse(cursor.getString(5), convert the string to Uri results.addAll(createADataFromCursor(cursor)); } openCloseDB.uDatabase.close(); cursor.close(); return results;} boolean isDataExist (ArrayList<String> colmNames, ArrayList<String> colmValues){ setEntryDatas(colmNames, colmValues); ArrayList<String> results = new ArrayList<String>(); boolean resul=false; openCloseDB.openR(); Cursor cursor = openCloseDB.uDatabase.query(theTable, setAllColumns(), colmNames.get(2) + "=?", new String[]{colmValues.get(1)}, null, null, null, null); //comprueba si has encontrar el university con dicha id if (cursor.getCount() != 0) { cursor.moveToFirst(); resul= true; } openCloseDB.uDatabase.close(); cursor.close(); return resul;}

Page 167: UniSubject - rodin.uca.es

Page � of �167 188

//metodo para get todos los datos de la tabla, crear los userData y insertarlo en una lista llamada userData y// devolver la listaArrayList<ArrayList<String>> getAllData (ArrayList<String> colmNames, ArrayList<String> colmValues){ setEntryDatas(colmNames, colmValues); ArrayList<ArrayList<String>> allDatas = new ArrayList<ArrayList<String>>(); openCloseDB.openW(); //el objeto cursor recibe el resultado de query Cursor cursor = openCloseDB.uDatabase.rawQuery("SELECT * FROM " + theTable, null); //moveToFirst devuelve true si el cursor no es null if (cursor.moveToFirst()) { do { //iterando creando todos los UserData y añadirlas a la lista, UserData. allDatas.add(createADataFromCursor(cursor)); }while (cursor.moveToNext()); //moveToNext devuelve true tambien } openCloseDB.close(); cursor.close(); return allDatas;} //get the number of UserData in the dbpublic int getDatasCount(String theTableName) { openCloseDB.openR(); Cursor cursor = openCloseDB.uDatabase.rawQuery("SELECT * FROM " + theTableName, null); int count = cursor.getCount(); openCloseDB.close(); cursor.close(); return count;} void flush(){} //DAO for Subjectprivate String[] setAllColumns() { int i = 1; int tam = columnNames.size(); String[] ssAllColumns = new String[tam - 1]; while (i < tam) { ssAllColumns[i - 1] = columnNames.get(i); i++; } return ssAllColumns;}

Page 168: UniSubject - rodin.uca.es

Page � of �168 188

public ContentValues addValuesForData(ContentValues values){ int i = 0; int tam = columnValues.size(); while (i<tam){ values.put(columnNames.get(i + 1), columnValues.get(i)); i++; } return values;} public ArrayList<String> createADataFromCursor(Cursor cursor){ ArrayList<String> datas = new ArrayList<String>(); int i = 0; int tam = cursor.getColumnCount(); while (i < tam) { datas.add(cursor.getString(i)); i++; } return datas;} //Check if a given UserData is in the databasepublic ArrayList<String> getUserDataByEmailAndPassword(ArrayList<String> colmNames, ArrayList<String> colmValues){ setEntryDatas(colmNames, colmValues); ArrayList<String> results = new ArrayList<String>(); openCloseDB.openR(); //el objeto cursor recibe el resultado de query //comprueba si has encontrar el asignatura con nombre Cursor cursor = openCloseDB.uDatabase.query(theTable, setAllColumns(), colmNames.get(2) + "=?" + " AND " + colmNames.get(4) + "=?", new String[]{colmValues.get(1), colmValues.get(3)}, null, null, null, null); //If we find a user with the same username and password then we return true //If we find a user with the same username and password then we return true if (cursor.getCount() != 0) { cursor.moveToFirst(); results.addAll(createADataFromCursor(cursor)); } openCloseDB.uDatabase.close(); cursor.close(); return results;} public ArrayList<String> findDataByName (ArrayList<String> colmNames, ArrayList<String> colmValues){ setEntryDatas(colmNames, colmValues); ArrayList<String> results = new ArrayList<String>(); openCloseDB.openR(); //el objeto cursor recibe el resultado de query //comprueba si has encontrar el asignatura con nombre Cursor cursor = openCloseDB.uDatabase.query(theTable, setAllColumns(), colmNames.get(2) + "=?", new String[]{colmValues.get(1)}, null, null, null, null); //If we find a user with the same username and password then we return true if (cursor.getCount() != 0){ cursor.moveToFirst(); results.addAll(createADataFromCursor(cursor)); } openCloseDB.uDatabase.close(); cursor.close(); return results; }}

Page 169: UniSubject - rodin.uca.es

Database helper for SQLite

Page � of �169 188

package lbs.uca.es.lbs;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;import android.util.Log;/** * Created by ale on 11/06/15. */public class DatabaseHandler extends SQLiteOpenHelper { private static final int DATABASE_VERSION = 1; public static final String TAG = "DatabaseHandler"; // public static SQLiteDatabase uDatabase; //Database management public static final String DATABASE_NAME = "universityManager", TABLE_UNIVERSITIES = "universities", KEY_ID_UNI = "id", KEY_NAME_UNI = "nameUni", KEY_YEAR_UNI = "year", KEY_POPULATION_UNI = "population", Key_PHONE_UNI = "phone", KEY_EMAIL_UNI = "email", KEY_ADDRESS_UNI = "address", KEY_COUNTRY_UNI = "country", KEY_CONTINENTE_UNI = "continente", KEY_DESCRIPTION_UNI = "description", KEY_INFO = "info", KEY_LONGITUDE = "longitude", KEY_LATITUDE = "latitude", KEY_WEB_UNI = "webUri", KEY_IMAGE_UNI = "imageUni", KEY_HITS_UNI = “hits", TABLE_FACULTY = "faculties", KEY_ID_FACULTY = "id", KEY_NAME_FACULTY = "nameFaculty", KEY_IMAGE_FACULTY = "imageFaculty", KEY_LONGITUDE_FACULTY = "longitude", KEY_LATITUDE_FACULTY = "latitude", KEY_POPULATION_FACULTY = "population", KEY_PHONE_FACULTY = "phone", KEY_EMAIL_FACULTY = "email", KEY_ADDRESS_FACULTY = "address", KEY_DESCRIPTION_FACULTY = "description", KEY_INFO_FACULTY = "info", KEY_WEB_FACULTY = "webFACULTY", KEY_ID_UNI_FACULTY = "idUni", KEY_HITS_FACULTY = "hits",

Page 170: UniSubject - rodin.uca.es

Page � of �170 188

TABLE_MAJOR = "majors", KEY_ID_MAJOR = "id", KEY_NAME_MAJOR = "nameMajor", KEY_IMAGE_MAJOR = "imageMajor", KEY_WEB_MAJOR = "webMAJOR", KEY_ID_FACULTY_MAJOR = "idFaculty", KEY_HITS_MAJOR = "hits", TABLE_SUBJECTS = "subjects", KEY_ID_SUBJECT = "id", KEY_NAME_SUBJECT = "nameSubject", KEY_DESCRIPTION_SUBJECT = "description", KEY_ID_MAJOR_SBJ = "idMajorSubl", KEY_HITS_SUBJECT = "hits", KEY_LIKE_SUBJECT = "like", KEY_DISLIKE_SUBJECT = "dislike", TABLE_UNI_APP_USER = "userdatas", KEY_ID_USER_DATA = "id", KEY_UNI_APP_USER_EMAIL = "email", KEY_UNI_APP_USER_NAME = "uniAppUserName", KEY_UNI_APP_USER_PASSWORD = "uniAppUserPassword", KEY_UNI_APP_USER_ROLE = "uniAppUserRole", KEY_UNI_APP_USER_STATUS = "uniAppUserStatus", TABLE_IMAGE_GALLERY = "galleries", KEY_ID_GALLERY = "id", KEY_NAME_GALLERY = "nameGallery", KEY_TYPE_GALLERY = "type", KEY_PARENT_GALLERY = "idParent", KEY_LIKE_GALLERY = "like"; public String DATABASE_QUERY_CREATE_UNIVERSITY = "CREATE TABLE " + TABLE_UNIVERSITIES + "(" + KEY_ID_UNI + " INTEGER PRIMARY KEY," + KEY_NAME_UNI + " TEXT," + KEY_YEAR_UNI + " TEXT," + KEY_POPULATION_UNI + " TEXT," + Key_PHONE_UNI + " TEXT," + KEY_EMAIL_UNI + " TEXT," + KEY_ADDRESS_UNI + " TEXT," + KEY_COUNTRY_UNI + " TEXT," + KEY_CONTINENTE_UNI + " TEXT," + KEY_DESCRIPTION_UNI + " TEXT," + KEY_INFO + " TEXT," + KEY_LONGITUDE + " DOUBLE," + KEY_LATITUDE + " DOUBLE," + KEY_WEB_UNI + " TEXT," + KEY_IMAGE_UNI + " INTEGER," + KEY_HITS_UNI + " INTEGER);";

Page 171: UniSubject - rodin.uca.es

Page � of �171 188

public String DATABASE_QUERY_CREATE_FACULTY = "CREATE TABLE " + TABLE_FACULTY + "(" + KEY_ID_FACULTY + " INTEGER PRIMARY KEY," + KEY_NAME_FACULTY + " TEXT," + KEY_IMAGE_FACULTY + " INTEGER," + KEY_LONGITUDE_FACULTY + " DOUBLE," + KEY_LATITUDE_FACULTY + " DOUBLE," + KEY_POPULATION_FACULTY + " TEXT," + KEY_PHONE_FACULTY + " TEXT," + KEY_EMAIL_FACULTY + " TEXT," + KEY_ADDRESS_FACULTY + " TEXT," + KEY_DESCRIPTION_FACULTY + " TEXT," + KEY_INFO_FACULTY + " TEXT," + KEY_WEB_FACULTY + " TEXT," + KEY_ID_UNI_FACULTY + " INTEGER," + KEY_HITS_FACULTY + " INTEGER," + " FOREIGN KEY ("+ KEY_ID_UNI_FACULTY + ") REFERENCES " + TABLE_UNIVERSITIES + "(" + KEY_ID_UNI + "));"; public String DATABASE_QUERY_CREATE_MAJOR = "CREATE TABLE " + TABLE_MAJOR + "(" + KEY_ID_MAJOR + " INTEGER PRIMARY KEY," + KEY_NAME_MAJOR + " TEXT," + KEY_IMAGE_MAJOR + " INTEGER," + KEY_WEB_MAJOR + " TEXT," + KEY_ID_FACULTY_MAJOR + " INTEGER," + KEY_HITS_MAJOR + " INTEGER," + " FOREIGN KEY ("+ KEY_ID_FACULTY_MAJOR + ") REFERENCES " + TABLE_FACULTY + "(" + KEY_ID_FACULTY + "));"; public String DATABASE_QUERY_CREATE_SUBJECT = "CREATE TABLE " + TABLE_SUBJECTS + "(" + KEY_ID_SUBJECT + " INTEGER PRIMARY KEY," + KEY_NAME_SUBJECT + " TEXT," + KEY_DESCRIPTION_SUBJECT + " TEXT," + KEY_ID_MAJOR_SBJ + " INTEGER," + KEY_HITS_SUBJECT + " INTEGER," + KEY_LIKE_SUBJECT + " INTEGER," + KEY_DISLIKE_SUBJECT + " INTEGER," + " FOREIGN KEY ("+ KEY_ID_MAJOR_SBJ + ") REFERENCES " + TABLE_MAJOR + "(" + KEY_ID_MAJOR + "));";

Page 172: UniSubject - rodin.uca.es

Page � of �172 188

public String DATABASE_QUERY_CREATE_GALLERY = "CREATE TABLE " + TABLE_IMAGE_GALLERY + "(" + KEY_ID_GALLERY + " INTEGER PRIMARY KEY," + KEY_NAME_GALLERY + " TEXT," + KEY_TYPE_GALLERY + " TEXT," + KEY_PARENT_GALLERY + " TEXT," + KEY_LIKE_GALLERY + " INTEGER);"; //To create the database public DatabaseHandler(Context context){ super(context, DATABASE_NAME, null, DATABASE_VERSION); Log.d(TAG, "Database successfully created"); } //To create the table for the University database @Override public void onCreate(SQLiteDatabase db) { db.execSQL(DATABASE_QUERY_CREATE_UNIVERSITY); Log.d(TAG, "University table successfully created"); db.execSQL(DATABASE_QUERY_CREATE_FACULTY); Log.d(TAG, "Faculty table successfully created"); db.execSQL(DATABASE_QUERY_CREATE_MAJOR); Log.d(TAG, "Major table successfully created"); db.execSQL(DATABASE_QUERY_CREATE_SUBJECT); Log.d(TAG, "Subject table successfully created"); db.execSQL(DATABASE_QUERY_CREATE_USER); Log.d(TAG, "App user table successfully created"); db.execSQL(DATABASE_QUERY_CREATE_GALLERY); Log.d(TAG, "App gallery table successfully created"); } //When we update the table we first drop it (eleminarlo) y lueg llamar el metodo onCreate para crearlo de nuevo @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //note that before we drop the table we should save the data and give the user the option to restore the unchanged data or not db.execSQL("DROP TABLE IF EXISTS " + TABLE_UNIVERSITIES); db.execSQL("DROP TABLE IF EXISTS " + TABLE_FACULTY); db.execSQL("DROP TABLE IF EXISTS " + TABLE_MAJOR); db.execSQL("DROP TABLE IF EXISTS " + TABLE_SUBJECTS); db.execSQL("DROP TABLE IF EXISTS " + TABLE_UNI_APP_USER); db.execSQL("DROP TABLE IF EXISTS " + TABLE_IMAGE_GALLERY); Log.w(TAG, "Upgrading the database from version " + oldVersion + " to " + newVersion); onCreate(db); }}

Page 173: UniSubject - rodin.uca.es

5.2.8 Interface

El marco de trabajo Android proporciona la flexibilidad de poder declarar los elementos que componen la UI tanto en documentos XML como en tiempo de ejecución. Por ejemplo, es posible declarar los diseños predeterminados de la aplicación en XML, incluyendo los elementos que apareceran en las distintas pantallas y sus propiedades. También es posible incluir código en la aplicación que modifique el estado de los objetos en pantalla, incluyendo los que han sido declarados en XML, en tiempo de ejecución.

La ventaja de declarar la UI en XML es que permite separar de forma más eficiente la presentación de la aplicación del código que controla su comportamiento. De esta forma, la definición de la UI es externa al código de la aplicación, lo cual significa que puede modificarse o adaptarse sin tener que modificar el código fuente y recompilar.

UI del perfil de usuario

Page � of �173 188

<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:background="#ffe2ccfc" android:orientation="vertical" tools:context="lbs.uca.es.lbs.UserProfile"> <TextView android:layout_width="match_parent" android:layout_height="10dp" android:id="@+id/textViewPg25Line1" android:background="#ff844d9b" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:id="@+id/linLayPg25pic" android:orientation="horizontal" android:weightSum="2"> <ImageView android:layout_width="80dp" android:layout_height="80dp" android:id="@+id/imgVPg25" android:layout_gravity="top|left" android:orientation="vertical" android:layout_weight="1" android:background="@drawable/ale" />

Page 174: UniSubject - rodin.uca.es

Page � of �174 188

<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="UniSubject User Profile" android:id="@+id/textView25" android:orientation="vertical" android:layout_marginLeft="20dp" android:textStyle="bold" android:textColor="#ff610f6e" android:textSize="25dp" android:layout_gravity="center_vertical" android:layout_weight="1" android:textAlignment="center" /> </LinearLayout> <TextView android:layout_width="match_parent" android:layout_height="10dp" android:id="@+id/textViewPg25Line2" android:background="#ff844d9b" /> <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/LinLayPg1Scroll" android:orientation="vertical"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Email: " android:textColor="#ff610f6e" android:id="@+id/textViewPg25Email" android:layout_marginTop="20dp" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="User Name: " android:textColor="#ff610f6e" android:id="@+id/textViewPg25userName" android:layout_marginTop="10dp" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Role: " android:textColor="#ff610f6e" android:id="@+id/textViewPg25Role" android:layout_marginTop="10dp" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Back" android:id="@+id/btnPg25Back" android:textColor="#fff5e7fc" android:textStyle="bold" android:layout_weight="1"

Page 175: UniSubject - rodin.uca.es

5.3.2 Clase de conexión

La siguiente clase PHP proporcionan acceso simplificado a los datos almacenados en la base de datos de la parte servidor (MySQL). Contiene métodos para realizar la conexión y desconexión de la base de datos, así como los métodos necesarios para extraer o introducir la información en las tablas que la componen. Se incluye un pequeño script que trata de aportar algo de seguridad frente a SQL injection.

umconexion.php

Page � of �175 188

<?php include("umsecurity.php");

class Database{ // Connection param var $database_name; var $database_user; var $database_pass; var $database_host; var $database_link;

// Constructor. function Database() { $this->database_user = "root"; $this->database_pass = ""; $this->database_host = "localhost"; $this->database_name = "universitymanager"; }

// Method to connect to the database. function connect() { $this->database_link = mysqli_connect($this->database_host, $this->database_user, $this->database_pass) or die("\Could not make connection to MySQL"); mysqli_select_db($this->database_link, $this->database_name) or die ("Could not open database: ". $this->database_name);

}

// Method to disconnect the database. function disconnect() { if(isset($this->database_link)){ mysqli_close($this->database_link); }else{ mysqli_close($this->database_link); } }

Page 176: UniSubject - rodin.uca.es

Page � of �176 188

// Method to make modifications or insertions. function iquery($qry) { if(!isset($this->database_link)) { $this->connect(); } mysqli_query($this->database_link, "SET CHARACTER SET utf8 "); $temp = mysqli_query($this->database_link, $qry) ; //or die("Error: ". mysqli_error($this->database_link)); return $temp; //return mysqli_affected_rows(); } //Method to count the number of rows. function countquery($qry) { if(!isset($this->database_link)){ $this->connect(); } $result = mysqli_query($this->database_link, $qry) or die("Error: ". mysqli_error($this->database_link)); $row = mysqli_fetch_array($result, MYSQL_BOTH); return $row[0]; }

//Method to make selection. function squery($qry) { if(!isset($this->database_link)){ $this->connect(); } mysqli_query($this->database_link, "SET CHARACTER SET utf8 "); $result = mysqli_query($this->database_link, $qry) or die("Error: ". mysqli_error($this->database_link)); $returnArray = array(); $i=0; while ($row = mysqli_fetch_array($result, MYSQL_BOTH)){ if ($row) { $returnArray[$i++]=$row; } } mysqli_free_result($result); return $returnArray; }

} ?>

Page 177: UniSubject - rodin.uca.es

Capítulo 6. Pruebas de sistema

En este capítulo se documentan los diferentes tipos de pruebas que se han llevado a cabo durante el desarrollo del sistema. Como se mencionó en la fase de planificación, para realizar las pruebas del sistema se ha contado con la ayuda de varios colaboradores, que se han encargado de realizar pruebas guiadas por el desarrollador para cada módulo desarrollado, aportando el máximo nivel posible de detalles para cada error encontrado, con el fin de que pueda ser reproducido por el desarrollador en el depurador de Android Studio para ser corregido.

Ha sido especialmente importante la colaboración de personas externas al desarrollo al realizar las pruebas, ya que existe un gran nivel de fragmentación entre dispositivos móviles Android, y su colaboración ha permitido realizar pruebas en un mayor número de dispositivos con diferentes características y versiones del sistema operativo, así como tamaños de pantallas y disposiciones de los botones físicos. Las pruebas más específicas o de carácter más técnico han sido realizadas directamente por el desarrollador.

6.1 Pruebas unitarias

Las pruebas unitarias tienen por objetivo localizar errores en cada nuevo módulo desarrollado, antes que se produzca la integración con el resto de módulos del sistema. Estas pruebas se han llevado a cabo de forma manual para cada módulo, teniendo en cuenta lo siguiente:

6.1.1 Validación de entrada

Es necesario comprobar que una actividad responde correctamente a la introducción de datos. Esto puede lograrse comprobando el valor de los campos de introducción en distintas secciones del código y validado que se mantiene la integridad de los datos introducidos. También es importante comprobar que los campos de introducción de datos no admiten datos no permitidos o con formato erróneo.

Para los script del servicio web, se ha comprobado que no se aceptan palabras reservadas en el cuerpo del mensaje, y que los valores recuperados o introducidos en la base de datos cumplen el formato y la codificación esperados.

6.1.2 Cambio de orientación de la pantalla

Para los dispositivos que soportan múltiples orientaciones, Android detecta un cambio en la orientación cuando el usuario gira el dispositivo. Cuando Android detecta cambios en la orientación, su comportamiento por defecto es destruir y volver a comenzar la actividad que está en primer plano. Por lo tanto se deben comprobar

Page � of �177 188

Page 178: UniSubject - rodin.uca.es

que la pantalla vuelve a redibujarse correctamente y que el estado de la aplicación se mantiene. La actividad no debe perder ninguna información que el usuario haya introducido en la UI, ni olvidar el lugar donde se encontraba en la transacción actual.

6.1.3 Eventos del ciclo de vida

Estas pruebas tienen como objetivo comprobar que cada una de las actividades de la aplicación se comporta de manera correcta cuando se ejecutan eventos del ciclo de vida. En general, los eventos del ciclo de vida son acciones, tanto del usuario como del sistema, que desencadenan un método de respuesta como onCreate() u onClick(). Por ejemplo, una actividad debe responder a eventos de pausa o destrucción guardando su estado, teniendo en cuenta que incluso un cambio en la orientación de la pantalla causa que la actividad actual sea destruida, por lo tanto es necesario comprobar que movimientos accidentales del dispositivo no causan pérdidas en el estado de la aplicación.

Page � of �178 188

Page 179: UniSubject - rodin.uca.es

6.2 Pruebas de integración

Este tipo de pruebas tienen por objetivo localizar errores en módulos o subsistemas completos, analizando la interacción entre varios artefactos software.

6.2.1 Pruebas de navegabilidad

Para realizar las pruebas de navegabilidad se ha seguido el esquema de navegabilidad elaborado durante la fase de diseño, de forma que se compruebe que se pueden seguir todas las rutas y sentidos de navegación establecidas en el mismo para cada actividad y menú que forma parte de la aplicación.

6.2.2 Dependencia de recursos externos

La aplicación depende de recursos externos, como la conexión a redes, el GPS o los servicios de Google, por lo tanto es necesario comprobar que ocurre cuando dichos recursos no están disponibles.

Para los script del servicio web, se han realizado pruebas desde el navegador, comprobando que el comportamiento sea el esperado, es decir, que la operación solicitada se realiza con éxito y se devuelve el estado de éxito junto a la respuesta en el formato adecuado, o bien la operación fracasa y se devuelve el estado de fracaso.

6.3 Pruebas de sistema

Ya que el sistema se basa en una arquitectura cliente-servidor, es necesario comprobar el comportamiento del sistema cuando existe un gran número de usuarios registrados y se debe realizar una operación crítica, como puede ser la elaboración de la lista de resultados de compatibilidad. El tiempo de respuesta para las solicitudes del cliente no debe sobrepasar un nivel aceptable. Para realizar las pruebas de carga se han generado de forma automática N usuarios, utilizando el siguiente script en la parte servidor. Y comprobando que el tiempo de respuesta para operaciones críticas, como la elaboración de la lista de resultados de compatibilidad, está dentro de lo admisible.

6.4 Pruebas de aceptación

Como se ha explicado al inicio del capítulo, una serie de colaboradores han participado de forma activa durante las pruebas del sistema, notificando errores y aportando sugerencias sobre cómo mejorar la navegabilidad o las características de la aplicación. Dichas sugerencias, junto a las aportaciones del tutor, han mejorado la calidad del sistema resultando y han aportado suficiente información para realizar

Page � of �179 188

Page 180: UniSubject - rodin.uca.es

mejoras en la aplicación incluso más allá de lo previsto durante el desarrollo del proyecto. Esta información será recogida y comentadas durante el prólogo.

Page � of �180 188

Page 181: UniSubject - rodin.uca.es

Parte III

Epílogo

Page � of �181 188

Page 182: UniSubject - rodin.uca.es

Capítulo 7. Manual de usuario

7.1 Introducción El sistema utiliza la tecnología disponible para propiciar un servicio de búsqueda y comparación de entidades universitarias según las asignaturas que se oferten. El sistema permitir la creación de perfil universitario, facultad, major y asignatura. La aplicación basa su funcionamiento en ayudar el usuario comparar asignaturas de diferentes universidades en un tiempo de menos de un minuto.

7.2 Características

El usuario podrá registrar su perfil en el sistema, y una vez registrado podrá iniciar sesión en cualquier momento para acceder a todas las funciones que ofrece la aplicación.

7.3 Requisitos previos

El usuario debe instalar y ejecutar la aplicación en un dispositivo móvil con sistema operativo Android 2.3 (Gingebread) o superior, que disponga de capacidad de localización por satélite (GPS/AGPS), conexión a Internet (Wi-Fi, 3G, 4G, etc.), c

7.4 Instalación

Obtener el paquete AleSoft Las aplicaciones Android se instalan en el dispositivo móvil a partir de su paquete APK correspondiente. Normalmente, las aplicaciones pueden descargarse desde Google Play, la plataforma de distribución digital de aplicaciones móviles de Google, accediendo a dicha plataforma desde su versión web o directamente en el dispositivo móvil desde la aplicación para Google Play que viene instalada por defecto en los dispositivos Android. Actualmente, la aplicación sobre la cual trata el presente manual no está disponible en la plataforma Google Play, por lo tanto será necesario conectar el dispositivo móvil a un ordenador mediante conexión USB y copiar el paquete ALeSoft.apk (proporcionado en el DVD que acompaña este documento) en el sistema de ficheros del dispositivo.

Abrir el paquete APK con el Instalador de paquete de Android Una vez almacenado el paquete ALeSoft.apk en el dispositivo móvil, se puede retirar el cable USB y finalizar la conexión con el ordenador. Entonces se debe acceder desde el gestor del sistema de ficheros del dispositivo móvil a la ubicación del paquete APK y pulsar sobre el mismo, para que se inicie un diálogo que permita elegir al Instalador de paquete como método de apertura.

Page � of �182 188

Page 183: UniSubject - rodin.uca.es

Finalmente, cuando la instalación finaliza, si todo se ha salido correctamente, aparece un mensaje para notificar el éxito de la instalación.

7.5 Utilización

A continuación se describen los pasos necesarios para hacer uso de las funcionalidades del sistema, descritas en la sección 9.2 (Características).

Iniciar la aplicación Para iniciar la aplicación basta con buscar el icono del lanzador de la misma en el menú de aplicaciones del dispositivo móvil y pulsar sobre él, la aplicación se iniciará en pocos segundos.

Registrarse como usuario Para registrar a un usuario, lo primero que debe hacerse es acceder a la pantalla de registro de usuario desde la pantalla de inicio de sesión, para ello basta con pulsar el enlace disponible en dicha pantalla.

Cuando se muestra la pantalla de registro de usuario, se deben introducir los datos solicitados en los campos correspondientes, pudiéndose obtener información sobre el formato esperado mediante los botones de ayuda situados al lado de cada campo. Cuando todos los campos hayan sido debidamente cumplimentados, se debe finalizar el registro pulsando el botón de registro situado en la parte inferior de la pantalla. Iniciar sesión La pantalla de inicio de sesión es la primera que se muestra cuando se inicia la aplicación tal como se ha descrito en los apartados anteriores. Para iniciar sesión tan solo hay que introducir los parámetros de inicio de sesión en los campos habilitados para ello y pulsar el botón para iniciar sesión situado debajo de dichos campos.

Page � of �183 188

Page 184: UniSubject - rodin.uca.es

Page � of �184 188

Page 185: UniSubject - rodin.uca.es

Capítulo 9. Conclusiones

En este último capítulo se detallan las lecciones aprendidas tras el desarrollo del presente proyecto y se identifican las posibles oportunidades de mejora sobre el software desarrollado.

9.1 objectivos

9.1.1 Integración de conocimientos

Durante la realización del presente proyecto he tenido la oportunidad de repasar gran parte de lo aprendido durante mi paso por la titulación, aplicando los conocimientos previos obtenidos sobre ingeniería del software, bases de datos, estructuras de datos, estadística, desarrollo de aplicaciones informáticas multimedia, sistemas operativos y programación orientada a objetos, entre otros muchos conocimientos aportados por las distintas materias estudiadas.

Considero especialmente importante la obtención de una visión integradora de los diferentes campos a los que pertenecen dichos conocimientos, ya que me permite valorar la importancia que tienen todos y cada uno de ellos en un proyecto real, dándole sentido a tantas horas de estudio.

Por último, la responsabilidad que supone llevar a cabo un proyecto en todas sus etapas durante tantos meses de trabajo me ha permitido poner a prueba mi determinación y capacidad para llevar a cabo los objetivos planificados a pesar de los inconvenientes que han surgido durante la realización de los mismos.

9.1.2 Adquisición de conocimientos

La adquisición de conocimientos ha sido un punto clave del proyecto desde el primer momento. Dicho objetivo se ha mantenido de forma activa durante todo el desarrollo. El proyecto final de carrera marca el último tramo de mi aprendizaje dentro de la titulación, por lo tanto decidí ampliar mi formación durante la elaboración del mismo y no limitarme a la aplicación de los conocimientos previamente adquiridos.

Con dicho propósito en mente, decidí obtener nuevos conocimientos sobre el desarrollo de sistemas para dispositivos móviles, un campo que, como comenté al inicio del presente documento, ha experimentado una importante expansión en los últimos tiempos, consiguiendo una gran aceptación en la sociedad actual.

El desarrollo en Android me ha permitido conocer y aprender en gran medida el lenguaje Java, uno de los lenguajes más populares y actualmente más demandados que existen, sobre el cual apenas tenía conocimientos previos.

Page � of �185 188

Page 186: UniSubject - rodin.uca.es

9.1.3 Desarrollo de aplicación móvil

El desarrollo de una aplicación móvil es el producto resultante del aprendizaje y el esfuerzo llevado a cabo durante la realización del proyecto. En este aspecto, se ha conseguido desarrollar una aplicación sólida y funcional, con un aspecto elegante y una navegabilidad intuitiva.

La aplicación desarrollada es el fruto de la progresión a medida que se obtenían nuevos conocimientos relacionados con el desarrollo de aplicaciones móviles, por lo tanto admite un gran margen de mejora en todos sus aspectos, pero considero que se ha alcanzado un nivel bastante aceptable de profundidad y una base sólida sobre la cual seguir aprendiendo.

9.2 Lesiones aprendidas

9.2.1 Metodologías ágiles de desarrollo de software

Para el desarrollo del sistema se ha utilizado una metodología incremental, englobada dentro del marco de las metodologías ágiles de desarrollo de software. Dichas metodologías promueven la planificación adaptativa, el desarrollo evolutivo, la entrega temprana, la mejora continua y alienta una respuesta rápida y flexible frente a los cambios. Es un marco de trabajo que se enfoca en desarrollar el software a través de varios incrementos funcionales. Este tipo de metodología propone los siguientes principios:

- Satisfacer al consumidor entregando contenido funcional rápidamente. - Aceptar cambios en los requisitos, incluso en un estado avanzado del desarrollo. - Entregar contenido funcional con frecuencia. - Cooperación frecuente entre gente de negocios y desarrolladores - Los proyectos se construyen en torno a individuos motivados y de confianza. - El contenido funcional es la principal medición del progreso. - El desarrollo debe ser sostenible, manteniendo un ritmo constante de trabajo. - Prestar atención constantemente a la excelencia técnica y el buen diseño. - La simplicidad es esencial. - Desarrollar la capacidad de auto-organización. - La adaptación constante a circunstancias cambiantes.

Page � of �186 188

Page 187: UniSubject - rodin.uca.es

9.2.2 Separación entre presentación e implementación El desarrollo en Android está plenamente comprometido con la separación entre presentación e implementación. De esta forma es posible desarrollar la parte funcional de la aplicación sin tener que preocuparse por aspectos estéticos. De esta manera el desarrollador puede centrarse en cada tarea por separado, obteniendo mejores resultados en cada una de ellas.

Cuando es necesario realizar un cambio en la presentación o la implementación se tiene plena libertad para hacerlo, incluso en un estado avanzado del desarrollo, ya que los cambios que se realicen en un campo afectarán mínimamente al contenido del otro para la mayoría de los casos, siempre que la utilidad del módulo siga siendo la misma.

Después de probar este sistema de trabajo, se comprende en gran medida la utilidad del mismo y la gran cantidad de ventajas que ofrece frente a un desarrollo en el cual la presentación y la implementación estén estrechamente ligados.

9.2.3 Programación por capas

La programación por capas es una arquitectura en la cual el objetivo principal es la separación de la lógica de negocios de la lógica de diseño. La ventaja principal de este estilo es que el desarrollo se puede llevar a cabo en varios niveles y, en caso de que sobrevenga algún cambio, sólo se ataca al nivel requerido sin tener que revisar entre código mezclado.

En el diseño de sistemas informáticos actual se suelen usar las arquitecturas multinivel o programación por capas. En dichas arquitecturas a cada nivel se le confía una misión simple, lo que permite el diseño de arquitecturas escalables, que pueden ampliarse con facilidad en caso de que las necesidades aumenten. El diseño más utilizado actualmente es el diseño en tres niveles o capas: capa de presentación, capada de negocio y capa de datos.

El sistema desarrollado durante el proyecto actual sigue este último patrón de diseño en tres capas, de forma que cualquier capa puede ser modificada por separado para ajustarse a las necesidades cambiantes. De hecho, durante el desarrollo del sistema se pudo comprobar la utilidad de la programación por capas, ya que al principio del desarrollo se escogió SQL Server como SGBD de la parte servidor y más tarde decidió cambiarse por MySQL, para lo cual la división del sistema en capas fue de gran utilidad, ya que solo fue necesario realizar cambios en el nivel afectado del sistema.

Page � of �187 188

Page 188: UniSubject - rodin.uca.es

9.2.4 Gestión de riesgos

Cuando se inicia el desarrollo de proyecto es importante analizar los riesgos que pueden encontrarse, ya que podrían aparecer de forma inesperada si no se ha llevado a cabo un análisis sobre los mismos.

También es importante tomar todas las medidas posibles para evitar que dichos riesgos lleguen a convertirse en problemas, ya que podrían retrasar el proyecto e incluso acabar con su desarrollo.

Durante el desarrollo de un proyecto siempre pueden surgir problemas inesperados, que no pueden ser previstos durante el análisis, pero si se ha realizado bien la gestión de riesgos, no tendrán que añadirse riesgos evitables a los que surgen de forma inesperada, lo cual podría dañar seriamente al desarrollo.

9.3 Trabajo futuro

Durante el desarrollo del proyecto, algunos colaboradores han realizado interesantes aportaciones en forma de sugerencias de mejora aplicables al proyecto, las cuales se exponen a continuación. También se exponen algunas sugerencias realizadas por el tutor, o mejoras adicionales que pudieran mejorar la calidad del sistema.

Conclusiones He obtenido nuevos conocimientos sobre el desarrollo de sistemas para dispositivos móviles, un campo que, como comenté al inicio del presente documento, ha experimentado una importante expansión en los últimos tiempos, consiguiendo una gran aceptación en la sociedad actual.

El desarrollo en Android me ha permitido conocer y aprender en gran medida el lenguaje Java, uno de los lenguajes más populares y actualmente más demandados que existen, sobre el cual tenia poco conocimientos. He desarrollado una aplicación móvil sólida y funcional, con un aspecto elegante y una navegación rápida , como resultado de mi conocimiento previo y que he adquirido durante el aprendizaje y el desarrollo del proyecto. Mi aplicación ofrece al usuario las herramientas necesarias para la búsqueda y comparación de asignaturas universitarias sin perder su tiempo, sin la necesidad de su ordenador, cumpliendo el objetivo de encontrar y comunicar con la universidad en que desea cursar un curso. Sabiendo que este objetivo fue cumplido dentro del ámbito del proyecto, pero aun tengo mucho por explorar en este campo, por lo tanto seguiré trabajando y experimentando sobre ello.

Gracias

Page � of �188 188