Diagrama de clases

En el siguiente diagrama de clases se muestran las relaciones entre las clases utilizadas.

Las clases están clasificadas por colores según su tipo:

* Las clases en rojo indican que esas clases son *Fragments.*
* Las clases en azul son las *Activities* que forman la aplicación.
* Las de color morado son clases que interaccionan con archivos PHP en el servidor, usados para realizar conexiones a la base de datos(BD).
* Las clases en amarillo son utilizadas para crear *Dialogs* personalizados.
* Las verdes son adaptadores personalizados que se usan en los dos *ListViews* que hay en la aplicación.
* La clase en negro es el modelo de la aplicación. Es utilizada para guardar los datos recibidos de la BD en la aplicación y es usada como *caché.*

## Software de la aplicación Android

Ahora se mostrarán las clases por separado con una pequeña explicación que indica su rol en la aplicación y en que momento son utilizadas.

### **Activities**

En este apartado se muestran las actividades que conforman la aplicación. También se explica un poco la función de cada método.

Las actividades de la aplicación son las siguientes:

#### **MainActivity**

Es la primera actividad que aparece al abrir la aplicación. En ella aparece el *login,* para que el usuario se identifique y con ello se carguen sus datos en la aplicación. La clase solo tiene cuatro métodos:

* onCreate: Es el método con el que se indica el *layout* a utilizar y se le da funcionalidad a los botones de la pantalla asociada. Al ser este un método genérico en las siguientes clases solo se mencionará si realiza alguna acción diferente.
* registrar: Esta función es llamada a la hora de pulsar el botón "Registrarse". Envía al usuario a la ventana de registro eliminando la ventana del *login* de memoria.
* login: Este método es llamado a la hora de pulsar el botón "Acceder". Realiza una llamada a la clase que se utiliza para conectarse a la BD en el servidor mandando los parámetros necesarios.
* processFinish: Este el único método de la interfaz *AsyncResponse* que se encuentra en la clase DoHTTPRequest. En él se cogen los parámetros que se reciben de la BD en formato JSON. Si el usuario introducido es correcto reenvía al usuario a la actividad MenuPrincipalActivity, de lo contrario hace una llamada a la clase ErrorLoginDialog para mostrar un error por pantalla

#### **RegisterActivity**

Esta actividad es utilizada para poder añadir nuevos usuarios a la aplicación. En estos momentos el único campo obligatorio es el usuario, pero más adelante se quieren añadir la contraseña y la fecha de nacimiento ya que son relevantes para la aplicación.

Los métodos implementados en esta clase son:

* register: Con este método se comprueban los campos obligatorios y se comprueba que la contraseña y la contraseña repetida contengan los mismos caracteres. Si no son iguales o falta algún campo obligatorio, se muestra un *Toast* indicando qué ha causado el error. Si no falta ningún dato y todo es correcto, hace una llamada a la clase que se conecta a la BD para enviar la información introducida por el usuario.
* getFecha: Esta función llama a la clase DateDialog para mostrar un Dialog personalizado en el que aparece un calendario para escoger la fecha de nacimiento.
* administrarFecha: Dada una fecha, este método la pasa a *String* y la introduce en el *EditText*  que indica la fecha de nacimiento del usuario.
* processFinish: Al terminar de introducirse los datos en la BD se llama a este método para comprobar que los datos se han metido correctamente. Si ha habido algún error se le indica al usuario mediante un *Toast,* de lo contrario, manda una notificación indicando que se ha registrado correctamente y envía al usuario a la actividad MenuPrincipalActivity.

#### **MenuPrincipalActivity**

Está actividad hace de contenedor a uno o dos *Fragments* dependiendo de la orientación de la pantalla. Si la pantalla está en *landscape* (posición horizontal)aparecen dos *Fragments*, uno con el listado de los productos y otro con las especificaciones de un producto seleccionado. En caso de tener el dispositivo en posición vertical solo aparecerá el *Fragment* con el listado de los productos a la venta.

Los métodos implementados en esta clase son:

