scieee AI-readable full text Open interactive document viewer

Aplicación de contactos compartida

Milán Rodríguez, Alejandro

Abstract

El trabajo de fin de grado contendrá un proyecto basado en una aplicación que consultará las llamadas entrantes en la base de datos a través de un servicio web del servidor para reemplazar número desconocido por el nombre y los apellidos de la persona llamante. También contendrá un servicio para recibir notificaciones del administrador.

Full text

1 Equation Chapter 1 Section 1 Trabajo Fin de Grado Ingeniería de Telecomunicación Aplicación de contactos compartida Autor: Alejandro Milán Rodríguez Tutor: Jose Manuel Fornés Rumbao Dpto. Ingeniería Telemática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2018 Índice de Figuras 2 3 3 Aplicación de contactos compartida Trabajo Fin de Grado Ingeniería de Telecomunicación Aplicación de contactos compartida Autor: Alejandro Milán Rodríguez Tutor: Jose Manuel Fornés Rumbao Profesor titular Dep. de Telemática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2018 Índice de Figuras 4 5 5 Aplicación de contactos compartida Proyecto Fin de Carrera: Aplicación de contactos compartida Autor: Alejandro Milán Rodríguez Tutor: Jose Manuel Fornés Rumbao El tribunal nombrado para juzgar el Proyecto arriba indicado, compuesto por los siguientes miembros: Presidente: Vocales: Secretario: Acuerdan otorgarle la calificación de: Índice de Figuras 6 Sevilla, 2018 El Secretario del Tribunal 7 7 Aplicación de contactos compartida A mi familia A mis maestros Índice de Figuras 8 9 9 Aplicación de contactos compartida Resumen El trabajo de fin de grado contendrá un proyecto basado en una aplicación que consultará las llamadas entrantes en la base de datos a través de un servicio web del servidor para reemplazar número desconocido por el nombre y los apellidos de la persona llamante. También contendrá un servicio para recibir notificaciones del administrador. Índice de Figuras 16 Figura 5 Panel del administrador en el servidor 25 Figura 6 Aplicación móvil. Cliente correctamente registrado 26 Figura 7 Características servidor emulado 27 Figura 8 Versión mysql 28 Figura 9 Ilustración modelo vista controlador 29 Figura 10 Funcionamiento Firebase 30 Figura 11Proyecto Firebase 31 Figura 12 Panel de control Firebase web 31 Figura 13 Paso de mensajes cliente servidor FCM 32 Figura 14 Android Studio 33 Figura 15 Máquina virtual Android Studio 34 Figura 16 Características AVD 35 Figura 17 Características servidor VMware 12 Figura 18 Esquema base de datos. 13 Figura 19 Base de datos en el servidor 14 Figura 20 Tablas 14 Figura 21 Tabla admin 15 Figura 22 Tabla contactos 15 Figura 23 Tabla login 16 Figura 24 Tabla migration 16 Figura 25 Función migration 18 Figura 26 Funciones User.php 19 Figura 27 Función Index servidor 19 Figura 28 Servidor sin autenticar 20 Figura 29 Servidor pantalla autenticación 20 Figura 30 Función registrar token 1 21 Figura 31 Función registrar token 2 21 Figura 32 Función consultar llamadas 22 Figura 33 Petición get consultar llamada 22 Figura 34 Función sincronizar base de datos 23 Figura 35 Panel de control administrador 23 Figura 36 Función añadir contacto 1 24 Figura 37 Función añadir contacto 2 24 Figura 38 Añadir contacto nuevo 25 Figura 39 Funciñon añadir usuario aplicación móvil 26 Figura 40 Añadir usuario a base de datos 27 Figura 41 Consultar contactos 28 Figura 42 Función Firebase 1 29 17 17 Aplicación de contactos compartida Figura 43 Función Firebase 2 29 Figura 44 Panel de notitificación 30 Figura 45 Panel de notificación otras opciones 30 Figura 46 Panel de notitificación. Enviado 31 Figura 47 Permisos Android 32 Figura 48 Directorio archivo configuración 32 Figura 49 Contenido arhivo de configuración 33 Figura 50 Error archivo de configuración 34 Figura 51 Panel de usuario aplicación móvil 36 Figura 52 Registro de token desde el móvil 38 Figura 53 Opciones usuario aplicación móvil 39 Figura 54 Función devolver contactos 39 Figura 55 Lista contactos base de datos 40 Figura 56 Agenda móvil 42 Figura 57 Llamada entrante 43 Figura 58 Descolgar 44 Figura 59 Consultar en el servidor 45 Figura 60 Función añadir contacto 46 Figura 61 Función eliminar contacto 46 Figura 62 Contenido notificación Firebase 47 Figura 63 Firebase SplashActivity 48 Figura 64 Recibo de notificación desde el servidor 49 Figura 65 Apertura mensaje notificatorio desde servidor 50 Figura 66 Abrir url 51 Figura 67 Caso de uso usuario aplicación 52 Figura 68 Caso de uso administrador 53 Figura 69 Diagrama de mensaje autenticación 54 Figura 70 Diagrama de mensaje sincronización 55 Figura 71 Diagrama de mensaje envío de notificación 55 Figura 72 Características Linux Mint 58 Figura 73 Contacto correctamente registrado. 63 Índice de Figuras 18 19 19 Aplicación de contactos compartida BLOQUE 1. INTRODUCCION Y ALCANCE 1.1 Introducción e plantea un proyecto con el fin de simplificar y facilitar la conexión entre diferentes usuarios sin necesidad de la interacción física entre ellos. Estos usuarios pertenecerán a un departamento y debido a la incompatibilidad de horarios, de altas y bajas, y de contacto entre ellos, este proyecto nace para conseguir una comunicación más fácil. El objetivo final de este proyecto, es unificar los diferentes teléfonos de los contactos pertenecientes a un departamento determinado en una base de datos. Esta base de datos podrá ser luego consultada por la aplicación móvil cuando reciba una llamada entrante y conocer quien es el contacto origen (si es que existiese en la base de datos). De esta manera, se logra una accesibilidad mayor entre usuarios sin necesidad de la misma interacción entre ellos. A su vez, el administrador del sistema, podrá notificar a los diferentes usuarios registrados en la aplicación móvil con mensajes notificatorios como reuniones, noticias o imágenes desde su panel de control. Para abordar esta tarea, en este apartado analizaremos la situación actual, el estado de arte, los objetivos y el alcance de este proyecto. 1.2 Situación actual Como hemos explicado anteriormente, la situación actual es la existencia de numerosos departamentos y estos a su vez lleno de usuarios: de altas, bajas, y con horarios dispares entre ellos. Se quiere conseguir así un acercamiento entre ellos de tal manera que la comunicación sea más realizable. El usuario podrá contactar con otro de su mismo departamento sin necesidad de conocer previamente su teléfono. El administrador también quiere poder enviar a un usuario o a un conjunto de ellos información desde su panel de control, ubicado en el servidor, en forma de mensaje (al recibirlo en el destino el usuario recibirá además una notificación sonora) a fin de mantenerlos informados con noticias, hechos o reuniones. De esta forma se consigue una transmisión de información sin necesidad de estar en contacto personalmente con todos ellos o esperando que revisen el correo. 1.3 Objetivos El objetivo principal de este proyecto es lograr una aplicación que funcione como una “agenda global” entre usuarios sin mezclar con la personal. Con esta herramienta, si un usuario llama a otro, la aplicación consultará en la base de datos local el nombre del llamante y lo mostrará por pantalla sin necesidad de tenerlo añadido a la agenda de contactos (se prefiere evitar esta opción). Recordemos que en un departamento no todos estarán fijos y siempre habrá altas o bajas que considerar. Otro objetivo es recibir notificaciones enviadas desde el servidor por el administrador (mensajes, imágenes, S Bloque 1. Introduccion y alcance 20 enlaces) a partir de su panel en el servidor con previa autenticación. Esta herramienta será accedida sólo por profesores (excluyendo al administrador), por lo que será una herramienta cerrada, privada y securizalizada y que cumplirá una serie de requisitos de seguridad (pantalla de autenticación, comprobación de existencia en la base de datos…) para poder ser lanzada. 1.4 Alcance Este proyecto va a ser divido en 7 bloques, donde se realizará:  Una introducción al mismo y definición de su alcance, así como los objetivos a cumplir y el estado del arte, en este primer bloque.  En el segundo bloque, se realizará un estudio de la situación actual, desde el escenario donde se desea implementar el uso de la herramienta hasta las herramientas que se utilizarán.  Un tercer bloque, donde se detallará la información acerca del desarrollo y se añadirán diagramas para explicar su funcionamiento.  Un cuarto bloque donde se expondrá una línea futura y las conclusiones.  Un quinto bloque donde se detallará un pliego de condiciones que deberá cumplir el escenario donde se implemente el proyecto.  Finalizaremos con dos bloques, a saber un sexto bloque, en el que incluiremos la bibliografía; y un séptimo y último bloque destinado a los diferentes anexos, donde se incluirán desde el código fuente completo de la herramienta, hasta diferentes manuales o páginas de interés relacionadas con el mismo. 1.5 Estado del arte Actualmente, existen multitud de aplicaciones móviles para compartir contactos entre usuarios (las conocidas whassap o telegram) o consultar llamadas de desconocidos (trapcall, truecaller, whoscall). Sin embargo, se necesita conocer antes el teléfono destino. Para el envío y recepción de mensajes, entre las mencionadas arriba, también encontramos firebase cloud messaging, un servicio de google que se puede implementar en proyectos de manera no muy complicada. Esta herramienta permite enviar mensaje a los usuarios desde un servidor web o una aplicación móvil, por ejemplo. La aplicación móvil estará diseñada en Android Studio al igual que muchas aplicaciones que se crean diaramente. Como el objetivo final es para móviles Android, es una de las mejores herramientas con la que codificar nuestro código. Para la recepción de mensajes usaremos firebase cloud messaging de google. Una herramienta fácil de implementar y pensada para el envio y recepción de mensajes entre otras utilidades. 21 21 Aplicación de contactos compartida Figura 1 Ejemplo FCM La gestión del servidor estará basada en php. Para ello se usará apache y para el código se usará Yii [1]. Yii es un framework basado en php pensado para trabajar con base de datos. Las operaciones CRUD (Create, Read, Update, Delete) son así mas fáciles de gestionar. El servidor, además, contendrá lenguaje curl para el envío de notificaciones. Figura 2 Funcionamiento de Yii La base de datos, entre las diferentes opciones existentes (sqlite, mariadb, amazon relational database service…) estará diseñada en myqsl para una mejor implementación con la aplicación móvil y el servidor. Bloque 1. Introduccion y alcance 22 23 BLOQUE 2. ESCENARIO Y SOFTWARE En este bloque se expondrá el escenario que se quiere realizar, así como el software utilizado para el desarrollo de las diferentes herramientas que lo componen. Se detallará de esta forma el por qué de la elección o decisión de tales herramientas para el desarrollo de este proyecto. 2.1 Escenario Figura 3 Escenario El escenario como se puede observar será un servidor con varios servicios webs que consultará en la base de datos y responderá a las peticiones realizadas por los clientes desde su aplicación. Absolutamente todas las peticiones realizadas por el móvil pasarán por el servidor y usarán sus servicios para obtener respuesta alguna. Para ello el usuario deberá de autenticarse y se comprobará que el usuario esté dado de alta y tiene permisos para poder realizar ciertas acciones. 2.1.1 Servidor A primera instancia se necesitará un servidor donde se tendrá:  Base de datos: contendrá varias tablas: 1. Tabla contactos: Nombre, apellidos, teléfono y token asignado al teléfono de los diferentes contactos. 2. Tabla login: formada por usuario, contraseña para poder acceder a la aplicación móvil. 3. Tabla admin: formada por la cuenta del administrador (usuario, contraseña) para gestionar tanto el servicio web como la base de datos. Bloque 2. Escenario y software 24 Figura 4 Esquema básico tablas  Servidor web: basado en yii, lenguaje basado en php y optimizado para base de datos. Ejecutará el servicio web que permitirá: 1. Consultar teléfonos a través de la aplicación móvil. 2. Administración de usuarios: 2.1 Agregar contactos. 2.2 Dar de alta usuarios para la aplicación móvil. 2.3 Consultar datos de todos los contactos. 2.4 Enviar notificaciones a los usuarios. 3. Sincronizar la base de datos. 4. Autenticar al usuario en el móvil. 5. Registrar el token del móvil. 6. Gestionar la autenticación del administrador del sistema. 25 25 Aplicación de contactos compartida Figura 5 Panel del administrador en el servidor 2.1.2 Cliente El cliente de este proyecto solo se hará a nivel de aplicación móvil (Android). Este cliente tendrá una pantalla de autenticación donde podrá:  Registrar el token de su teléfono en la base de datos  Sincronizar la base de datos local con la remota  Consultar la base de datos Cuando reciba una llamada entrante se consultará la base de datos para consultar el llamante y se mostrará por pantalla en vez de número desconocido. Tendrá integrado un servicio para recibir notificaciones y se mostrarán detalladamente. Bloque 2. Escenario y software 32 Figura 13 Paso de mensajes cliente servidor FCM 2.2.4 Aplicación móvil Para la aplicación móvil se desarrollará en Android Studio [8]. Android Studio es un entorno integrado oficial para Android. Entre las principales caracteristicas encontramos: • Renderizado en tiempo real • Consola de desarrollo • Herramienta Lint para detectar problemas de rendimiento, usabilidad, compatiblidad de versiones y otros problemas. • Dispositivo virtual de Android para ejecutar y probar aplicaciones. 33 33 Aplicación de contactos compartida Figura 14 Android Studio Bloque 2. Escenario y software 34 Figura 15 Máquina virtual Android Studio 35 35 Aplicación de contactos compartida Figura 16 Características AVD Resta decir que la aplicación siempre se desarrollará en la ultima plataforma existente y siempre actualizada. Bloque 2. Escenario y software 12 11 BLOQUE 3. DESARROLLO n este capítulo se describirá y detallará el diseño de los diferentes componentes del proyecto. Para ello, se acompañarán las descripciones con diagramas, casos de usos y algún gráfico para facilitar su explicación. El ecosistema de trabajo será en una máquina virtual de WMware donde se pondrá en el siguiente apartado sus características, así como la de la del sistema móvil simulado por Android Studio. 3.1 VMware La máquina virtual que simulará el servidor, será como se ha nombrado anteriormente, un escenario de simulación que intentará amoldarse al escenario real. E Bloque 3. Desarrollo 12 12 Figura 17 Características servidor VMware Se comprobarán diferentes configuraciones, de núcleos de procesador y memoria RAM, entre las cuales se apreciará:  Memoriam RAM: Se variará en rangos desde 512mb a 2048mb. Se ha observado que para el uso del servicio web desde la aplicación móvil con 512 mb son suficientes. Sin embargo, si se quiere acceder al panel de control del adminitrador vía navegador, se recomienda subir la memoria RAM hasta 1024 mb. Esto es porque el navegador puede consumir recursos de más y esta configuración evita la ralentizaciones con el sistema.  Núcleos del procesador: en cuanto a los núcleos tampoco ha hecho falta probar muchas configuraciones. Se puede variar entre 1 o 2 núcleos pero se recomienda este último en la configuración.  Disco duro: se ha dejado por defecto la configuración de 20 gb recomendada por la máquina virtual. 13 13 Aplicación de contactos compartida 3.2 Base de datos La base de datos se diseñará en mysql como se ha explicado anteriormente, por facilidades a la hora de implementarlo tanto en el servidor [9] [10] como en la aplicación móvil. La base de datos tendrá de nombre “Agenda” y contendrá 3 tablas (una por cada gestión): [11]  Contactos: que tendrá los campos Nombre (String (20)), Apellidos (String (20)), Teléfono (String (9)) y Token (String).  Login: estará formada por user (String (20)) y passwd (String (20)) la cuál debera ser de mínimo 6 caracteres y será cifrada con md5 por lo que su valor real no será mostrado.  Admin: formada por por username (String (20)) y password (String (20)). Ya que el administrador es el único que tendrá acceso y Yii, esta contraseña no estará cifrada. El diseño que se realizará se detalla a continuación con una imagen. Estará creada con el software DBDesigner 4 [12] de la asignatura Base de datos. Esta aplicación nos dará una vez diseñado, los scripts para crear, optimizar y eliminar las diferentes tablas, que se detallarán en los anexos. Figura 18 Esquema base de datos. Y su implementación en el servidor. Bloque 3. Desarrollo 14 14 Figura 19 Base de datos en el servidor Figura 20 Tablas 15 15 Aplicación de contactos compartida Figura 21 Tabla admin Figura 22 Tabla contactos Bloque 3. Desarrollo 22 22 La petición se realizará con el método POST. Figura 32 Función consultar llamadas Se buscará mediante una petición sql a la table correspondiente, si coincide el número con algun contacto, y de ser así, devolverá el nombre y los apellidos. Para ello se utilizará el controlador ConsultaController.php. Figura 33 Petición get consultar llamada 3.3.4 Sincronizar la base de datos local con la del móvil El servidor devolverá nombre, apellidos, y teléfono de cada uno de los contactos de la base de datos local. Para ello el servidor recibirá un token que comprobará de su existencia y si así fuera responderá la petición. El mensaje de respuesta se comprondrá con una respuesta de correcto o incorrecto y si fuera correcto los campos anteriormente mencionados. Este trabajo lo realizará el controlador SincronizarController.php. Separará el mensaje de respuesta (nombre, apellidos, teléfono, salto de línea) de OK o KO en otra línea. 23 23 Aplicación de contactos compartida Figura 34 Función sincronizar base de datos 3.4 Panel de control del administrador El panel de control o vista que mostrará Yii una vez la autenticación sea correcta será el siguiente, la vista index.php Esta vista contará con 4 botones que harán referencia a un servicio diferente cada uno y evitará tener que acceder de forma manual. Figura 35 Panel de control administrador Bloque 3. Desarrollo 24 24 3.4.1 Añadir un contacto Añadir un contacto permitirá al administrador completando los campos correspondientes y cumpliendo los requisitos, añadir un nuevo contacto completo a la base de datos. Para ello AgendaController.php devolverá el modelo Agenda.php y renderizará la vista correspondiente del formulario. Este modelo comprobará que se cumple los requisitos anteriormente mencionados. Figura 36 Función añadir contacto 1 Figura 37 Función añadir contacto 2 25 25 Aplicación de contactos compartida Figura 38 Añadir contacto nuevo Se comprobará que los campos no estarán vacios y además que el teléfono contendrá 9 dígitos. 3.4.2 Dar de alta a un usuario Esta función permitirá al administrador añadir un usuario nuevo a la tabla Login. Recordaremos que esa tabla corresponderá con la autenticación desde la aplicación móvil. El controlador que nos facilitará la vista de este formulario será LoginController.php. [13] Recordemos que el controlador no devolverá ninguna vista si el usuario no se ha autenticado antes en la tabla de admin. Se comprobará una serie de requisitos para introducirlo como que no estarán en blanco o que la longitud de la contraseña será mayor de 6 caracteres. Se hará una conexión con la base de datos si los datos no contienen errores, y se almacenarán, evitando al administrador tener que añadir los usuarios a través del programa mysql. La contraseña se codificará usando la función md5 que contiene php. Bloque 3. Desarrollo 26 26 Figura 39 Funciñon añadir usuario aplicación móvil 27 27 Aplicación de contactos compartida Figura 40 Añadir usuario a base de datos 3.4.3 Consultar usuarios El administrador podrá consultar los usuarios de la tabla Contactos vía web sin necesidad de acceder mediante mysql. Para ello el controlador AgendaController.php renderizará su propia vista index.php. Desde ahí el adminsitrador podrá modificar, visualizar, editar los diferentes contactos o añadir contactos nuevos a la base de datos. Bloque 3. Desarrollo 28 28 Figura 41 Consultar contactos 3.4.4 Enviar notificaciones Para el uso de esta función, se necesitará tener instalado en el servidor curl. Curl es una biblioteca y un interprete de comandos orientado a la transferencia de archivos. Desde este panel, el administrador podrá enviar notificaciones en forma de mensajes Json que el usuario recibirá en su aplicación. Para ello hará uso de Notifications.php para formar la clase. [14] [15] Se deberá completar los campos token, titulo y mensaje. El token corresponderá al número de teléfono enlazado al que se querrá enviar. Habrá campos opcionales también como incluir una imagen o incluir una acción. La acción a realizar será añadir una url que se podrá abrir desde el cliente móvil. La imagen reemplazará a la imagen por defecto de la aplicación. La respuesta del servidor de Firebase se recogerá y mostrará por pantalla, así como el mensaje Json creado. 29 29 Aplicación de contactos compartida Figura 42 Función Firebase 1 Figura 43 Función Firebase 2 Bloque 3. Desarrollo 30 30 Figura 44 Panel de notitificación Figura 45 Panel de notificación otras opciones 31 31 Aplicación de contactos compartida Figura 46 Panel de notitificación. Enviado En este ejemplo, la respuesta ha sido failure puesto que ese token no corresponde a nadie de la base de datos. En la carpeta /views/firebase/server.php habrá que configurar el usuario y contraseña de root y el nombre de la base de datos. 3.5 Aplicación móvil La aplicación móvil contará con una pantalla de autenticación en el MainActivity que el usuario rellenerá con sus credenciales [16] [17] [18]. Si la autenticación con el servidor es correcta, se pasará a la actividad User donde se mostrará una pantalla que permite registrar el token del teléfono en el servidor, sincronizar y consultar la base de datos local. Contendrá dos servicios que correrán en segundo plano:  Un servicio para las llamadas entrantes. Este servicio buscará en la base de datos local y si no encuentra nada, en la remota.  Un servicio para la recepción de mensajes. Al pulsar en ella, llevará a una actividad nueva Splash que mostrará el contenido del mensaje. La aplicación necesitará de los siguientes permisos.  Acceso a la red/Internet: para poder realizar la conexion con el servidor y sincronizar los datos.  Leer estado del teléfono/Procesar llamadas: correspondiente al servicio PhoneStateReceiver para conocer cuando se reciberá una llamada entrante y sus datos. [19] [20]  Leer / Escribir en la memoria externa: se leerá el fichero de configuración de la IP del servidor. Bloque 3. Desarrollo 38 38 Figura 52 Registro de token desde el móvil 39 39 Aplicación de contactos compartida Esto permitirá al usuario utilizar todas las funciones y servicios posibles de la aplicación. Si por un casual el usuario no encontrara su teléfono registrado en la base de datos, se le devolverá un mensaje de error. El token de registro podrá cambiar en las siguientes situaciones:  La app borra un ID de instancia.  La app se restablece en un dispositivo nuevo.  El usuario desinstala y vuelve a instalar la app.  El usuario borra los datos de la app. Cuando se necesite recuperar el token actual, se llamará a FirebaseInstanceId.getInstance().getToken(). Este método muestra el valor null si el token aún no se genera. Una vez registrado el token correspondiente al teléfono móvil, el usuario podrá sincronizar manualmente la base de datos. Para ello basta con pulsar al botón “Sincronizar BBDD” que hará una sincronización con los datos del servidor. Figura 53 Opciones usuario aplicación móvil Al pulsar el botón “Consultar base de datos” el usuario abrirá otra actividad, ContactosActivity.class donde podrá consultar la base de datos que ha descargado y que tiene como local. Esta actividad no contendrá ninguna función. Figura 54 Función devolver contactos Bloque 3. Desarrollo 40 40 Figura 55 Lista contactos base de datos Hasta aquí las interacciones que podrá tener el usuario directamente con la aplicación. Ahora explicaremos los servicios que se desarrollarán. 41 41 Aplicación de contactos compartida 3.5.1 Servicio de búsqueda de número de teléfono Este servicio responderá cuando el usuario reciba una llamada entrante (state.equals(TelephonyManager.EXTRA_STATE_RINGING)). El servicio se encargará de buscar ese número desconocido en la base de datos local, y, si obtiene respuesta, sustituirá el teléfono en pantalla por el nombre. Para ello, usaremos el servicio PhoneStateReciver.java que usará la clase BroadcastReceiver. Utilizará las siguientes funciones:  read_from_sd: función encargada que leerá al iniciar la actividad el archivo config ubicado en storage/sdcard/Download/. Tendrá que leer la línea que compone el fichero que contiene la dirección IP del servidor.  SendNumbertoServer: función que será llamada en el caso que no se encuentre en la base de datos local el teléfono de la llamada entrante. Se encargará de realizar una petición POST al servidor enviando el número de teléfono entrante mediante una petición Volley, esperará la respuesta y añadirá el contacto activando una bandera si lo encuentra. Posteriormente, eliminará el contacto si la bandera se ha activado. Pondrá en cola la petición realizada.  addContact: recibirá un nombre y un teléfono y lo añadirá a la agenda local del móvil mediante un OperationList.  deleteContact: recibirá un nombre y un teléfono y lo borrará de la agenda local del móvil. Es necesario que esta petición se realice justo después de añadir el contacto, porque al salir de la función la variable nombre perderá su valor. Se recorrerá mediante un cursor la agenda personal buscando los valores y posteriormente eliminándolo. Bloque 3. Desarrollo 42 42 Figura 56 Agenda móvil 43 43 Aplicación de contactos compartida Figura 57 Llamada entrante Bloque 3. Desarrollo 44 44 Figura 58 Descolgar Si por casualidad, el teléfono no se encontrase en la base de datos local, el servicio buscará en el servidor, a ver si obtiene alguna respuesta. 45 45 Aplicación de contactos compartida Figura 59 Consultar en el servidor Bloque 3. Desarrollo 46 46 Para ello se realizará todo en una petición volley y con el método POST. Se enviará el número a consultar y se esperará una respuesta inmediata del nombre. Si no se encontrase ningún nombre relacionado con el teléfono asociado, no se mostrará nada por pantalla. Para mostrar los nombres por pantalla, Android buscará en la agenda de contactos el nombre, ya que la variable DISPLAY_NAME de una llamada es solo de lectura. Para poder mostrar el nombre de la respuesta habrá que usar dos funciones. Una que añadirá el usuario a la agenda de contactos y otra que la eliminará. El motivo principal por el que no se guardará el contacto es porque no se permite tocar la información del usuario. Si así fuera el usuario tendria sus contactos mezclados con los de la aplicación y al final será todo muy engorroso. Para ello, se añadirá el contacto y se eliminará, dando el tiempo justo a Android para buscarlo. Figura 60 Función añadir contacto Figura 61 Función eliminar contacto 47 47 Aplicación de contactos compartida 3.5.2 Servicio de notificaciones de Firebase Cloud Messasing Este servicio se implementará con el objetivo de que el usuario reciba los mensajes enviados por el servidor. Se hará uso de la clase MyFirebaseMessagingService.class que utiliza FirebaseMessagingService. [21] [22] [23] [24] Esta clase contiene varias funciones reseñables:  onMessageReceived: esta función recibirá un RemoteMessage y lo desglozará internamente en Logs. Recibirá un JsonObject y lo convertirá a String y se lo pasará a sendPushNotification.  sendPushNotification: recibirá un JSONObject y un RemoteMessage. Se encargará de realizar la notificación al sistema. Esta función dividirá el mensaje en varias partes:  Título  Cuerpo  ImagenUrl  Url Cogerá si existe campo ImageUrl y la convertirá a un Bitmap. Iniciará un nuevo Intent para poder mostrarlo todo en SplashActivity.class. Para ello hará uso de PendingIntent.Creará un NotificationCompact.Builder para añadirle los diferentes campos a la notificación. Figura 62 Contenido notificación Firebase  getBitmapfromUrl: esta función se encargará de a partir de una url, de obtener la imagen y la convertirá en bitmap para posteriormente devolverla. Para entrar en la actividad SplashActivty.class se necesitará recibir una notificación. Sin ella será imposible acceder. La pantalla por defecto será la siguiente. Bloque 3. Desarrollo 54 54 Figura 69 Diagrama de mensaje autenticación 55 55 Aplicación de contactos compartida Figura 70 Diagrama de mensaje sincronización Figura 71 Diagrama de mensaje envío de notificación Bloque 3. Desarrollo 56 56 57 57 Aplicación de contactos compartida BLOQUE 4. PLIEGO DE NECESIDADES En este bloque se abarcará todos los requisitos necesarios a la hora de implementar este proyecto en otro destino que no sea aquel donde se ha desarrollado originalmente y al cual está adaptado. Para ello se diferenceriará las tres herramientas que lo componen y se recapitularán sus requisitos. Recordar que el sistema original en el que se desarrollará será en una máquina virtual en VMware, en un sistema Linux por lo que se el ecosistema deberá ser similar para un correcto funcionamiento. Las características de esta máquina virtual son:  En este proyecto ha sido Linux Mint 19 versión x64 bits.  La máquina virtual ha tenido dos núcleos del procesador dedicado.  2048 gb de ram y 20 gb de disco duro.  Conectividad en puente con la máquina host. 4.1 Base de datos Para la base de datos se necesitará tener instalado mysql. Por defecto debería debir instalado en la imagen de Linux Mint 19. Si no estuviera disponible se adjuntará la versión utilizada durante el desarrollo. Bloque 4. Pliego de necesidades 58 58 Figura 72 Características Linux Mint Además, hará falta crear una base de datos de nombre: “Agenda” cuyas tablas sean: -Contactos. -Login. -Admin. -Migration. Esta última tabla es la que utilizará Yii para la concordancia con el servidor y que puede inyectar en la base de datos.  Script para crear las tablas: CREATE TABLE admin ( idadmin INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, username VARCHAR(20) NOT NULL, password VARCHAR(20) NOT NULL, authKey VARCHAR(50) NULL, PRIMARY KEY(idadmin) ); CREATE TABLE contacto ( idUsuario INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, 59 59 Aplicación de contactos compartida nombre VARCHAR(20) NOT NULL, apellidos VARCHAR(45) NOT NULL, telefono VARCHAR(9) NOT NULL, token VARCHAR(50) NULL, PRIMARY KEY(idUsuario) ); CREATE TABLE login ( idlogin INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, user VARCHAR(20) NULL, passwd VARCHAR(20) NULL, PRIMARY KEY(idlogin) );  Script para eliminar las tablas: DROP TABLE login; DROP TABLE contacto; DROP TABLE admin;  Script para optimizar las tablas: DROP TABLE login; DROP TABLE contacto; DROP TABLE admin;  Script para reparar las tablas: Bloque 4. Pliego de necesidades 60 60 OPTIMIZE TABLE admin; OPTIMIZE TABLE contacto; OPTIMIZE TABLE login; 4.2 Servidor Web Para el servidor web (Yii) hará falta una serie de configuraciones y adaptaciones que enumeramos a continuación:  Instalación y configuración del servidor apache para exportar la carpeta.  Instalación de curl para el funcionamiento del servicio de notificaciones firebase.  Modificación de los ficheros siguientes ficheros :  Config/db.php y config/db2.php donde deberá ponerse en la siguiente línea el nombre de la base de datos, el usuario y contraseña de root. 'dsn' => 'mysql:host=localhost;dbname=’, 'username' => 'root', 'password' => '',  Config/web.php: una key válida para Yii (aleatoria) para poder ser iniciado. *'cookieValidationKey' => 'asdsadsadsadsaa',  En migrations/ estará la estructura de la tabla principal de contacto. Si quisiera cambiarse alguno de sus valores habría que editarlo aquí y volver a realizar la migración. public function up() { $this->createTable('contacto', [ 'idUsuario' => $this->primaryKey(), 61 61 Aplicación de contactos compartida 'nombre' => $this->string()->notNull(), 'apellido' => $this->string()->notNull(), 'telefono' => $this->string()->notNull(), 'token' => $this->string() ]); }  Views/usuarios/server.php : se deberá cambiar la parte de conexión con la base de datos. $db = mysqli_connect('localhost', 'root', ‘ ’, 'agenda'); Permisos: drwxrwxrwx 2 alejandro alejandro 4096 jun 5 2017 assets drwxr-xr-x 2 alejandro alejandro 4096 sep 4 02:22 backend -rwxrwxrwx 1 alejandro alejandro 800 jun 5 2017 codeception.yml drwxrwxrwx 2 alejandro alejandro 4096 sep 1 14:21 commands drwxr-xr-x 2 alejandro alejandro 4096 ago 12 13:16 components -rwxrwxrwx 1 alejandro alejandro 1782 jun 5 2017 composer.json -rwxrwxrwx 1 alejandro alejandro 109291 jun 5 2017 composer.lock -rwxr-xr-x 1 alejandro alejandro 1875611 ago 29 11:51 composer.phar -rw-r--r-- 1 alejandro alejandro 305459 ago 29 11:50 composer-setup.php drwxrwxrwx 2 alejandro alejandro 4096 ago 1 11:42 config drwxrwxrwx 2 alejandro alejandro 4096 sep 4 05:16 controllers -rwxrwxrwx 1 alejandro alejandro 1622 jun 5 2017 LICENSE.md drwxrwxrwx 3 alejandro alejandro 4096 jun 5 2017 mail drwxrwxrwx 2 alejandro alejandro 4096 feb 23 2018 migrations drwxrwxrwx 2 alejandro alejandro 4096 sep 1 14:38 models -rwxrwxrwx 1 alejandro alejandro 6579 jun 5 2017 README.md -rwxrwxrwx 1 alejandro alejandro 5141 jun 5 2017 requirements.php drwxrwxrwx 6 alejandro alejandro 4096 jul 28 2017 runtime drwxrwxrwx 9 alejandro alejandro 4096 jun 5 2017 tests drwxrwxrwx 23 alejandro alejandro 4096 jun 5 2017 vendor drwxrwxrwx 7 alejandro alejandro 4096 sep 1 12:47 views drwxrwxrwx 4 alejandro alejandro 4096 jun 5 2017 web -rwxrwxrwx 1 alejandro alejandro 556 jun 5 2017 yii Bloque 4. Pliego de necesidades 62 62 -rwxrwxrwx 1 alejandro alejandro 515 jun 5 2017 yii.bat Config -rwxrwxrwx 1 alejandro alejandro 990 jun 5 2017 console.php -rwxrwxrwx 1 alejandro alejandro 188 ago 7 2017 db2.php -rwxrwxrwx 1 alejandro alejandro 188 ago 7 2017 db.php -rwxrwxrwx 1 alejandro alejandro 60 jun 5 2017 params.php -rwxrwxrwx 1 alejandro alejandro 199 jun 5 2017 test_db.php -rwxrwxrwx 1 alejandro alejandro 1001 jun 5 2017 test.php -rwxrwxrwx 1 alejandro alejandro 2531 ago 1 11:42 web.php Controllers -rwxrwxrwx 1 alejandro alejandro 3149 feb 23 2018 AgendaController.php -rwxrwxrwx 1 alejandro alejandro 1740 sep 4 03:32 ConsultaController.php -rw-r--r-- 1 alejandro alejandro 700 sep 1 14:27 FirebaseController.php -rwxrwxrwx 1 alejandro alejandro 1776 sep 1 14:29 LoginController.php -rwxrwxrwx 1 alejandro alejandro 2015 sep 1 14:37 SincronizarController.php -rwxrwxrwx 1 alejandro alejandro 3030 sep 1 14:33 SiteController.php -rwxrwxrwx 1 alejandro alejandro 1760 sep 4 05:16 TokenController.php -rw-r--r-- 1 alejandro alejandro 588 sep 1 14:36 UsuariosController.php Migrations -rw-r--r-- 1 alejandro alejandro 763 feb 23 2018 m170807_112948_create_contacto_table.php Views drwxrwxrwx 2 www-data www-data 4096 sep 1 14:43 agenda drwxr-xr-x 2 alejandro alejandro 4096 sep 4 04:05 firebase drwxrwxrwx 2 alejandro alejandro 4096 sep 1 15:05 layouts drwxrwxrwx 2 alejandro alejandro 4096 sep 1 15:09 site drwxr-xr-x 2 alejandro alejandro 4096 sep 4 06:37 usuarios 63 63 Aplicación de contactos compartida 4.3 Aplicación móvil Para la aplicación móvil el usuario deberá descargarse un fichero “config” sin extensión y que deberá situar en la carpeta por defecto de las descargas: /storage/sdcard/Downloads. Dicho esto, el usuario ya tendrá acceso a la aplicación móvil si se ha dado de alta en la base de datos, tanto el usuario de autenticación como sus datos. Una vez hecho esto, el usuario sólo deberá registrar el token correspondido a su teléfono móvil para poder utilizar los servicios del servidor web. Figura 73 Contacto correctamente registrado. 70 70 71 71 Aplicación de contactos compartida BLOQUE 7. ANEXOS Por último, se añadirán todos los anexos correspondientes a este proyecto así como el código programado para ello. 7.1 Herramientas 7.1.1 Base de datos Create.sql CREATE TABLE admin ( idadmin INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, username VARCHAR(20) NOT NULL, password VARCHAR(20) NOT NULL, authKey VARCHAR(50) NULL, PRIMARY KEY(idadmin) ); CREATE TABLE contacto ( idUsuario INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, nombre VARCHAR(20) NOT NULL, apellidos VARCHAR(45) NOT NULL, telefono VARCHAR(9) NOT NULL, token VARCHAR(50) NULL, PRIMARY KEY(idUsuario) ); CREATE TABLE login ( idlogin INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, user VARCHAR(20) NULL, passwd VARCHAR(20) NULL, PRIMARY KEY(idlogin) ); Bloque 7. Anexos 72 72 Drop.sql DROP TABLE login; DROP TABLE contacto; DROP TABLE admin; Repair.sql REPAIR TABLE admin; REPAIR TABLE contacto; REPAIR TABLE login; Optimize.sql OPTIMIZE TABLE admin; OPTIMIZE TABLE contacto; OPTIMIZE TABLE login; 7.1.2 Servidor Web Para poder hacer funcionar el servidor primero habrá que realizar los siguientes comandos. sudo apt-get install php-curl sudo apt-get install mysql-server libapache2-mod-auth-mysql php5-mysql sudo apt-get install php5 libapache2-mod-php5 php5-mcrypt sudo service apache2 restart Y desde la carpeta de Yii: ./yii migrate/create create_agenda_table 73 73 Aplicación de contactos compartida  Directorio config Console.php <?php $params = require(__DIR__ . '/params.php'); $db = require(__DIR__ . '/db.php'); $config = [ 'id' => 'basic-console', 'basePath' => dirname(__DIR__), 'bootstrap' => ['log'], 'controllerNamespace' => 'app\commands', 'components' => [ 'cache' => [ 'class' => 'yii\caching\FileCache', ], 'log' => [ 'targets' => [ [ 'class' => 'yii\log\FileTarget', 'levels' => ['error', 'warning'], ], ], ], 'db' => $db, ], 'params' => $params, /* 'controllerMap' => [ 'fixture' => [ // Fixture generation command line. 'class' => 'yii\faker\FixtureController', ], Bloque 7. Anexos 74 74 ], */ ]; if (YII_ENV_DEV) { // configuration adjustments for 'dev' environment $config['bootstrap'][] = 'gii'; $config['modules']['gii'] = [ 'class' => 'yii\gii\Module', ]; } return $config; db.php <?php return [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=agenda', 'username' => 'root', 'password' => 'alemilrod', 'charset' => 'utf8', ]; db2.php <?php return [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=agenda', 'username' => 'root', 'password' => 'alemilrod', 'charset' => 'utf8', ]; params.php <?php 75 75 Aplicación de contactos compartida return [ 'adminEmail' => '[email protected]', ]; test.php <?php $params = require(__DIR__ . '/params.php'); $db = require(__DIR__ . '/test_db.php'); /** * Application configuration shared by all test types */ return [ 'id' => 'basic-tests', 'basePath' => dirname(__DIR__), 'language' => 'en-US', 'components' => [ 'db' => $db, 'mailer' => [ 'useFileTransport' => true, ], 'assetManager' => [ 'basePath' => __DIR__ . '/../web/assets', ], 'urlManager' => [ 'showScriptName' => true, ], 'user' => [ 'identityClass' => 'app\models\User', ], 'request' => [ 'cookieValidationKey' => 'test', 'enableCsrfValidation' => false, // but if you absolutely need it set cookie domain to localhost /* 'csrfCookie' => [ Bloque 7. Anexos 76 76 'domain' => 'localhost', ], */ ], ], 'params' => $params, ]; test_db.php <?php $db = require(__DIR__ . '/db.php'); // test database! Important not to run tests on production or development databases $db['dsn'] = 'mysql:host=localhost;dbname=yii2_basic_tests'; return $db; web.php <?php $params = require(__DIR__ . '/params.php'); $db = require(__DIR__ . '/db.php'); $config = [ 'id' => 'basic', 'basePath' => dirname(__DIR__), 'bootstrap' => ['log'], 'components' => [ 'request' => [ // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation 'cookieValidationKey' => 'asdsadsadsadsaa', ], 'cache' => [ 'class' => 'yii\caching\FileCache', ], 'user' => [ 'identityClass' => 'app\models\BackendUser', // backenduser es nuestra nueva clase que implementara los metodos de la nueva base de datos (admin) 'enableAutoLogin' => true, 'enableSession' => true, 77 77 Aplicación de contactos compartida ], 'errorHandler' => [ 'errorAction' => 'site/error', ], 'urlManager' => [ //es necesario para la barra de navegacion tenga una estructura mas limpia 'class' => "yii\web\UrlManager", 'showScriptName' => true, 'enablePrettyUrl' => true, ], 'mailer' => [ 'class' => 'yii\swiftmailer\Mailer', // send all mails to a file by default. You have to set // 'useFileTransport' to false and configure a transport // for the mailer to send real emails. 'useFileTransport' => true, ], 'log' => [ 'traceLevel' => YII_DEBUG ? 3 : 0, 'targets' => [ [ 'class' => 'yii\log\FileTarget', 'levels' => ['error', 'warning'], ], ], ], 'db' => $db, //db=bbdd para agenda /* 'urlManager' => [ 'enablePrettyUrl' => false, 'showScriptName' => true, 'rules' => [ ], ],*/ ], 'params' => $params, ]; Bloque 7. Anexos 78 78 if (YII_ENV_DEV) { // configuration adjustments for 'dev' environment $config['bootstrap'][] = 'debug'; $config['modules']['debug'] = [ 'class' => 'yii\debug\Module', // uncomment the following to add your IP if you are not connecting from localhost. //'allowedIPs' => ['127.0.0.1', '::1'], ]; $config['bootstrap'][] = 'gii'; $config['modules']['gii'] = [ 'class' => 'yii\gii\Module', // uncomment the following to add your IP if you are not connecting from localhost. //'allowedIPs' => ['127.0.0.1', '::1'], ]; } return $config;  Directorio Controllers AgendaController.php <?php namespace app\controllers; use Yii; use app\models\Agenda; use app\models\AgendaSearch; use yii\web\Controller; use yii\web\NotFoundHttpException; use yii\filters\VerbFilter; /** * AgendaController implements the CRUD actions for Agenda model. 79 79 Aplicación de contactos compartida */ class AgendaController extends Controller //generado por gii { /** * @inheritdoc */ public function behaviors() { return [ 'verbs' => [ 'class' => VerbFilter::className(), 'actions' => [ 'delete' => ['POST'], ], ], ]; } /** * Lists all Agenda models. * @return mixed */ public function actionIndex() { $searchModel = new AgendaSearch(); $dataProvider = $searchModel->search(Yii::$app->request->queryParams); return $this->render('index', [ 'searchModel' => $searchModel, 'dataProvider' => $dataProvider, ]); } /** * Displays a single Agenda model. * @param integer $id * @return mixed */ Bloque 7. Anexos 86 86 class SincronizarController extends Controller //el controlador es el que da lo que muestra //localhost/index.php/sincronizar { public function beforeAction($action) { $this->enableCsrfValidation = false; return parent::beforeAction($action); } public function actionIndex() { $request = Yii::$app->request; $result="false"; if ($request->isGet) { $token = $request->get('token'); } if ($request->isPost) { $post = $request->post(); $token = $request->post('token'); } if ($token == NULL){ $params = $request->bodyParams; $token = $request->getBodyParam('token'); } if($token != null){ $sql = "SELECT * FROM contacto WHERE ((token = '$token'))"; $model = \app\models\Agenda::findBySql($sql)->all(); //modelo donde se encuentra la clase Login que devuelve la tabla foreach($model as $consulta) { 87 87 Aplicación de contactos compartida if($consulta != null){ $result=true; } } } echo $result . "<br>"; if($result=== true){ $sql = "SELECT * FROM contacto"; $model = \app\models\Agenda::findBySql($sql)->all(); foreach($model as $contacto) { echo $contacto->nombre . "<br>"; echo $contacto->apellido . "<br>"; echo $contacto->telefono . "<br>"; } } } } SiteController.php <?php namespace app\controllers; use Yii; use yii\filters\AccessControl; use yii\web\Controller; use yii\web\Response; use yii\filters\VerbFilter; use app\models\LoginForm; use app\models\ContactForm; class SiteController extends Controller { /** * @inheritdoc */ Bloque 7. Anexos 88 88 public function behaviors() { return [ 'access' => [ 'class' => AccessControl::className(), 'only' => ['logout'], 'rules' => [ [ 'actions' => ['logout'], 'allow' => true, 'roles' => ['@'], ], ], ], 'verbs' => [ 'class' => VerbFilter::className(), 'actions' => [ 'logout' => ['post'], ], ], ]; } /** * @inheritdoc */ public function actions() { return [ 'error' => [ 'class' => 'yii\web\ErrorAction', ], 'captcha' => [ 'class' => 'yii\captcha\CaptchaAction', 'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null, ], ]; 89 89 Aplicación de contactos compartida } /** * Displays homepage. * * @return string */ public function actionIndex() { // necesitamos que el usuario se autentique. Para poder autenticarse tendra que superar la autentificacion frente a la base de datos. mientras tanto // el usuario valdra null. Asi que no pararemos de mostar la misma vista if(($identity = Yii::$app->user->identity) != null) return $this->render('index'); else return $this->render('index2'); } /** * Login action. * * @return Response|string */ public function actionLogin() { if (!Yii::$app->user->isGuest) { return $this->goHome(); } $model = new LoginForm(); if ($model->load(Yii::$app->request->post()) && $model->login()) { return $this->goBack(); } return $this->render('login', [ 'model' => $model, ]); } Bloque 7. Anexos 90 90 /** * Logout action. * * @return Response */ public function actionLogout() { Yii::$app->user->logout(); return $this->goHome(); } /** * Displays contact page. * * @return Response|string */ public function actionContact() { $model = new ContactForm(); if ($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app- >params['adminEmail'])) { Yii::$app->session->setFlash('contactFormSubmitted'); return $this->refresh(); } return $this->render('contact', [ 'model' => $model, ]); } /** * Displays about page. * * @return string */ public function actionAbout() { 91 91 Aplicación de contactos compartida return $this->render('about'); } } TokenController.php <?php namespace app\controllers; use yii\web\Controller; use Yii; // controlador usado por la aplicacion movil para obtener un token // este token es necesario para poder enviar notificaciones class TokenController extends Controller //el controlador es el que da lo que muestra //localhost/index.php/token { public function beforeAction($action) { $this->enableCsrfValidation = false; return parent::beforeAction($action); } public function actionIndex() { $request = Yii::$app->request; $result="false"; if ($request->isGet) { $numero = $request->get('numero'); $token = $request->get('token'); } if ($request->isPost) { $post = $request->post(); $numero = $request->post('numero'); $token = $request->post('token'); } if ($numero == NULL && $token == NULL){ $params = $request->bodyParams; Bloque 7. Anexos 92 92 $numero = $request->getBodyParam('numero'); $token = $request->getBodyParam('token'); } if($numero != null && $token != null){ $sql = "SELECT * FROM contacto WHERE ((telefono = $numero))"; $model = \app\models\Agenda::findBySql($sql)->all(); //modelo donde se encuentra la clase Login que devuelve la tabla foreach($model as $contacto) { //recorremos la tabla buscando que usuario y numero coincidan. Si es asi ponemos a 1 y validamos. $result=true; $contacto->token = NULL; $contacto->token = $token; $contacto->save(); } } echo $result; } } UsuariosController.php <?php namespace app\controllers; use yii\web\Controller; use Yii; class UsuariosController extends Controller //el controlador es el que da lo que muestra { public function beforeAction($action) { $this->enableCsrfValidation = false; return parent::beforeAction($action); 93 93 Aplicación de contactos compartida } public function actionIndex() { if(($identity = Yii::$app->user->identity) != null) { $contactos = \app\models\Agenda::find()->all(); return $this->render('./usuarios'); } else return $this->render('../index2'); } }  Directorio migrations m170807_112948_create_contacto_table.php <?php use yii\db\Migration; /** * Handles the creation of table `contacto`. */ /** archivo de migracion usado para el tfg. Se le pasa la tabla a crear para que lo haga yii con su script * */ class m170807_112948_create_contacto_table extends Migration { /** * @inheritdoc */ public function up() Bloque 7. Anexos 94 94 { $this->createTable('contacto', [ 'idUsuario' => $this->primaryKey(), 'nombre' => $this->string()->notNull(), 'apellido' => $this->string()->notNull(), 'telefono' => $this->string()->notNull(), 'token' => $this->string() ]); } /** * @inheritdoc */ public function down() { $this->dropTable('contacto'); } }  Directorio models Agenda.php <?php namespace app\models; class Agenda extends \yii\db\ActiveRecord { public static function tableName() { return "contacto"; } public function rules() //para validar el formulario 95 95 Aplicación de contactos compartida { return [ [["nombre", "apellido", "telefono"], "required"], //exigimos todos los campos [["nombre"], "string"], [["apellido"], "string"], [["telefono"], "string", "max" => 9, "min" => 9], //maximo numero 9 digitos ]; } public function attributeLabels() { return[ "id" => "Id", "nombre" => "Nombre", "apellido" => "Apellidos", "telefono" => "Telefono" ]; } } AgendaSearch.php <?php namespace app\models; use Yii; use yii\base\Model; use yii\data\ActiveDataProvider; use app\models\Agenda; /** * AgendaSearch represents the model behind the search form about `app\models\Agenda`. */ class AgendaSearch extends Agenda { Bloque 7. Anexos 102 102 public static function tableName() { return "login"; } public function rules() //para validar el formulario { return [ [["user", "passwd"], "required"], //exigimos todos los campos [["user"], "string"], [["passwd"], "string"], ]; } public function attributeLabels() { return[ "id" => "Id", "user" => "user", "passwd" => "passwd" ]; } } LoginForm.php <?php namespace app\models; use Yii; use yii\base\Model; /** * LoginForm is the model behind the login form. 103 103 Aplicación de contactos compartida * * @property User|null $user This property is read-only. * */ class LoginForm extends Model { public $username; public $password; public $rememberMe = true; private $_user = false; /** * @return array the validation rules. */ public function rules() { return [ // username and password are both required [['username', 'password'], 'required'], // rememberMe must be a boolean value ['rememberMe', 'boolean'], // password is validated by validatePassword() ['password', 'validatePassword'], ]; } /** * Validates the password. * This method serves as the inline validation for password. * * @param string $attribute the attribute currently being validated * @param array $params the additional name-value pairs given in the rule */ public function validatePassword($attribute, $params) { if (!$this->hasErrors()) { Bloque 7. Anexos 104 104 $user = $this->getUser(); if (!$user || !$user->validatePassword($this->password)) { $this->addError($attribute, 'Incorrect username or password.'); } } } /** * Logs in a user using the provided username and password. * @return bool whether the user is logged in successfully */ public function login() { if ($this->validate()) { return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0); } return false; } /** * Finds user by [[username]] * * @return User|null */ public function getUser() { if ($this->_user === false) { $this->_user = BackendUser::findByUsername($this->username); } return $this->_user; } } User.php <?php 105 105 Aplicación de contactos compartida namespace app\models; class User extends \yii\base\Object implements \yii\web\IdentityInterface { public $id; public $username; public $password; public $authKey; public $accessToken; private static $users = [ ]; /** * @inheritdoc */ public static function findIdentity($id) { return isset(self::$users[$id]) ? new static(self::$users[$id]) : null; } /** * @inheritdoc */ public static function findIdentityByAccessToken($token, $type = null) { foreach (self::$users as $user) { if ($user['accessToken'] === $token) { return new static($user); } } return null; } /** * Finds user by username Bloque 7. Anexos 106 106 * * @param string $username * @return static|null */ public static function findByUsername($username) { foreach (self::$users as $user) { if (strcasecmp($user['username'], $username) === 0) { return new static($user); } } return null; } /** * @inheritdoc */ public function getId() { return $this->id; } /** * @inheritdoc */ public function getAuthKey() { return $this->authKey; } /** * @inheritdoc */ public function validateAuthKey($authKey) { return $this->authKey === $authKey; 107 107 Aplicación de contactos compartida } /** * Validates password * * @param string $password password to validate * @return bool if password provided is valid for current user */ public function validatePassword($password) { return $this->password === $password; } }  Directorio views/agenda Create.php <?php use yii\helpers\Html; /* @var $this yii\web\View */ /* @var $model app\models\Agenda */ $this->title = 'Introducir nuevo contacto'; $this->params['breadcrumbs'][] = ['label' => 'Agendas', 'url' => ['index']]; $this->params['breadcrumbs'][] = $this->title; ?> <div class="agenda-create"> <h1><?= Html::encode($this->title) ?></h1> <?= $this->render('_form', [ 'model' => $model, ]) ?> </div> Bloque 7. Anexos 108 108 _form.php <?php use yii\helpers\Html; use yii\widgets\ActiveForm; /* @var $this yii\web\View */ /* @var $model app\models\Agenda */ /* @var $form yii\widgets\ActiveForm */ ?> <div class="agenda-form"> <?php $form = ActiveForm::begin(); ?> <?= $form->field($model, 'nombre')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'apellido')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'telefono')->textInput(['maxlength' => true]) ?> <div class="form-group"> <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> </div> <?php ActiveForm::end(); ?> </div> Index.php <?php use yii\helpers\Html; use yii\grid\GridView; /* @var $this yii\web\View */ /* @var $searchModel app\models\AgendaSearch */ 109 109 Aplicación de contactos compartida /* @var $dataProvider yii\data\ActiveDataProvider */ $this->title = 'Contactos'; $this->params['breadcrumbs'][] = $this->title; ?> <div class="agenda-index"> <h1><?= Html::encode($this->title) ?></h1> <?php // echo $this->render('_search', ['model' => $searchModel]); ?> <p> <?= Html::a('Crear nuevo contacto', ['create'], ['class' => 'btn btn-success']) ?> </p> <?= GridView::widget([ 'dataProvider' => $dataProvider, 'filterModel' => $searchModel, 'columns' => [ ['class' => 'yii\grid\SerialColumn'], 'idUsuario', 'nombre', 'apellido', 'telefono', 'token', ['class' => 'yii\grid\ActionColumn'], ], ]); ?> </div> Index2.php <?php /* @var $this yii\web\View */ $this->title = 'USNotificaciones'; ?> <div class="site-index"> Bloque 7. Anexos 110 110 <div class="jumbotron"> <p class="lead">Trabajo de fin de grado 2017-2018.</p> <p><a class="btn btn-lg btn-success" href="http://localhost/index.php/site/login">Login</a></p> </div> </div> _search.php <?php use yii\helpers\Html; use yii\widgets\ActiveForm; /* @var $this yii\web\View */ /* @var $model app\models\AgendaSearch */ /* @var $form yii\widgets\ActiveForm */ ?> <div class="agenda-search"> <?php $form = ActiveForm::begin([ 'action' => ['index'], 'method' => 'get', ]); ?> <?= $form->field($model, 'idUsuario') ?> <?= $form->field($model, 'nombre') ?> <?= $form->field($model, 'apellido') ?> <?= $form->field($model, 'telefono') ?> <?= $form->field($model, 'token') ?> 111 111 Aplicación de contactos compartida <div class="form-group"> <?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?> <?= Html::resetButton('Reset', ['class' => 'btn btn-default']) ?> </div> <?php ActiveForm::end(); ?> </div> Update.php <?php use yii\helpers\Html; /* @var $this yii\web\View */ /* @var $model app\models\Agenda */ $this->title = 'Update Agenda: ' . $model->idUsuario; $this->params['breadcrumbs'][] = ['label' => 'Agendas', 'url' => ['index']]; $this->params['breadcrumbs'][] = ['label' => $model->idUsuario, 'url' => ['view', 'id' => $model->idUsuario]]; $this->params['breadcrumbs'][] = 'Update'; ?> <div class="agenda-update"> <h1><?= Html::encode($this->title) ?></h1> <?= $this->render('_form', [ 'model' => $model, ]) ?> </div> View.php <?php use yii\helpers\Html; use yii\widgets\DetailView; /* @var $this yii\web\View */ Bloque 7. Anexos 118 118 </html> Notification.php <?php class Notification{ private $title; private $message; private $image_url; private $action; private $action_destination; private $data; function __construct(){ } public function setTitle($title){ $this->title = $title; } public function setMessage($message){ $this->message = $message; } public function setImage($imageUrl){ $this->image_url = $imageUrl; } public function setAction($action){ $this->action = $action; } public function setActionDestination($actionDestination){ $this->action_destination = $actionDestination; } public function setPayload($data){ $this->data = $data; 119 119 Aplicación de contactos compartida } public function getNotificatin(){ $notification = array(); $notification['title'] = $this->title; $notification['message'] = $this->message; $notification['image'] = $this->image_url; $notification['action'] = $this->action; $notification['action_destination'] = $this->action_destination; return $notification; } } ?>  Directorio views/site About.php <?php /* @var $this yii\web\View */ use yii\helpers\Html; $this->title = 'Sobre'; $this->params['breadcrumbs'][] = $this->title; ?> <div class="site-about"> <h1><?= Html::encode($this->title) ?></h1> <p>Este TFG ha sido realizado por:</p> <p>Alumno: Alejandro Milán Rodríguez</p> <p>Tutor: José Manuel Fornés Rumbao</p> </div> Consulta.php <?php namespace app\models; Bloque 7. Anexos 120 120 class Token extends \yii\db\ActiveRecord { public static function tablename() { return "contactos"; } } Contact.php <?php /* @var $this yii\web\View */ /* @var $form yii\bootstrap\ActiveForm */ /* @var $model app\models\ContactForm */ use yii\helpers\Html; use yii\bootstrap\ActiveForm; use yii\captcha\Captcha; $this->title = 'Contacto'; $this->params['breadcrumbs'][] = $this->title; ?> <div class="site-contact"> <h1><?= Html::encode($this->title) ?></h1> <?php if (Yii::$app->session->hasFlash('contactFormSubmitted')): ?> <div class="alert alert-success"> Gracias por contactarnos. Le responderemos lo antes posible. </div> <p> Note that if you turn on the Yii debugger, you should be able to view the mail message on the mail panel of the debugger. <?php if (Yii::$app->mailer->useFileTransport): ?> 121 121 Aplicación de contactos compartida Because the application is in development mode, the email is not sent but saved as a file under <code><?= Yii::getAlias(Yii::$app->mailer->fileTransportPath) ?></code>. Please configure the <code>useFileTransport</code> property of the <code>mail</code> application component to be false to enable email sending. <?php endif; ?> </p> <?php else: ?> <p> Si tiene alguna duda o preguntas rellene el siguiente formulario para contactarnos. Gracias. </p> <div class="row"> <div class="col-lg-5"> <?php $form = ActiveForm::begin(['id' => 'contact-form']); ?> <?= $form->field($model, 'name')->textInput(['autofocus' => true]) ?> <?= $form->field($model, 'email') ?> <?= $form->field($model, 'subject') ?> <?= $form->field($model, 'body')->textarea(['rows' => 6]) ?> <?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [ 'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg- 6">{input}</div></div>', ]) ?> <div class="form-group"> <?= Html::submitButton('Enviar', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?> </div> <?php ActiveForm::end(); ?> </div> Bloque 7. Anexos 122 122 </div> <?php endif; ?> </div> Error.php <?php /* @var $this yii\web\View */ /* @var $name string */ /* @var $message string */ /* @var $exception Exception */ use yii\helpers\Html; $this->title = $name; ?> <div class="site-error"> <h1><?= Html::encode($this->title) ?></h1> <div class="alert alert-danger"> <?= nl2br(Html::encode($message)) ?> </div> <p> Ha ocurrido un error mientras el servidor web estaba procesando su petición. </p> <p> Por favor, contáctenos si piensa que es un error de servidor. Gracias. </p> </div> Index.php <?php /* @var $this yii\web\View */ 123 123 Aplicación de contactos compartida $this->title = 'USNotificaciones'; ?> <div class="site-index"> <div class="jumbotron"> <p class="lead"><b>UsNotificaciones</b></p> <p><a class="btn btn-lg btn-success" href="http://localhost/index.php/agenda/create">Agregar un contacto a la base de datos</a></p> <p><a class="btn btn-lg btn-success" href="http://localhost/index.php/usuarios">Agregar un usuario para la aplicacion movil</a></p> <p><a class="btn btn-lg btn-success" href="http://localhost/index.php/agenda/index">Consultar usuarios en la base de datos</a></p> <p><a class="btn btn-lg btn-success" href="http://localhost/index.php/firebase">Enviar una notificacion a un usuario</a></p> </div> <div class="body-content"> <div class="row"> <div class="col-lg-4"> <h2>TFG 2017-2018</h2> <p>Autor : Alejandro Milan Rodriguez</p> <p>Tutor : Jose Manuel Fornes Rumbao</p> </div> <div class="col-lg-4"> </div> <div class="col-lg-4"> <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Emblema_Universidad_de_Sevilla.png/ 245px-Emblema_Universidad_de_Sevilla.png" width="150" height="100" alt="Icono Universidad de Sevilla" align=right> </div> </div> </div> </div> Bloque 7. Anexos 124 124 Index2.php <?php /* @var $this yii\web\View */ $this->title = 'USNotificaciones'; ?> <div class="site-index"> <div class="jumbotron"> <p class="lead">Trabajo de fin de grado: Agenda.</p> <p><a class="btn btn-lg btn-success" href="http://localhost/index.php/site/login">Login</a></p> </div> </div> Login.php <?php /* @var $this yii\web\View */ /* @var $form yii\bootstrap\ActiveForm */ /* @var $model app\models\LoginForm */ use yii\helpers\Html; use yii\bootstrap\ActiveForm; $this->title = 'Autenticación'; $this->params['breadcrumbs'][] = $this->title; ?> <div class="site-login"> <h1><?= Html::encode($this->title) ?></h1> <p>Por favor rellene los siguientes campos:</p> <?php $form = ActiveForm::begin([ 'id' => 'login-form', 125 125 Aplicación de contactos compartida 'layout' => 'horizontal', 'fieldConfig' => [ 'template' => "{label}\n<div class=\"col-lg-3\">{input}</div>\n<div class=\"col-lg-8\">{error}</div>", 'labelOptions' => ['class' => 'col-lg-1 control-label'], ], ]); ?> <?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?> <?= $form->field($model, 'password')->passwordInput() ?> <?= $form->field($model, 'rememberMe')->checkbox([ 'template' => "<div class=\"col-lg-offset-1 col-lg-3\">{input} {label}</div>\n<div class=\"col-lg- 8\">{error}</div>", ]) ?> <div class="form-group"> <div class="col-lg-offset-1 col-lg-11"> <?= Html::submitButton('Enviar', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?> </div> </div> <?php ActiveForm::end(); ?> <!-- <div class="col-lg-offset-1" style="color:#999;"> You may login with <strong>admin/admin</strong> or <strong>demo/demo</strong>.<br> To modify the username/password, please check out the code <code>app\models\User::$users</code>. </div> --> </div> Sincronizar.php <?php namespace app\models; class Sincronizar extends \yii\db\ActiveRecord { public static function tablename() Bloque 7. Anexos 126 126 { return "contactos"; } } Token.php <?php namespace app\models; class Token extends \yii\db\ActiveRecord { public static function tablename() { return "contactos"; } } Directorio views/usuarios Errors.php <?php if (count($errors) > 0) : ?> <div class="error"> <?p hp foreach ($errors as $error) : ?> <p><?php echo $error ?></p> <?p hp endforeach ?> </div> <?php endif ?> Server.php <?php 127 127 Aplicación de contactos compartida $username = ""; $email = ""; $errors = array(); // conexion a la base de datos $db = mysqli_connect('localhost', 'root', 'alemilrod', 'agenda'); // registro de usuario if (isset($_POST['reg_user'])) { $username = mysqli_real_escape_string($db, $_POST['username']); $password_1 = mysqli_real_escape_string($db, $_POST['password_1']); $password_2 = mysqli_real_escape_string($db, $_POST['password_2']); // validamos el formulario if (empty($username)) { array_push($errors, "Un nombre de usuario es necesario"); } if (empty($password_1)) { array_push($errors, "Una contraseña es necesaria"); } if ($password_1 != $password_2) { arra y_push($errors, "Las dos contraseñas no coinciden"); } if (strlen($password_1) < 6){ arra y_push($errors, "La contraseña tiene que tener 6 caracteres minimo"); } // Comprobamos que el usuario no exista en la base de datos $user_check_query = "SELECT * FROM login WHERE user='$username' LIMIT 1"; $result = mysqli_query($db, $user_check_query); $user = mysqli_fetch_assoc($result); if ($user) { // si existe array_push($errors, "Error. El usuario ya existe"); } // Registramos al usuario si no hay errores en el formulario if (count($errors) == 0) { $pa