scieee AI-readable full text Open interactive document viewer

Aplicación android para el internet de las cosas

Marín Portillo, Adrián

Abstract

El presente trabajo aborda la creación de una aplicación para dispositivos Android que, utilizando unas placas de Libelium para recoger el ruido, permite a los usuarios finales ver los niveles de ruido de los lugares donde dichas placas se encuentran. La información se recoge con unos sensores de ruido integrados en las placas y se mandan a través de una conexión WiFi. La información se manda a un servidor desarrollado para esta tarea por mi compañero Antonio Garcia Jiménez. La aplicación Android descargará esa información y la hará disponible al usuario a través de un mapa, donde aparecerán marcados como puntos en el mapa las zonas de las que hay información. Los usuarios también podrán enviar audios al servidor, utilizando una grabadora propia de la aplicación que cogerá la media del nivel de ruido (en decibelios), acompañándose de la ubicación del dispositivo, para tratar dicha información.

Full text

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA GRADO EN INGENIERÍA INFORMÁTICA APLICACIÓN ANDROID PARA EL INTERNET DE LAS COSAS ANDROID APP FOR THE INTERNET OF THINGS Realizado por Adrián Marín Portillo Tutorizado por Mercedes Amor Pinilla Departamento Lenguajes y Ciencias de la Computación UNIVERSIDAD DE MÁLAGA MÁLAGA, JUNIO DE 2016 Fecha defensa: El Secretario del Tribunal Resumen: El presente trabajo aborda la creación de una aplicación para dispositivos Android que, utilizando unas placas de Libelium para recoger el ruido, permite a los usuarios finales ver los niveles de ruido de los lugares donde dichas placas se encuentran. La información se recoge con unos sensores de ruido integrados en las placas y se mandan a través de una conexión WiFi. La información se manda a un servidor desarrollado para esta tarea por mi compañero Antonio Garcia Jiménez. La aplicación Android descargará esa información y la hará disponible al usuario a través de un mapa, donde aparecerán marcados como puntos en el mapa las zonas de las que hay información. Los usuarios también podrán enviar audios al servidor, utilizando una grabadora propia de la aplicación que cogerá la media del nivel de ruido (en decibelios), acompañándose de la ubicación del dispositivo, para tratar dicha información. Palabras claves: android, iot, sensor, mapa, localización, ruido Abstract: This proyect addresses the creation of an Android application that, using some Libelium boards to gather the noise, allows the final users to see the noise levels of the places where the boards are located and an estimation of the ocupation of that place. The information is gathered with a noise sensor integrated within the board, the board sends it via WiFi. This information is sended to a server developed only for this task by my partner Antonio Garcia Jiménez. The Android application will gather this information and it will make it available in a map. That map will contain the points with the geographical location sended by the server. The users can also send audio files to the server, using a recorder that will take the average noise level in the environment, with the geographical location of the device attached, with the purpose of working with that information. Keywords: android, iot, sensor, map, location, noise ´ Indice general Lista de figuras 3 Lista de tablas 5 1. Introducci´on. 7 1.1. Resumen. .................................... 7 1.2. Introducci´on al proyecto y objetivos. . . . . . . . . . . . . . . . . . . . . . 8 1.3. Descripci´on y justificaci´on de la estructura del documento. . . . . . . . . . 9 1.4. Aclaraciones sobre el anexo del anteproyecto. . . . . . . . . . . . . . . . . . 9 2. El sistema operativo Android. 11 2.1. Introducci´on a Android. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2. VersionesdeAndroid............................... 11 2.3. Arquitectura de Android. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.4. Desarrollo de aplicaciones para Android. . . . . . . . . . . . . . . . . . . . 15 2.5. Publicaci´on de aplicaciones para Android. . . . . . . . . . . . . . . . . . . 17 3. Placa Waspmote. 19 3.1. Introducci´on a Waspmote. . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.2. Caracter´ısticas t´ecnicas y arquitectura. . . . . . . . . . . . . . . . . . . . . 19 3.3. Sensores...................................... 21 3.4. Interfaces de comunicaciones. . . . . . . . . . . . . . . . . . . . . . . . . . 22 3.5. Desarrollo de programas para Waspmote. . . . . . . . . . . . . . . . . . . . 23 4. Desarrollo e implementaci´on del proyecto. 25 4.1. Sketch paraWaspmote.............................. 25 4.1.1. Explicaci´on del funcionamiento del sketch. . . . . . . . . . . . . . . 25 4.1.2. Despliegue en el entorno de pruebas. . . . . . . . . . . . . . . . . . 27 4.1.3. C´odigo del sketch............................. 27 4.2. Aplicaci´on para dispositivos Android. . . . . . . . . . . . . . . . . . . . . . 31 4.2.1. Descripci´on del proyecto y diversas decisiones. . . . . . . . . . . . . 31 4.2.2. Estructura de la aplicaci´on. . . . . . . . . . . . . . . . . . . . . . . 34 4.2.3. Explicaci´on del funcionamiento de la integraci´on. . . . . . . . . . . 38 1 ´ INDICE GENERAL 4.2.4. Fases del desarrollo de la aplicaci´on. . . . . . . . . . . . . . . . . . . 38 4.2.5. C´odigo del proyecto. . . . . . . . . . . . . . . . . . . . . . . . . . . 39 5. Conclusiones y trabajo futuro. 61 5.1. Conclusiones................................... 61 5.1.1. Mi opini´on sobre el desarrollo en Android . . . . . . . . . . . . . . 61 5.1.2. Mi opini´on sobre el desarrollo para Waspmote . . . . . . . . . . . . 62 5.1.3. An´alisis de los resultados . . . . . . . . . . . . . . . . . . . . . . . . 62 5.2. Trabajofuturo. ................................. 63 6. Ap´endice. 67 6.1. Listadeacr´onimos ............................... 67 6.2. Manual de usuario y capturas de pantalla. . . . . . . . . . . . . . . . . . . 67 6.2.1. Aplicaci´on para dispositivos Android. . . . . . . . . . . . . . . . . . 67 6.2.2. Sketch paraWaspmote.......................... 70 2 ´ Indice de figuras 2.1. Distribuci´on de dispositivos Android seg´un la versi´on del sistema . . . . . 13 2.2. Capas de la arquitectura de Android . . . . . . . . . . . . . . . . . . . . . 14 2.3. Pantalla de Android Studio . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.1. Parte delantera de una mota . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.2. Diagrama del flujo de datos de una mota . . . . . . . . . . . . . . . . . . 21 3.3. Mota con sensor de presencia . . . . . . . . . . . . . . . . . . . . . . . . . 22 3.4. Interfaz del entorno de desarrollo. . . . . . . . . . . . . . . . . . . . . . . . 23 4.1. Vista previa de la actividad de inicio. . . . . . . . . . . . . . . . . . . . . 32 4.2. Vista previa de la actividad de la grabadora. . . . . . . . . . . . . . . . . 33 4.3. Caso de uso para MainActivity ........................ 35 4.4. Diagrama de estados para RecordActivity .................. 36 4.5. Ejemplo de JavaScript Object Notation (JSON) que se env´ıa . . . . . . . 38 6.1. Punto donde se han realizado pruebas de sonido. . . . . . . . . . . . . . . 68 6.2. Localizaci´on actual. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 6.3. Estado inicial de la grabadora. . . . . . . . . . . . . . . . . . . . . . . . . 69 6.4. Grabando. ................................... 69 6.5. Prueba de env´ıo de audio. . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 6.6. Escogiendo que aplicaci´on usar para compartir informaci´on . . . . . . . . 70 6.7. Muestra del funcionamiento de la placa . . . . . . . . . . . . . . . . . . . 71 3 ´ INDICE DE FIGURAS 4 ´ Indice de tablas 1.1. Tabla de horas corregida . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 4.1. Modosdeenerg´ıa................................ 26 4.2. Relaci´on ruido-decibelios . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 5 ´ INDICE DE TABLAS 6 CAP´ ITULO 2. EL SISTEMA OPERATIVO ANDROID. Figura 2.1: Distribuci´on de dispositivos Android seg´un la versi´on del sistema La anterior gr´afica muestra la distribuci´on de usuarios respecto a la versi´on de Android que utiliza [7] . Para este proyecto se ha tenido en cuenta la distribuci´on de los dispositivos Android, teniendo en cuenta tambi´en las herramientas disponibles a nivel de desarrollador. 2.3. Arquitectura de Android. Android se basa en un kernel de Linux, sobre el cual hay ciertas librer´ıas y API’s escritas en C, un framework de aplicaciones y un conjunto de aplicaciones en la capa de m´as alto nivel. Linux Kernel Hay que aclarar primero que Android est´a basado en Linux pero no es una distribuci´on de Linux, sino que los desarrolladores pueden modificar el kernel para adaptarlo a las necesidades propias de Android, construyendo un sistema totalmente distinto. Este n´ucleo incluye los drivers necesarios para el funcionamiento del dispositivo. Libraries Son librer´ıas escritas en C/C++ que hacen operaciones de forma mas sencilla para el programador y ayudan a mejorar el rendimiento. Un ejemplo ser´ıan las librer´ıas de SQLite o OpenGL. 13 2.3. ARQUITECTURA DE ANDROID. Android Runtime Las aplicaciones Android se ejecutan sobre una m´aquina virtual. Primero fue Dalvik, utilizando compilaci´on Just In Time (JIT) de Java a Java bytecode, y luego el resultado se traduce a un fichero con formato .dex para ser entendido por Dalvik. Desde Android 5.0 se utiliza Android Runtime (ART), que usa compilaci´on ahead of time (AOT) y otras t´ecnicas para mejorar la velocidad y el rendimiento. Application Framework Aqu´ı se encuentran recursos que utilizan los desarrolladores para realizar las aplicaciones. Se puede destacar el Activity Manager, para la gesti´on del ciclo de vida de las actividades, los Content Providers, para compartir datos entre aplicaciones distintas, o el Location Manager, para tareas relacionadas con el Global Positioning System (GPS). Applications La capa superior incluye las aplicaciones b´asicas que incluye el sistema, como el gestor de contactos, el navegador, etc Figura 2.2: Capas de la arquitectura de Android 14 CAP´ ITULO 2. EL SISTEMA OPERATIVO ANDROID. 2.4. Desarrollo de aplicaciones para Android. Las aplicaciones Android est´an escritas, principalmente, en Java, empleando para ello el Software Development Kit (SDK) que proporciona el framework necesario: librer´ıas, depuradores, emuladores, c´odigos de ejemplo, etc. El SDK de Android est´a disponible tanto para Windows, Mac OS X y GNU/Linux. Otras posibilidades destacables para realizar aplicaciones para Android son: Kotlin: Es un lenguaje desarrollado por JetBrains que corre sobre cualquier m´aquina virtual de Java. Es compatible 100 % con Android, puede ser utilizado en un proyecto en el cual se utilice Java, y nos da ciertas ventajas que a´un no est´an en Java, como las funciones lambda, y otras que no est´an ni en versiones mas actuales de Java, como un manejo mas seguro de los objetos null. Es un lenguaje a tener en cuenta en el futuro, puesto que Google lo est´a promocionando mucho[8]. Xamarin: Creado por los ingenieros que desarrollaron el compilador Mono, es un software bajo el cual se pueden desarrollar aplicaciones m´oviles para m´ultiples plataformas (Android, iOS y Windows Mobile) utilizando C# Corona: Un SDK basado en el lenguaje LUA pensado para realizar aplicaciones de manera mas sencilla que en Java. NDK: Utilizando la JNI (Java Native Interface), los desarrolladores pueden utilizar c´odigo escrito en C/C++, y haciendo que se aproveche mas el procesador del dispositivo. Anteriormente se usaba principalmente Eclipse, pero Google descontinu´o su soporte en 2015, animando a los desarrolladores a utilizar el nuevo entorno oficial, Android Studio. Android Studio est´a basado en IntelliJ IDEA, un entorno desarrollado por JetBrains (que tiene Integrated Development Environment (IDE)’s para otros lenguajes como Java, PHP, Python, etc). Fue presentado en mayo de 2013 en una Google I/O Conference y se lanz´o p´ublicamente a finales de 2014. Recientemente ha sido lanzada la versi´on 2.1, mejorando los tiempos de compilaci´on y a˜nadiendo mejoras como instant run, para probar c´odigo de manera m´as r´apida. Tambi´en est´a disponible para Mac OS X, GNU/Linux y Windows[9]. Sus caracter´ısticas principales son: Renderizaci´on en tiempo real. Construcci´on del archivo .apk usando Gradle, sistema heredero de Ant y Maven. Posibilidad de crear Build Variants, versiones/configuraciones distintas de la aplicaci´on seg´un el dispositivo para el cual se lance u otras reglas. Integraci´on mas f´acil de Unit Testing. 15 2.4. DESARROLLO DE APLICACIONES PARA ANDROID. Optimizaci´on del proyecto mediante el uso de Android Lint, que estudia el c´odigo y te destaca que se deber´ıa arreglar o cambiar. Herramientas para un mejor desarrollo de interfaces. Figura 2.3: Pantalla de Android Studio El c´odigo de una aplicaci´on Android se divide en tres partes principales [10] Las clases Java, que podr´an ser de los siguientes tipos: •Clase t´ıpica en Java, pudiendo utilizarse interfaces, que sean clases abstractas, etc. •Actividades, que manejan la l´ogica de la visualizaci´on y organizan el funcionamiento general de la aplicaci´on. •Servicios, que son procesos en background. •Content Provider, para compartir informaci´on a trav´es de las aplicaciones. •Etc´etera, etc´etera. El archivo manifest que incluye la configuraci´on b´asica de la aplicaci´on: la lista de actividades, los permisos que se necesitan, etc. Los archivos eXtensible Markup Language (XML) para distintas tareas: •Almacenar valores de cadenas de texto (que pueden tener distintos valores seg´un el idioma del sistema) o estilos de dise˜nos. 16 CAP´ ITULO 2. EL SISTEMA OPERATIVO ANDROID. •Claves para API’s externas. •Dise˜nar las interfaces/layouts de usuario, pudiendo realizarse de distinta forma seg´un la resoluci´on del dispositivo donde se instale. 2.5. Publicaci´on de aplicaciones para Android. La manera oficial para distribuir las aplicaciones Android es utilizando el Google Play Store, anteriormente conocido como Android Market. Se trata de una plataforma de distribuci´on digital donde los usuarios pueden acceder tanto a aplicaciones como pel´ıculas, m´usica, revistas, juegos, etc. Para el primer trimestre de 2016 se ha llegado a los casi 2 millones de aplicaciones publicadas[11]. Existen tanto las aplicaciones gratuitas como las de pago, y en ambas se acepta el uso de los micro-pagos. Para poder subir aplicaciones como desarrollador solo hay que hacer un peque˜no pago ´unico de 25 dolares. Google no hace ning´un tipo de revisi´on a las aplicaciones que subimos, a diferencia de Apple que impone revisiones muy complicadas haciendo que haya menos aplicaciones en su tienda, aunque si revisa luego posibles denuncias de falsificaci´on o infracciones del copyright[12]. Hay otras tiendas para poder descargar aplicaciones, aunque no mencionar´e ninguna aqu´ı, ya que son muchos los casos en los que estas otras tiendas han sido utilizadas para distribuir software falso o con virus. Tambi´en pueden ser instaladas manualmente, descargando el archivo .apk, desactivando antes una opci´on de seguridad en los ajustes del dispositivo. 17 2.5. PUBLICACI´ ON DE APLICACIONES PARA ANDROID. 18 Cap´ıtulo 3 Placa Waspmote. 3.1. Introducci´on a Waspmote. Waspmote es una plataforma de sensores wireless de c´odigo abierto pensada para que el desarrollador tenga el control total de una o varias motas aut´onomas que sigan una filosof´ıa en la que los componentes necesarios sean sencillos de a˜nadir a la mota. Se pueden preparar redes inal´ambricas de sensores bastante f´aciles y escalables con esta plataforma. Estas motas fueron desarrolladas por la empresa Libelium, de Zaragoza, que fue fundada en 2006 por Alicia As´ın y David Gasc´on. Se considera una empresa pionera en el mundo del Internet de las Cosas, y actualmente trabajan con muchas empresas y organismos p´ublicos para llevar sus productos a todas partes del mundo[13]. Waspmote empez´o como un proyecto derivado de Arduino, por eso utilizan un compilador y drivers similares y ambos tienen un entorno de desarrollo similar. 3.2. Caracter´ısticas t´ecnicas y arquitectura. La Waspmote Pro v1.1, que es la que utilizo en este proyecto y una de las ´ultimas a la venta, tiene las siguientes caracter´ısticas t´ecnicas: Microprocesador Atmega1281 a 8 Mhz. 128Kb de memoria Flash, 8Kb de Static Random Access Memory (SRAM) y 4Kb de Electrically Erasable Programmable Read-Only Memory (EEPROM). Dimensiones de 73.5x51x13 mm y un peso de 20 gramos. Admite desde -20 a 60 grados cent´ıgrados. Incluye un reloj Real Time Clock (RTC) (Real Time Clock) a 32 Khz. 19 3.2. CARACTER´ ISTICAS T´ ECNICAS Y ARQUITECTURA. Consume encendido 15mA, en modo sleep 55µA, en modo deep sleep 55µA y en modo hibernaci´on 0.06µA. Entradas/salidas: •7 entradas an´alogas. •8 entradas/salidas digitales. •2 UART (Universal Asynchronous Receiver-Transmitter). •1 L2C (Inter-Integrated Circuit). •1 SPI (Serial Peripheral Interface). •1 entrada USB. •Varios sockets espec´ıficos para ciertos sensores (temperatura, ruido, etc). Voltaje de la bater´ıa de 3.3V a 4.2V Figura 3.1: Parte delantera de una mota 20 CAP´ ITULO 3. PLACA WASPMOTE. Figura 3.2: Diagrama del flujo de datos de una mota Waspmote est´a pensado para tener una arquitectura modular, en la que cada m´odulo solo sea instalado si es necesario, ahorrando en costes y complejidad. Un m´odulo integrable de Waspmote es un circuito dise˜nado para funcionar con estas motas al instante, tan s´olo hay que insertarlo en su respectivo hueco, y mediante la API que ofrece, que debe ser importada en el sketch, se pueden utilizar sus funciones de manera sencilla. Los m´odulos integrables principales se describen en los siguientes apartados 3.3. Sensores. Los sensores se utilizan a trav´es de las placas de sensores que ofrece Libelium. Estas placas permiten a los desarrolladores acceder a diversos tipos de sensores f´acilmente, sin tener que preocuparse por problemas como los referentes al cableado, mediante la API que ofrece cada una. Gracias a estas placas podemos medir las variaciones en una gran variedad de medidas posibles. En las motas se pueden integrar las siguientes placas de sensores: Gases, desde los mas propios de procesos industriales como de poluci´on o incluso para detectar incendios. Ejemplos: CO, CO2, O3 Gases PRO, que pueden detectar part´ıculas de polvo y gases mas ’complejos’ para los sensores anteriores. Ejemplos: CH4, HCl 21 3.4. INTERFACES DE COMUNICACIONES. De eventos, como cambios en la presi´on, temperatura, efecto Hall, vibraciones, etc. Smart Water para propiedades relacionadas con el agua, como el pH, los nitratos que tiene, la salinidad, etc. Smart Cities, para recoger informaci´on sobre el ruido, los ultrasonidos, la temperatura, etc. Smart Parking, para la gesti´on de aparcamientos. Para la agricultura, pudiendo detectar la temperatura, la radiaci´on ultravioleta, la humedad, etc. Aunque se mencione varias veces, por ejemplo, la temperatura en lo que pueden recoger los sensores, estos sensores no son intercambiables entre si. Es decir, un sensor de la categor´ıa de eventos para recoger la temperatura no es v´alido para la agricultura, puesto que est´a expuesto a unas condiciones totalmente distintas que determinan su calibraci´on y su medici´on en un entorno ambiental concreto. Figura 3.3: Mota con sensor de presencia 3.4. Interfaces de comunicaciones. Las motas pueden aprovechar de los siguientes protocolos importantes usando sus respectivos m´odulos: 802.15.4/ZigBee, con cifrado AES 128b y pudiendo usar las topolog´ıas de ´arbol, malla y P2P. 22 CAP´ ITULO 4. DESARROLLO E IMPLEMENTACI´ ON DEL PROYECTO. s t r c a t ( value message , gps ) ; USB. print (” sentence : ” ) ; USB. pri n t ln ( value message ) ; i f (WIFI . j o i n (ESSID ) ) { USB. pri n tln (F(” Conexion con e l AP es tabl ecid a ” ) ) ; s p r i n t f ( sentence ,”POST?” , value message ) ; USB. print (” sentence : ” ) ; USB. pri n t ln ( sentence ) ; stat us = WIFI . getURL(IP , IP ADDRESS, sentence ) ; i f ( s tat us ==200) { USB. pri n t ln (F(”\nPeticion OK. ” ) ) ; USB. pr intl n (WIFI . answer ) ; } e l s e { USB. pri n t ln (F(”\nERROR PETICION” ) ) ; } } e l s e { USB. pri n t ln (F(” Conexion f a l l i d a ” ) ) ; } Sensor Cities . setSensorMode (SENS OFF, SENS CITIES AUDIO ) ; /∗ Modo s l e e p durante 1 minuto . La placa no admite valores s uperi o res a 8 segundos a s i que para dormir un minuto , 60 segundos , debe dormir 15 veces durante 4 segundos ∗/ fo r ( int i =0; i <16; i++) { PWR. sleep (WTD 4S, ALL OFF) ; } } /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ ∗wifi setup ∗funcion para config u rar la conexion WiFi ∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ void w i f i s e t u p () { // Encender e l modulo WiFi en e l socket deseado i f ( WIFI .ON( socket ) == 1 ){ 29 4.1. SKETCH PARA WASPMOTE. USB. pri n tln (F(”WiFi encendido ” ) ) ; // 1 . Configura e l pro tocolo a s e guir . WIFI. setConnectionOptions(HTTP|CLIENT SERVER) ; // 2. Configura como obtener la IP . WIFI . setDHCPoptions (DHCP ON) ; // 3. Configura como conectarte al AP WIFI . setJoinMode (MANUAL) ; // 4. Configurar modo de autentic acion . WIFI . setAuthKey (WPA1,AUTHKEY) ; // 5. Guardar cambios WIFI . storeData ( ) ; } e l s e { USB. pri n tln (F(”WiFi no funcionando ” ) ) ; } } /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ ∗ftoa ∗funcion para conv e r t ir de double a char , ∗con una c i e r t a p r e c i s i o n ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ char ∗ftoa ( double f , char ∗a , i nt p r e c i s i o n ) { long p [ ] = { 0,10,100,1000,10000,100000,1000000,10000000,100000000 }; char ∗ret = a ; long h e i l t a l = ( long ) f ; itoa ( h e i l t a l , a , 1 0); while (∗a != ’\0 ’) a++; ∗a++ = ’ . ’ ; long desimal = abs ( ( long ) ( ( f −heiltal) ∗p [ p r e c i s i o n ] ) ) ; itoa ( desimal , a , 10); return ret ; } 30 CAP´ ITULO 4. DESARROLLO E IMPLEMENTACI´ ON DEL PROYECTO. 4.2. Aplicaci´on para dispositivos Android. 4.2.1. Descripci´on del proyecto y diversas decisiones. Para hablar sobre el funcionamiento de la aplicaci´on antes hay que comentar ciertos aspectos sobre los componentes y partes de Android que he utilizado en el desarrollo y que hay que explicar: Fragment: Introducidos en Android 3.0 y pensados para su uso en tabletas, permiten representar en una parte de la pantalla cierta informaci´on, pudiendo utilizar la otra parte para otra tarea. En este caso, he utilizado un fragment espec´ıfico llamado SupportMapFragment que es de la API de Google para dispositivos Android, para integrar f´acilmente un mapa dentro de la propia aplicaci´on y poder manipularlo seg´un mis necesidades. Volley: Es una librer´ıa desarrollada por Google para realizar las peticiones Hypertext Transfer Protocol (HTTP) de manera m´as sencilla y r´apida, permitiendo m´ultiples conexiones de red concurrentes sin tener que complicarnos con los aspectos de la concurrencia. Anteriormente se utilizaba para las peticiones la librer´ıa de Apache, pero ya no se incluye en Android desde el nivel de API 23 (Android 6.0) y se consider´o deprecated en el nivel de API 22 (Android 5.1). Para utilizarlo se puede incluir una linea en el archivo de Gradle o se puede incluir como .jar en las librer´ıas. AsyncTask: Se utiliza esta clase, concretamente creando una clase que herede de ella, para realizar operaciones de background complicadas que puedan tardar, evitando que se realicen en el hilo/thread de la interfaz gr´afica. Esto se hace as´ı debido a que estas operaciones pueden congelar dicho hilo, y si lo hacen m´as de 5 segundos el programa lanza una excepci´on del tipo ANR (Android Not Responding). LocationManager: Un recurso que pertenece dentro del stack de Android al framework de aplicaciones y que gestiona los sistemas de localizaci´on. Concretamente en este proyecto se utiliza para la localizaci´on GPS. Handler: Utilizado para mandar y recibir procesos entre aplicaciones y/o clases. En este proyecto se utiliza junto a la clase que toma los valores de ruido para manejar dicha informaci´on. La aplicaci´on tiene 3 pantallas principales: Inicio: En esta pantalla, que es la que se carga al iniciar la aplicaci´on, se elige la acci´on a lanzar, que puede ser consultar el mapa con los niveles de ruidos, mandar un audio propio, una pantalla con informaci´on sobre la aplicaci´on o compartir un mensaje en redes sociales. La actividad que gestiona esta pantalla es MainActivity. 31 4.2. APLICACI´ ON PARA DISPOSITIVOS ANDROID. Figura 4.1: Vista previa de la actividad de inicio. Niveles de ruido: En esta pantalla podemos ver, gracias a la API de Google Maps, un mapa, que est´a controlado por un fragment, en el cual se pueden ver los marcadores de los puntos de los cuales el servidor tiene informaci´on. Esta pantalla est´a controlada por la actividad NoiseActivity y para poder entrar en ella el usuario debe activar el GPS, ya que se necesita dentro (al intentar entrar sin tener activo el GPS se muestra un aviso al usuario para que lo active). 32 CAP´ ITULO 4. DESARROLLO E IMPLEMENTACI´ ON DEL PROYECTO. Figura 4.2: Vista previa de la actividad de la grabadora. Enviar prueba de ruido: Aqu´ı el usuario puede grabar un ruido que considere que debe enviar a los servidores. Se crea dentro un grabador de sonidos, en vez de reutilizar el que tiene incorporado Android, porque as´ı, al salir de la pantalla, se puede enviar el audio al servidor f´acilmente (el grabador nativo de Android daba problemas respecto a este tema). La actividad controladora de esta pantalla es RecordActivity y tambi´en es necesario que se active el GPS, funcionando en este sentido igual que la actividad anterior. Los otros dos botones que aparecen en la aplicaci´on de inicio corresponden a un bot´on en el que se repite de manera mas sencilla esta informaci´on, de cara al f´acil entendimiento del usuario final, y un bot´on para compartir un mensaje en las redes sociales sobre la 33 4.2. APLICACI´ ON PARA DISPOSITIVOS ANDROID. aplicaci´on o para mandar un correo. Un aspecto principal de todo desarrollo en Android es escoger que nivel de API es el m´ınimo con el cual puede funcionar. Para compilar se recomienda utilizar las herramientas incluidas en las APIs mas modernas (concretamente se utilizan las librer´ıas de support), pero siempre hay que indicar un nivel m´ınimo de API. Esto es as´ı debido a como funcionan los niveles: cuando vamos subiendo de nivel se a˜naden funcionalidades nuevas y otras son sustituidas por nuevas implementaciones. Otro aspecto fundamental a la hora de escoger nivel es el porcentaje de dispositivos que hay en uso que tengan m´ınimo esa API. Hemos podido ver en la Figura 1 el porcentaje de dispositivos que utilizan cada versi´on de Android, y por tanto la API que usan. Es por ello que, teniendo en cuenta la distribuci´on de su uso y las ventajas que se a˜naden, he escogido para este desarrollo utilizar como nivel m´ınimo la API 16, que se corresponde con Android 4.1, pudiendo abarcar casi el 95 % de los dispositivos que hay en uso actualmente. 4.2.2. Estructura de la aplicaci´on. Las partes destacables de todo proyecto Android son: Archivo manifest. Los componentes que controlan la vista y l´ogica de la aplicaci´on. Los recursos, como cadenas de texto, im´agenes, etc´etera. Archivos relacionados con Gradle. El n´ucleo del funcionamiento de la aplicaci´on es el archivo del manifest, que es un archivo xml donde se incluye, siguiendo la estructura t´ıpica de este tipo de archivos: Los permisos que se solicitan a la hora de instalar (API menor o igual que la 22) o en tiempo de ejecuci´on (API superior que la 22). Si en una actualizaci´on de la aplicaci´on se a˜nade una nueva petici´on de permisos, se avisa al usuario antes de ejecutar la actualizaci´on. Solo se deben incluir los permisos necesarios para el correcto funcionamiento de la aplicaci´on, siendo sospechoso que se pidan algunos permisos, concretamente si son de los que la documentaci´on oficial considera peligrosos, como los relacionados con las llamadas o SMS, por ejemplo. Informaci´on sobre la aplicaci´on en si y los componentes que usa, incluyendo las pantallas o activities que se utilizan y el estilo o estilos que utilizan. Tambi´en se puede cambiar en esta parte otros aspectos importantes como el icono o incluso el nombre de la aplicaci´on. Anteriormente se indicaba en el archivo que nivel de API era el m´ınimo para el funcionamiento de la aplicaci´on, pero eso se incluye ahora en el archivo de propiedades de Gradle. 34 CAP´ ITULO 4. DESARROLLO E IMPLEMENTACI´ ON DEL PROYECTO. Otros datos importantes, como la key de una API. Para poder utilizar la API de Google Maps hay que solicitar una key, indicando luego en el archivo manifest cual es o la ruta hacia donde est´e el valor almacenado. Los componentes que controlan la vista y l´ogica de la aplicaci´on ser´an, en nuestro caso, las actividades o activities. Las actividades gestionan el funcionamiento de la pantalla y la informaci´on que se maneja entre ellas. En este proyecto se encuentran 3 actividades importantes y una a modo de informaci´on: MainActivity: El funcionamiento es como el que se muestra en la siguiente figura, indicando que se necesita para el funcionamiento de dos de las actividades la activaci´on del GPS. Figura 4.3: Caso de uso para MainActivity NoiseActivity: En esta actividad se puede ver un mapa con unos marcadores que indican los lugares de los cuales tiene datos el servidor. Puede seleccionarlos uno a uno los marcadores o puede darle al bot´on de siguiente, que se los ense˜nar´a uno a uno en bucle. Tambi´en puede darle al bot´on de geolocalizaci´on para mostrarle donde se encuentra. RecordActivity: Esta actividad incluye una grabadora de sonidos, que toma la media del nivel de ruido que hay en el ambiente y env´ıa dicha media al servidor. Para enviarlo se utiliza una clase que hereda de AsyncTask llamada UploadTask, enviando la localizaci´on tambi´en para que se muestre tambi´en en el mapa. El funcionamiento de esta actividad se describe en la siguiente figura: 35 4.2. APLICACI´ ON PARA DISPOSITIVOS ANDROID. Figura 4.4: Diagrama de estados para RecordActivity InformationActivity: Una actividad para mostrar informaci´on mas resumida sobre el funcionamiento de la aplicaci´on La tercera y ´ultima parte importante de un proyecto en Android es la carpeta de recursos, que se organiza de la siguiente forma en este proyecto: Drawable: Aqu´ı se incluyen archivos bitmap (.png, .9.png, .jpg, .gif) o archivos XML que son convertidos a bitmap. layout: Archivos XML para definir la interfaz de usuario. Dentro de estos archivos he usado, principalmente, los siguientes componentes: •RelativeLayout, que act´ua principalmente como ra´ız del dise˜no y es donde se indican cuales son los elementos que forman parte de esa interfaz. •LinearLayout, para poner ordenados los elementos de la interfaz. •TextView, para ense˜nar textos. •Buttons, para cambiar de interfaz, parar la grabadora, etc. •ImageView, que son b´asicamente botones peque˜nos con una imagen y acci´on asociada. 36 CAP´ ITULO 4. DESARROLLO E IMPLEMENTACI´ ON DEL PROYECTO. •Fragment, que se ha mencionado su funcionamiento antes y que tambi´en debe indicarse en el XML. Mipmap: Otro tipo de im´agenes. Values: Aqu´ı se almacenen distintos tipos de valores, organiz´andose as´ı: •Colors.xml para los colores. •Dimens.xml para las dimensiones de algunos elementos. •Strings.xml para las cadenas de texto. •Styles.xml para dise˜nar estilos propios que se usar´an en los botones y otros elementos. Con la introducci´on de Gradle algunas de las propiedades que se indicaban en el manifest o otros archivos han pasado a incluirse en el archivo de Gradle de cada proyecto. Principalmente sirve para construir el archivo .apk y para hacer debugging al proyecto, en este archivo se incluye: Identificaci´on de la aplicaci´on, su c´odigo de versi´on, el nivel de API m´ınimo que utiliza y la versi´on del SDK de Android con el que se compila. El tipo de versi´on que se construye, pudiendo crear archivos .apk distintos para tel´efonos y tabletas, por ejemplo. Las librer´ıas a compilar. Por defecto se compila las librer´ıas que se encuentren en la carpeta libs y JUnit pero tambi´en se pueden incluir otras librer´ıas. Para este proyecto se han incluido las librer´ıas de apoyo de Android (para hacer funcionar el proyecto en m´oviles con sistemas anteriores al del SDK con el que se compila) y la librer´ıa de Google Play Services, que es necesaria para poder utilizar la API de Google Maps. Una queja que hay respecto a Gradle es que es bastante lento, algo que es verdad cuando hay que compilar muchas librer´ıas externas, pero se puede mejorar la velocidad tocando unos peque˜nos ajustes de velocidad y memoria RAM que utiliza el compilador en el ordenador, pudiendo pasar a reducir los tiempos de compilaci´on de manera dr´astica. Como ´ultimo toca mencionar la clase Java que hace las funciones de grabadora y de donde se saca el nivel de ruido. La clase, llamada SplEngine1, tiene licencia GNU General Public License (GPL) versi´on 2, por lo cual puede ser utilizada perfectamente en este proyecto. Esta clase va recogiendo el nivel de ruido en un hilo aparte, que se comunica con la actividad que lo invoc´o a trav´es de su Handler. Si bien su c´odigo es perfectamente funcional, tiene una componente respecto al audio que en la API actual se considera deprecated, es decir, no se recomienda su uso y otra respecto a la hora de guardar logs sobre el funcionamiento, aunque no he retocado esta al no usar esta funci´on. 1creada por Hashir N.A, c´odigo fuente en https://code.google.com/archive/p/splmeter/ 37 4.2. APLICACI´ ON PARA DISPOSITIVOS ANDROID. 4.2.3. Explicaci´on del funcionamiento de la integraci´on. La tarea de integraci´on en Android es relativamente sencilla ya que para ello est´a la librer´ıa que coment´e: Volley. Concretamente se hacen peticiones en 2 momentos: Cuando se inicia NoiseActivity se hace una petici´on GET al servidor, concretamente una de la forma GET /user-id/device-id/TO-DO , que es un archivo JSON que debe ser tratado para convertir su informaci´on (coordenadas y nivel de ruido) a marcador de Google Maps. La clase encargada de hacer la petici´on se llama MarkerTask. Cuando se acaba la actividad RecordActivity y se pasa de nuevo a MainActivity se hace una petici´on POST en la clase UploadTask. Este POST ser´a un archivo JSON con la localizaci´on y el nivel de ruido. Un ejemplo de archivo JSON que se maneja en el proyecto: Figura 4.5: Ejemplo de JSON que se env´ıa 4.2.4. Fases del desarrollo de la aplicaci´on. El desarrollo ha seguido un modelo basado en prototipos, que es un tipo de modelo de desarrollo evolutivo. Cada prototipo ha sido construido utilizando los componentes m´ınimos y necesarios hasta llegar al producto definitivo, es decir, a una aplicaci´on completa y funcional. Los prototipos que se han desarrollado son, en ese orden, los siguientes: Creaci´on de la actividad principal, MainActivity, con el estilo deseado, incluyendo los botones hacia las correspondientes actividades (sin ning´un funcionamiento asociado en el momento). Inclusi´on de una pantalla explicando el funcionamiento deseado de la aplicaci´on y de un bot´on para compartir un mensaje sobre la aplicaci´on. Creaci´on de la actividad grabadora, RecordActivity, donde inicialmente solo grababa el audio. Se a˜nade en este momento el permiso de RECORD AUDIO, el de ACCESS FINE LOCATION yACCESS COARSE LOCATION. 38 CAP´ ITULO 4. DESARROLLO E IMPLEMENTACI´ ON DEL PROYECTO. public void onClickInformation (View view ) { Intent intent = new Intent ( getApplicationContext ( ) , InformationActivity . c l a s s ) ; s t a r t A c t i v i t y ( i nt ent ) ; } public void onClickShare ( View view ) { i f ( t h i s . openChooser != n ul l ) { s t a r t A c t i v i t y ( openChooser ) ; }e l s e { s t a r t A c t i v i t y ( g en er at eI nt en t ( ) ) ; } } public void setOpenChooser ( Intent openChooser ) { t h i s . openChooser = openChooser ; } public Intent generateIntent () { Resources resource s = getResources ( ) ; Intent emailIntent = new Intent ( ) ; emailIntent . setAction ( Intent .ACTION SEND) ; emailIntent . putExtra ( Intent .EXTRA TEXT, Html . fromHtml ( resources . g et St ri ng ( R. s t r i n g . s hare e mail n a tive ) ) ) ; emailIntent . putExtra ( Intent .EXTRA SUBJECT, r eso u rces . g etS tri ng (R. s t r i n g . s h are e m a il s u b jec t ) ) ; em ail Intent . setType (” message/ r fc822 ” ) ; PackageManager pm = getPackageManager ( ) ; Intent sendIntent = new Intent ( Intent .ACTION SEND) ; sendIntent . setType (” text / plai n ” ) ; Intent openInChooser = Intent . createChooser ( emailIntent , r eso u rces . g etS tri ng (R. s t r i n g . s h are c h o oser t e x t ) ) ; List <ResolveInfo>r e s I n f o = pm. q u ery Int ent Act ivi ti es ( sendIntent , 0 ) ; List <LabeledIntent>i n t e n t L i s t = new ArrayList < >(); fo r ( int i = 0; i <r e s I n f o . s i z e ( ) ; i++) { Resolve Info r i = r e s I n f o . get ( i ) ; String packageName = r i . a c t i v i t y I n f o . packageName ; i f ( packageName . contains (” android . email ”)) { em ailInte nt . setPackage ( packageName ) ; }e l s e i f ( packageName . contains (” tw itter ”) | | packageName . contains (” facebook ”) | | packageName . contains (”mms”) | | packageName . contains (” android .gm”)) { 45 4.2. APLICACI´ ON PARA DISPOSITIVOS ANDROID. Intent intent = new Intent ( ) ; intent . setComponent (new ComponentName( packageName , r i . a c t i v i t y I n f o . name ) ) ; intent . setAction ( Intent .ACTION SEND) ; inten t . setType (” text / p la in ” ) ; i f ( packageName . contains (” t w itt er ”)) { intent . putExtra ( Intent .EXTRA TEXT, r esour c es . g etSt rin g (R. s t r i n g . s h a r e t w i t t e r ) ) ; }e l s e i f ( packageName . contains (” facebook ”)) { intent . putExtra ( Intent .EXTRA TEXT, r eso u rces . g etS tri ng (R. s t r i n g . share f acebook ) ) ; }e l s e i f ( packageName . contains (” android .gm”)) { intent . putExtra ( Intent .EXTRA TEXT, Html . fromHtml ( resources . g et St ri ng ( R. s t r i n g . sha re e ma il g ma il ) ) ) ; intent . putExtra ( Intent .EXTRA SUBJECT, resources . getString ( R. s t r i n g . s h ar e e m ai l s u bj ect ) ) ; inten t . setType (” message / rfc 82 2 ” ) ; } i n t e n t L i s t . add (new LabeledIntent ( intent , packageName , r i . loadLabel (pm) , r i . icon ) ) ; } } LabeledIntent [ ] e xtr a In t ent s = i n t e n t L i s t . toArray (new LabeledIntent [ i n t e n t L i s t . s i z e ( ) ] ) ; openInChooser . putExtra ( Intent . EXTRA INITIAL INTENTS, extraIntents ); return openInChooser ; } private c l a s s UploadTask extends AsyncTask <String , Integer , Void>{ private Context context ; public UploadTask ( Context context ) { t h i s . context = context ; } @Override protected Void doInBackground ( String . . . params ) { JSONObject jsonObject = new JSONObject ( ) ; 46 CAP´ ITULO 4. DESARROLLO E IMPLEMENTACI´ ON DEL PROYECTO. JSONObject jsonArray = new JSONObject ( ) ; JSONObject jsonRequest = new JSONObject ( ) ; try { jsonObject . put (” value ” , params [ 0 ] ) ; jsonObject . put (” l o c a l i z a t i o n ” , params [ 1 ] ) ; jsonArray . put (” marker ” , jsonObject ) ; jsonRequest = new JSONObject ( jsonArray . toString ( ) ) ; }catch (JSONException e) { Log . e (” JSONException ” , e . getMessage ( ) ) ; }catch (NullPointerException e) { Log . e (” NullPointerException ” , e . getMessage ( ) ) ; } f i n a l String url = ” http : //150. 2 1 4.108.9 1 : 8000”; JsonObjectRequest req = new JsonObjectRequest ( Request . Method .POST, url , jsonRequest , new Response . Listener <JSONObject>() { @Override public void onResponse ( JSONObject response ) { try { VolleyLog . v(” Response: %n %s ” , response . toString ( 4 ) ) ; }catch (JSONException e) { e . printStackTrace ( ) ; } } }, new Response . ErrorListener () { @Override public void onErrorResponse ( VolleyError er r o r ) { VolleyLog . e (” Error : ” , erro r . getMessage ( ) ) ; } }) ; req . setTag (TAG) ; mRequestQueue . add ( req ) ; return null ; } } private c l a s s ChooserTask extends AsyncTask <Void , Void , Intent>{ 47 4.2. APLICACI´ ON PARA DISPOSITIVOS ANDROID. @Override protected Intent doInBackground ( Void . . . params ) { return generateIntent ( ) ; } @Override protected void onPostExecute ( Intent intent ) { setOpenChooser( intent ); } } } RecordActivity: public c l a s s RecordActivity extends AppCompatActivity { private s t a t i c f i n a l i nt MY MSG = 1; private s t a t i c f i n a l i nt ERROR MSG = −1; private SplEngine mEngine ; private Button start , stop , enviar ; private boolean stopped = f a l s e ; private double amplitude = −1; //Umbral public Handler mHandle = new Handler () { @Override public void handleMessage ( Message msg) { switch (msg . what) { case MY MSG: amplitude = ( double ) msg . obj ; break ; case ERROR MSG: break ; default : super . handleMessage (msg ) ; break ; } } }; @Override protected void onCreate ( Bundle savedInstanceState ) { super . onCreate ( savedInstanceState ) ; setContentView (R. layout . a c t i v i t y r e c o r d ) ; s t a r t = ( Button ) findViewById (R. id . btn grabar ) ; stop = ( Button ) findViewById (R. id . btn prueba ) ; enviar = ( Button ) findViewById (R. id . btn enviar ) ; stop . setEnabled ( f a l s e ) ; 48 CAP´ ITULO 4. DESARROLLO E IMPLEMENTACI´ ON DEL PROYECTO. stop . getBackground ( ) . s e t C o l o r F i l t e r ( Color .GRAY, PorterDuff . Mode .MULTIPLY) ; enviar . setEnabled ( f a l s e ) ; enviar . getBackground ( ) . s e t C o l o r F i l t e r ( Color .GRAY, PorterDuff . Mode .MULTIPLY) ; mEngine = new SplEngine ( t h i s . mHandle , RecordActivity . t h i s ) ; } @Override public void onBackPressed () { f i n i s h ( ) ; } public void s t a r t ( View view ) { i f ( ! stopped ) { mEngine . s t a r t e n g i n e ( ) ; s t a r t . setEnabled ( f a l s e ) ; s t a r t . getBackground ( ) . s e t C o l o r F i l t e r ( Color .GRAY, PorterDuff . Mode .MULTIPLY) ; stop . setEnabled ( true ) ; Log . i ( t h i s . t oSt ri ng ( ) , ” Recording s tarte d ” ) ; }e l s e { Toast . makeText( RecordActivity . this , ”Para grabar otro audio salga y vuelva a entrar en la pantalla ” , Toast .LENGTH SHORT) . show ( ) ; } } public void stop (View view ) { stopped = true ; amplitude = mEngine . getMedian ( ) ; mEngine . stop engine ( ) ; stop . setEnabled ( f a l s e ) ; stop . getBackground ( ) . s e t C o l o r F i l t e r ( Color .GRAY, PorterDuff . Mode .MULTIPLY) ; s t a r t . setEnabled ( true ) ; s t a rt . getBackground ( ) . c l e a r C o l o r F i l t e r ( ) ; enviar . setEnabled ( true ) ; enviar . getBackground ( ) . c l e a r C o l o r F i l t e r ( ) ; Log . i ( t h i s . t oSt ri ng ( ) , ”Value : ” + amplitude ) ; 49 4.2. APLICACI´ ON PARA DISPOSITIVOS ANDROID. } public void send (View view ) { showAlert ( ) ; } private void showAlert () { f i n a l AlertDialog . Builder builder = new AlertDialog . Builder ( t h i s ) ; builde r . setMessage (” Nivel de ruido : ”+ amplitude+ ” dB”) . s e t T i t l e (” Enviar audio ”) . setCancelable ( f a l s e ) . setPositiveButton (” Si ” , new DialogInte r f a c e . OnClickListener () { public void onClick ( @SuppressWarnings(”unused”) f i n a l D ialogInterface dialog , @SuppressWarnings (” unused ”) f i n a l i n t id ) { Intent intent = new Intent ( ) ; intent . putExtra (” value ” , amplitude ) ; setResult (1 , i ntent ) ; f i n i s h ( ) ; } }) . setNegativeButton(”No”, new DialogInte r f a c e . OnClickListener () { public void onClick ( f i n a l D ialogInterface dialog , @SuppressWarnings (” unused ”) f i n a l i n t id ) { dialog . cancel ( ) ; } }) ; f i n a l AlertDialog a l e r t = builde r . create ( ) ; a l e r t . show ( ) ; } } NoiseActivity: public c l a s s NoiseActivity extends FragmentActivity implements OnMapReadyCallback { private s t a t i c f i n a l String TAG = ” NoiseActivity ”; private GoogleMap mMap; 50 CAP´ ITULO 4. DESARROLLO E IMPLEMENTACI´ ON DEL PROYECTO. private LocationManager mLocationManager ; private List <Marker>mMarkerList ; private int mCounter = 0; private List <String>mStringMarkerList ; private RequestQueue mRequestQueue ; @Override protected void onCreate ( Bundle savedInstanceState ) { super . onCreate ( savedInstanceState ) ; mStringMarkerList = new ArrayList < >(); mMarkerList = new ArrayList < >(); MarkerTask markerTask = new MarkerTask (this . getApplicationContext ()); markerTask . execute ( ) ; mRequestQueue = Volley . newRequestQueue (getApplicationContext ()); mLocationManager = ( LocationManager ) getApplicationContext (). getSystemService (LOCATION SERVICE) ; setContentView (R. layout . a c t i v i t y n o i s e ) ; FragmentManager fManager = getSupportFragmentManager ( ) ; Fragment fragment = fManager . findFragmentById (R. id . mapview ) ; SupportMapFragment mapFragment = ( SupportMapFragment ) fragment ; mapFragment . getMapAsync ( t h i s ) ; } @Override public void onMapReady(GoogleMap googleMap ) { mMap = googleMap ; mMap. setOnMarkerClickListener (new GoogleMap . OnMarkerClickListener () { @Override public boolean onMarkerClick ( Marker marker ) { mMap. moveCamera( CameraUpdateFactory . newLatLngZoom( marker . getP osi tion ( ) , 1 5 ) ) ; mMap. animateCamera ( CameraUpdateFactory . zoomIn ( ) ) ; mMap. animateCamera ( CameraUpdateFactory . zoomTo(15) , 2000 , null ) ; marker . showInfoWindow ( ) ; return f a l s e ; } }) ; 51 4.2. APLICACI´ ON PARA DISPOSITIVOS ANDROID. fo r ( String s : mStringMarkerList ) { String [ ] s p l i t t e d = s . s p l i t ( ” ; ” ) ; String [ ] la tl ng = s p l i t t e d [ 1 ] . s p l i t ( ” , ”) ; LatLng stringLatLng = new LatLng ( Double . valueOf ( l a t l n g [ 0 ] ) , Double . valueOf ( l a t l n g [ 1 ] ) ) ; Marker stringMarker = mMap. addMarker (new MarkerOptions ( ) . pos i t ion ( stringLatLng ) . t i t l e (” Nivel de ruido :” + s p l i t t e d [ 0 ] ) . icon ( BitmapDescriptorFactory . fromResource (R. drawable . ic image ) ) ) ; mMarkerList . add( stringMarker ) ; } moveCamera( mMarkerList . get ( 0 ) ) ; } public void onClickFocus ( View view ) { try { List <String>providers = mLocationManager . getProviders ( true ) ; Location bestLocation = nul l ; fo r ( String provider : providers ) { Location l = mLocationManager . getLastKnownLocation ( provider ) ; i f ( l == n u l l ) { continue ; } i f ( bestLocation == n ull | | l . getAccuracy() <bestLocation . getAccuracy ()) { bestLocation = l ; } } i f ( bestLocation == n ull ) { C r i t e r i a c r i t e r i a = new C r i t e r i a ( ) ; c r i t e r i a . setAccuracy ( C ri te r ia .ACCURACY FINE) ; c r i t e r i a . setPowerRequirement ( C r it er i a . POWER HIGH) ; Locat io nLis te ner lL = l o c a t i o n L i s t e n e r ; String provider = mLocationManager . getBestProvider ( c r i t e r i a , true ) ; mLocationManager . requestLocationUpdates ( provider , 0 , 0 , lL , 52 CAP´ ITULO 4. DESARROLLO E IMPLEMENTACI´ ON DEL PROYECTO. getMainLooper ()); bestLocation = mLocationManager . getLastKnownLocation ( LocationManager .GPS PROVIDER) ; } i f ( bestLocation != n u l l ) { LatLng newLatLng = new LatLng ( bestLocation . getLatitude () , bestLocation . getLongitude ( ) ) ; Marker actualLocation = mMap. addMarker (new MarkerOptions ( ) . p ositi o n (newLatLng ) . t i t l e (” Usted esta aqui ” ) . snippet (” Ultima l o c a l i z a c i o n conocida ” ) . icon ( BitmapDescriptorFactory . fromResource ( R. drawable . i c l o c a l i z a r ) ) ) ; actualLocation . showInfoWindow ( ) ; mMap. moveCamera( CameraUpdateFactory . newLatLng (newLatLng ) ) ; }e l s e { Toast . makeText( NoiseActivity . this , ” Su d is p os i ti v o no ti e ne l o c a l i z a c i o n e s en cache ” , Toast .LENGTH SHORT) . show ( ) ; Log . e (” NoiseActivity ” , ”No hay l o c a l i z a c i o n e s en cache ” ) ; } }catch (SecurityException e) { Log . e (” SecurityException ” , e . getLocalizedMessage ( ) ) ; }catch (NullPointerException ex) { Log.e(”NullPointerException”, ex . getLocalizedMessage ( ) ) ; } } public void onClickNext (View view ) { int next = mCounter % mMarkerList . s i z e ( ) ; i f ( next <mMarkerList . s i z e ( ) ) { moveCamera( next ) ; mCounter++; } } public void moveCamera( i nt next ) { Marker next marker = mMarkerList . get ( next ) ; 53 4.2. APLICACI´ ON PARA DISPOSITIVOS ANDROID. mMap. moveCamera( CameraUpdateFactory . newLatLngZoom( next marker . g et Posi tio n ( ) , 1 5 ) ) ; mMap. animateCamera ( CameraUpdateFactory . zoomIn ( ) ) ; mMap. animateCamera ( CameraUpdateFactory . zoomTo (15) , 2000 , n u l l ) ; next marker . showInfoWindow ( ) ; } public void moveCamera( Marker marker ) { mMap. moveCamera( CameraUpdateFactory . newLatLngZoom( marker . getP osi tion ( ) , 1 5 ) ) ; mMap. animateCamera ( CameraUpdateFactory . zoomIn ( ) ) ; mMap. animateCamera ( CameraUpdateFactory . zoomTo (15) , 2000 , n u l l ) ; marker . showInfoWindow ( ) ; } private c l a s s MarkerTask extends AsyncTask <Void , Integer , Void>{ Context context ; public MarkerTask ( Context context ) { t h i s . context = context ; } @Override protected Void doInBackground ( Void . . . params ) { f i n a l String url = ” http : //150. 2 1 4.108.9 1 : 8000”; JsonArrayRequest req = new JsonArrayRequest ( url , new Response . Listener <JSONArray>() { @Override public void onResponse ( JSONArray response ) { try { fo r ( int i =0; i<response . length ( ) ; i++) { JSONObject marker = (JSONObject) response . get ( i ) ; String toAdd = marker . get String (” value ”) +”;”+marker . getString (”localization ”); mStringMarkerList . add(toAdd ) ; } }catch (JSONException e) { Log . e ( e . toString ( ) , 54 Cap´ıtulo 5 Conclusiones y trabajo futuro. 5.1. Conclusiones El desarrollo de un trabajo de fin de grado con las caracter´ısticas de este da para muchas conclusiones y an´ecdotas para futuros trabajos. Algunas de estas conclusiones est´an mas relacionadas con mi inter´es personal a la hora de hacer desarrollos y otras con cuestiones mas t´ecnicas. 5.1.1. Mi opini´on sobre el desarrollo en Android Aunque previamente ya hab´ıa hecho algunos peque˜nos desarrollos en Android, esta ha sido la primera vez que me he enfrentado a un desarrollo mas importante para la plataforma. Teniendo claro desde el momento en el que escrib´ı el anteproyecto que, dados mis conocimientos en ese momento, apenas conoc´ıa que herramientas y m´etodos podr´ıan serme ´utiles, empec´e a formarme en partes mas avanzadas del desarrollo en Android: manejo mas avanzado de threads, el uso de una nueva API para las conexiones a Internet (antes hab´ıa utilizado la de Apache), etc´etera. Otra parte importante del desarrollo surgi´o a mitad del mismo. En un principio yo hab´ıa considerado la opci´on de que, a la hora de subir un audio al servidor, el usuario tambi´en pudiese escoger un audio previamente grabado. El problema que encontr´e fue que no hab´ıa manera viable de poder sacar la media del nivel de ruido dentro de la aplicaci´on en un audio grabado sin cargar mas horas al proyecto o tener que utilizar software privativo. El balance al finalizar el proyecto es bastante positivo, puesto que he utilizado conceptos del desarrollo de Android bastante interesantes de cara al mercado laboral, pero tambi´en ha sido interesante para ganar conocimientos sobre este mundo. Uno de los problemas relacionados con este desarrollo fue a la hora de debuggear la aplicaci´on. Para hacer esto hay dos principales opciones: sobre un dispositivo f´ısico y 61 5.1. CONCLUSIONES sobre una m´aquina virtual. Para otras aplicaciones personalmente habr´ıa trabajado con una m´aquina virtual de Genymotion, que corre sobre Oracle VirtualBox, sin embargo, no permite el uso de micr´ofonos, lo cual hace imposible que pruebe el 100 % de mi aplicaci´on de esa forma, teniendo que escoger por tanto probar en un dispositivo f´ısico, concretamente en mi tel´efono con Android 5.1. 5.1.2. Mi opini´on sobre el desarrollo para Waspmote Los dos principales problemas que me he encontrado a la hora de desarrollar el sketch han sido: La falta de soporte para las placas, que solo tienen soporte en el foro oficial, donde rara vez la ayuda que se da por parte de los moderadores es ´util. Ante cualquier obst´aculo u problema que me encontrase durante el desarrollo, las primeras soluciones siempre eran relacionadas con Arduino y dichos problemas hab´ıan sido ya subsanados en esa plataforma. La versi´on del compilador de la placa es bastante anticuada, provocando que los sketchs tarden en compilar bastante, lo cual hace que se pierda mas tiempo porque solo detecta un fallo por cada compilaci´on y no varios. Tras resolver dichos problemas, he podido ver que el desarrollo para estas motas es bastante mas r´apido que para Arduino y mucho mas liviano, teniendo en cuenta cosas como que el tama˜no de los a˜nadidos para conectividad WiFi en Arduino es un shield casi mas grande que el propio Arduino y en Waspmote es un peque˜no a˜nadido que va en una esquina. La programaci´on para la mota tambi´en sufre al tener una versi´on antigua del compilador, como coment´e anteriormente sobre el uso de una funci´on. Sin embargo, no se necesitar´ıa tener conocimientos previos de C en la mayor´ıa de los casos de la mota, puesto que la bibliograf´ıa ayuda mucho a la hora de crear los sketchs. 5.1.3. An´alisis de los resultados Se han cubierto las siguientes funcionalidades de las propuestas en el anteproyecto: Despliegue de sensores que recojan los niveles de ruido y los env´ıen a un servidor. Desarrollo de una aplicaci´on para dispositivos Android que pueda realizar: •Ver los niveles de ruido de las zonas donde hay informaci´on. •Poder enviar informaci´on sobre el nivel de ruido de una zona. Se han a˜nadido las siguientes funcionalidades extra: 62 CAP´ ITULO 5. CONCLUSIONES Y TRABAJO FUTURO. Poder ver los puntos sobre los que hay informaci´on uno detr´as de otro, como una lista. Bot´on para compartir con aplicaciones de redes sociales y mensajer´ıa instant´anea que se est´a usando la aplicaci´on. Las siguientes funcionalidades no se han podido cubrir: Usar el dispositivo del usuario a modo de pasarela para las placas, que al final utilizan una conexi´on WiFi propia por dificultades para la integraci´on con dispositivos Android que se explican mas adelante. Ver hist´orico de los datos, que no se ha implementado debido a que, a medida que avanzaba el desarrollo de la aplicaci´on, no le ve´ıa inter´es a que el usuario final pudiese ver el hist´orico de datos, puesto que es algo que no le es ´util. La aplicaci´on se comporta como se espera: los mensajes llegan al servidor perfectamente y sin ning´un problema relacionado con los puertos o la conexi´on. Hubo que realizar una calibraci´on en la grabadora para que comenzara a grabar desde justo el momento que se le da a grabar, puesto que si no se hac´ıa dicha calibraci´on podr´ıa no recoger informaci´on y dar como resultado un valor nulo. 5.2. Trabajo futuro. Si este desarrollo se ampliase o modificase en un futuro, ser´ıa conveniente tener en cuenta los siguientes aspectos: Portar todo el desarrollo, o parte del mismo, a Kotlin: Kotlin es el futuro para el desarrollo de aplicaciones en Android, dandose incluso el caso de que Google lo est´a considerando, junto a otros lenguajes, como sustituto de Java. Poco a poco, son muchas las personas que van descubriendo las bondades de Kotlin, como por ejemplo: •Conciso: Se necesitan muchas menos l´ıneas de c´odigo para muchas tareas, comparandolo con Java. Por ejemplo, para conseguir la cantidad de n´umeros positivos en una lista, en Kotlin se har´ıa tal que as´ı: val positiveNumbers = l i s t . f i l t e r {i t >0} o para hacer una AsyncTask, con la librer´ıa de Anko, que suele acompa˜nar muchos desarrollos en Kotlin, queda as´ı: async () { // Do something in a secondary thread uiThread { 63 5.2. TRABAJO FUTURO. // Back to the main thread } } •Programaci´on funcional: Si bien la ´ultima versi´on de Android, Android N, si tiene las funciones lambda, con Kotlin es posible incluirlas, junto con todo el paradigma de la programaci´on funcional, para las versiones anteriores, siendo algo que ayuda mucho a la hora de escribir menos c´odigo. •Seguro: Se pueden evitar much´ısimos tipos de errores, sobretodo los relacionados con las referencias nulas. Por ejemplo, con el uso del operador ?:, conocido como el operador Elvis, podemos hacer cosas as´ı, que evitan las referencias nulas. //maybe es un String que puede ser nulo val name : String = maybe ?: ” stranger ” pr i n tln (” Hello $name”) •Versatilidad: Kotlin, aparte de en Android, puede funcionar principalmente en aplicaciones del lado del servidor, como es el caso de la web de presentaciones Prezi, o en el front-end de un navegador, haciendo que lo que se aprenda de Kotlin no se considere del todo in´util al cambiar de ´area de desarrollo. •Interoperabilidad: Funciona perfectamente con la m´aquina virtual de Java y con otros frameworks. Portar la aplicaci´on a Android Wear: Pensado para casi cualquier tipo de wearables, Android Wear es un sistema operativo basado en Android que responde a las necesidades y limitaciones de estos dispositivos. Aunque por ahora no hay muchos dispositivos a la venta de esta familia, podr´ıa ser interesante el desarrollo para estos dispositivos. No habr´ıa que cambiar mucho en la aplicaci´on, tan solo adaptar temas de resoluci´on, puesto que todo el c´odigo utilizado en la aplicaci´on de este proyecto es compatible en Android Wear, teniendo que incluir tan solo en el archivo Gradle la linea de las librer´ıas de Android Wear. Mejorar la experiencia en tablets: Si bien la aplicaci´on funciona perfectamente en las mismas, estar´ıa bien retocar un poco las vistas para resoluciones mas propias de tablets, pudiendo adoptarlas mejor a su funcionamiento. Portar la aplicaci´on a iOS: Si bien con Android cubrimos la mayor parte del mercado de dispositivos m´oviles como se coment´o anteriormente, portando la aplicaci´on a iOS terminar´ıamos de cubrir el mercado, quedando una parte casi despreciable sin cubrir. Para poder desarrollar aplicaciones para el sistema necesitamos principalmente unirnos al Apple Developer Program, donde se nos 64 CAP´ ITULO 5. CONCLUSIONES Y TRABAJO FUTURO. indicar´an todos los pasos para poder lanzar las aplicaciones, pudiendo realizar el desarrollo en Objective-C, Swift, o alg´un lenguaje multiplataforma. Portar el c´odigo a Xamarin: En la linea de lo mencionado anteriormente, Xamarin permitir´ıa sacar la aplicaci´on para Android, iOS y Windows Mobile partiendo del mismo c´odigo. En este supuesto nos ahorrar´ıamos de mantener 2 o 3 c´odigos distintos, ahorrando un tiempo que podr´ıa valer en introducir optimizaciones del funcionamiento general. Utilizar la informaci´on recogida: Si bien la informaci´on recogida se almacena en un servidor que yo no he desarrollado, si considero interesante que esta informaci´on se pueda utilizar para mas prop´ositos. Algo interesante para lo que se podr´ıan usar estos datos es el Big Data. El Big Data hace referencia a una cantidad de datos tal que supera la capacidad del software tradicional para ser capturados, administrados y procesados. Si bien al principio los datos que se nos presentan no se acercan a esta descripci´on, con el paso del tiempo se podr´ıa acabar generar tal volumen de informaci´on que ser´ıa interesante utilizar las t´ecnicas mas asociadas al Big Data para analizar dicha informaci´on. En un supuesto de desplegar este proyecto en sitios de la ciudad, se podr´ıa acabar estudiando las zonas mas ruidosas y dando estad´ısticas de ruido que puedan ayudar a la Administraci´on P´ublica, por ejemplo, si hubiera problemas con los vecinos en esas zonas. 65 5.2. TRABAJO FUTURO. 66 Cap´ıtulo 6 Ap´endice. 6.1. Lista de acr´onimos API: Application Programming Interface EEPROM: Electrically Erasable Programmable Read-Only Memory ext4: fourth extended filesystem GPL: General Public License GPS: Global Positioning System HTTP: Hypertext Transfer Protocol IDE: Integrated Development Environment JIT: Just In Time JSON: JavaScript Object Notation NFC: Near Field Communication REST: Representational State Transfer RTC: Real Time Clock SRAM: Static Random Access Memory WEP: Wired Equivalent Privacy WPA: Wi-Fi Protected Access XML: eXtensible Markup Language YAFFS: Yet Another Flash File System 6.2. Manual de usuario y capturas de pantalla. 6.2.1. Aplicaci´on para dispositivos Android. La aplicaci´on no est´a subida en Play Google, as´ı que para instalarla es necesario tener acceso al archivo .apk de la misma. Para poder instalarla es necesario activar la opci´on de instalar aplicaciones de or´ıgenes desconocidos, que se encuentra en el apartado de seguridad de los ajustes. En el mapa podemos ver los puntos sobre los que hay informaci´on. 67 6.2. MANUAL DE USUARIO Y CAPTURAS DE PANTALLA. Tambi´en podemos pulsar en el bot´on de la esquina superior izquierda para ir al siguiente punto del que haya informaci´on. Con el bot´on de la esquina superior derecha te ense˜na donde te encuentras, siempre y cuando el GPS tenga informaci´on actualizada. Figura 6.1: Punto donde se han realizado pruebas de sonido. Figura 6.2: Localizaci´on actual. Esta es la pantalla de la grabadora, con un funcionamiento ya explicado anteriormente. 68 CAP´ ITULO 6. AP´ ENDICE. Figura 6.3: Estado inicial de la grabadora. Figura 6.4: Grabando. 69 6.2. MANUAL DE USUARIO Y CAPTURAS DE PANTALLA. Figura 6.5: Prueba de env´ıo de audio. Cuando se pulsa el bot´on de compartir se puede elegir ciertas aplicaciones con las que compartir que se est´a usando la aplicaci´on. Figura 6.6: Escogiendo que aplicaci´on usar para compartir informaci´on 6.2.2. Sketch para Waspmote. Para poder utilizar la placa en Windows no es necesario instalar ning´un driver especial. Para poder lanzar el c´odigo es necesario bajarse el IDE propio de Libelium, pudiendo dar problemas si se usa otro. Primero debe compilarse el c´odigo y luego cargarse a la placa. 70