* onCreate: En esta clase se utiliza para guardar el usuario en *SharedPreferences* para mantener una "sesión" iniciada y que el usuario no tenga que introducir de nuevo el usuario y la contraseña.
* onCreateOptionsMenu: Este método especifica cual es el *layout* del menú que se usa en la ventana.
* onOptionsItemSelected: Esta función llama a otros métodos de esta misma clase dependiendo de el *item* del menú que haya pulsado el usuario.
* irAlCarro: Al pulsar "Ir al carro" en el menú se llama a esta función para que reenvíe al usuario a la actividad CarroActivity.
* cerrarSesion: Este es otro método llamado al pulsar la opción "Cerrar sesión". Elimina la variable que contiene el usuario de *SharedPreferences* y envía al usuario al *login.*
* onProductoFragmentInteractionListener: Método de implementación obligatoria por pertenecer a una interfaz necesaria pero que en este caso no se usa.
* onListaProductosFragmentInteractionListener: Este método llama a una función de los *Fragments* que contiene la actividad para actualizar el contenido de estos *Fragments.*
* onListaProductosFragmentSeleccionarComponente: Este método muestra al usuario un producto. Para ello primero comprueba la orientación del dispositivo. Si está en vertical abre la actividad ProductoActivity, la cual, se compone de un *Fragment* que muestra los detalles del producto que se ha seleccionado de la lista de productos. En caso de estar el dispositivo en *landscape*, al usuario se le mostrarán los detalles del producto seleccionado en la mitad derecha de la pantalla y a la izquierda seguirá viendo la lista de productos.

#### **ProductoActivity**

Esta clase contiene un *Fragment* con la información sobre un producto a la venta.

Los métodos implementados en esta clase son:

* onProductoFragmentInteractionListener: Este método llama a una función que actualiza la información del *Fragment* que contiene.

#### **CarroActivity**

Esta clase contiene un listado de los productos que el usuario quiere adquirir. En su pantalla aparece un listado de los productos que quiere comprar junto con el precio de cada uno de ellos, y, abajo del todo, se muestra el precio total de los componentes del listado junto con un botón para confirmar la compra de los productos.

Los métodos implementados en esta clase son:

* onCreateContextMenu: Este método crea un menú contextual en cada *item* de la lista para poder eliminarlo.
* onContextItemSelected: Método que llama a la función para eliminar un *item* de la lista de objetos del usuario en la bd.
* eliminarProductoCarro: Llama a la clase DoHTTPRequest para que desde esta se llame a la BD y así eliminar los datos.
* processFinish: Este método es llamado después de recibir la respuesta de la BD. Si solo se ha querido eliminar un producto, este se elimina de la lista y después se recalcula el precio total de todos los productos y se muestran los cambios por pantalla. En el caso de que se haya efectuado la compra del listado de productos, se eliminan todos los productos del carro de compra y el precio total se pone a cero. Si hay algún error durante el borrado de información en la BD se le advertirá al usuario mediante un *Toast.*
* comprar: Este método crea un *Dialog* en el que se le piden a los usuarios los datos de su tarjeta de crédito o débito para efectuar la transacción.
* aceptarCredito: Si después de introducir los datos de la tarjeta el usuario pulsa el botón "Comprar", se invoca este método para llamar a la clase DoHTTPRequest para eliminar los datos del carro.
* cancelarCredito: Si al introducir los datos de la tarjeta el usuario se arrepiente pude pulsar el botón "Cancelar", el cual, llama a este método que en realidad no tiene funcionalidad.

### **Fragments**

En esta aplicación se utilizan dos *Fragments* para mostrar el listado de los productos a la venta y para mostrar los detalles de un producto seleccionado por el usuario.

Se han utilizado *Fragmens* por su facilidad de uso y su adaptabilidad a la hora de girar la pantalla, ya que si el usuario cambia la orientación de la pantalla a *landscape* mientras se le muestra el listado de los productos, a la hora de seleccionar un producto los detalles de este se le mostraran en la mitad derecha de la pantalla. De esta manera, estando en una sola pantalla podrá ver el listado de productos disponibles, seleccionar alguno de ellos y mirar sus características sin tener que volver a la pantalla anterior.

He aquí los *Fragments* implementados:

#### **ProductoFragment**

En este *Fragment* se muestran los datos de un producto junto con un botón para que el usuario pueda añadir el producto a su carro de compra.

Métodos implementados en esta clase:

* addCarro: Método llamado al pulsar el botón "Añadir al carro". Llama a la clase que se conecta con el servidor para añadir los datos del producto que el usuario quiere comprar a su carro.
* onActivityCreated: En este método se inicializa el *Listener (interface)* que todo *Fragment* ha de implementar.
* actualizarFragment: Este método llama a la clase que se conecta a la BD para que se actualicen los datos del producto que se muestra por pantalla.
* processFinish: Esta función es llamada después de recibir los datos que se envían desde la base de datos del servidor. Si se han recibido los datos del producto, mete la información en los *TextView* correspondientes.
* imageLoadead: Con esta función se carga el *bitmap* de la imagen del producto después de recogerla del servidor.

#### **ListaProductosFragment**

Esta clase contiene el listado de los productos a la venta junto con un *Spinner* con el que se filtrarán los tipos de productos que aparecen en la lista. Por ahora solo hay seis productos y tres categorías, pero en el futuro se quieren añadir más tipos e incluso llegar a añadir desde móviles hasta electrodomésticos.

Métodos que implementa:

* verProducto: Con la posición del producto en la lista de productos se coge el *ID* del componente para cargarlo después en ProductosFragment.
* cambiarCategoria: Al seleccionar una categoría en el *Spinner,* se llama a este método para cargar los productos relacionados con la categoría seleccionada y así mostrarlos en la lista de productos a la venta.
* actualizarFragment: Al crear la actividad, este método llama a DoHTTPRequest para cargar desde la base de datos los elementos del *Spinner* y los productos de la lista de productos a la venta.

* processFinish: Después de recibir los datos de la BD este método es llamado para cargar la información recibida. Si la información recibida son los nombres de las diferentes categorías de productos, esa información se mete como *Items* del *Spinner*. Si son los nombres e *ID's* de productos a la venta, los mete en un *ArrayList* de productos para cargarlos en la lista de productos a la venta.

### **Dialogs**

En la aplicación actual solo se utilizan tres *Dialogs*. Uno para mostrar un error si el usuario introduce mal su usuario o contraseña en el *login*, otro *Dialog* para seleccionar la fecha de nacimiento en el registro y un último Dialog personalizado para introducir los datos de la tarjeta de crédito al realizar una compra.

Estas son las clases de los *Dialogs* implementados:

#### **ErrorLoginDialog**

Es una clase con un solo método en el que se crea la interfaz del *Dialog.* Se le asigna un título, un texto y un botón que no tiene funcionalidad alguna, simplemente se utiliza para cerrar el *Dialog*.

#### **CreditDialog**

Esta clase crea un *Dialog* con campos de texto para introducir la información de la tarjeta de crédito o débito con la que se pagará la compra a realizar. Los dos botones de este *Dialog* llaman a dos métodos de la *interface* implementada en CarroActivity.

#### **DateDialog**

Este *Dialog* muestra al usuario un calendario para que escoja su fecha de nacimiento en el registro. Consta de dos funciones. Una en la que se especifica el tipo de *Dialog* que es (*DatePickerDialog*) y otro que llama al método de la *interface* implementada en RegisterActivity para que meta la información de la fecha escogida en un *EditText.*

### **Adapters**

En este apartado se encuentran los *Adapters* que se han utilizado en las dos *ListViews* de la aplicación junto con la clase que se ha usado como modelo de un producto. Los *Adapters* se han utilizado para poder personalizar como se ven los productos en las listas de CarroActivity y ListaProductosFragment.

#### **CustomArrayProductosAdapter**

Esta clase que extiende de *BaseAdapter* contiene una lista de los productos que están en el carro de compra del usuario. Cada producto de esta lista solo consta del *ID*, el nombre y el precio precio.

Esta clase consta de los siguientes métodos:

* CustomArrayCarroAdapter: A esta constructora hay que pasarle el *Context* de la *Activity* que la llama junto con el *ArrayList* de productos mencionado anteriormente. Solo se encarga de inicializar las variables de la clase.

* getCount: Nos da información sobre el número de productos que hay en el carro del usuario.
* getItem: Este método devuelve un producto del *ArrayList* de productos dado su índice en el *Array.*
* getItemId: Devuelve el *ID* de un producto dado su índice en el *ArrayList*.
* getView: Este método asigna la vista que tendrá cada fila del *ListView* del carro y pondrá la información pertinente en los *TextViews* que la componen.

#### **CustomArrayProductosAdapter**

Está clase es el *Adapter* de la lista de los productos que aparecen en el menú principal. La clase que se ha explicado anteriormente tiene los mismos métodos que esta y tienen las mismas funciones como todo *Adapter* de una *ListView*. La única diferencia entre está clase y la anterior es que los productos del *ArrayList* que contiene solo están compuestos por el nombre del producto y su *ID*.

#### **Producto**

Es el modelo que se utiliza para guardar los datos de un producto. Esta clase solo se compone de variables publicas propias de un producto de la aplicación y tres constructoras que se utilizaran dependiendo de los datos que se necesite en cada momento.

### **Conectores al servidor**

Las clases de este apartado se encargan de conectar la aplicación con el servidor para recibir los datos que se necesiten en cada momento. DoHTTPRequest se encarga de enviar y recibir los datos necesarios en cada momento, mientras que la clase ImageGetter solo se encarga de buscar y descargar las imágenes que se necesiten en cada momento en la aplicación.

#### **ImageGetter**

Esta clase se encarga de descargar a la aplicación la imagen del producto que se pe pide. Se conecta de manera asíncrona al servidor, le pide la imagen que se encuentra en un *path* especifico, y el servidor le devuelve la imagen como un *Bitmap*.

En su constructor solo se inicializan las variables necesarias para hacer la petición al servidor. Después se ejecuta el método doInBackground, que como su nombre indica, descarga la imagen en *backgorund.* Para terminar se ejecuta la función onPostExecute, que llama al método de una *interface* en ProductoFragment pasando le el *Bitmap* que contiene la imagen.

#### **DoHTTPRequest**

Esta clase se encarga de las conexiones con el servidor para enviar y recibir datos de la BD. Las funciones de esta clase, en su gran mayoría, son para preparar datos específicos que se usarán en las *querys* ejecutadas por MYSQL en el servidor.

Los métodos, cuyo nombre empieza por "prepC", consisten en coger los parámetros que se les pasan y prepararlos para ser enviados mediante POST a una URL del del servidor. El método doInBackground se encarga de enviar los datos al fichero PHP del servidor para que después, este fichero PHP, devuelva la respuesta en formato JSON. Por último, la función onPostExecute, mediante la llamada a la función de la *interface* que está en esta misma clase, manda el JSON en un *String* a la clase que necesite los datos.

Los métodos onPreExecute, onCancelled y una parte del onPostExecute se está deliberando su supresión, ya que lo que hacen es poner una barra de carga mientras se hace la petición asíncrona al servidor. Debido a que la carga es de un periodo demasiado corto como para que la barra de carga aparezca en pantalla, se está planteando en quitarla.

## Software del servidor

El *software* del servidor solo se compone de dos ficheros en PHP. Estos ficheros se pueden encontrar en la carpeta app/server-src de la aplicación.

El fichero indexcompobuy.php se encarga de recibir la información que la aplicación envía. Para todas las conexiones realizadas por la aplicación se reciben los parámetros por POST, uno de los cuales se tiene el nombre "*func*", que es el que indica que es lo que se quiere hacer en el servidor. Por ejemplo, si el parámetro *func* es "*login*", el fichero indexcompobuy ejecutará el código relacionado con el *login* de un usuario. Cuando termina de ejecutar su código, este fichero convierte en un JSON la respuesta que se le envía desde connectioncompobuy.php, que en caso de dar error alguna ejecución en este último fichero, devuelve un JSON formado por un error ( { "error" : "error" } ).

El fichero connectioncompobuy.php contiene una clase con un atributo de conexión *PDO* de PHP. Con este atributo se crean todas las conexiones a la BD, y gracias a los métodos propios de la clase *PDO,* con unas pocas lineas de código fáciles de entender mirando un poco de documentación de PHP, se es capaz de devolver en cada método un *Array.* Ese *Array* tiene una estructura preparada para convertir a JSON con en método de PHP *json\_encode*.