3 Tecnologías utilizadasbibing.us.es/proyectos/abreproy/12108/fichero/3_tecnologias_utiliza… ·...

53
14 iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y base de datos de información 3 Tecnologías utilizadas 3.1 Android Es un sistema operativo basado en Linux diseñado para dispositivos móviles táctiles. Fue inicialmente desarrollado por la Android Inc., la cual Google financió hasta que la compró en 2005. Android fue presentado en 2007 junto con la Open Handset Alliance, un consorcio de empresas liderada por Google. Es utilizado por cientos de millones de teléfonos en más de 190 países. Es la plataforma más extendida y con un crecimiento más rápido, cada día un millón de usuarios activan dispositivos Android por primera vez. Ilustración 1: Activaciones Android en los últimos años Android es de código abierto (“open source”) y Google libera el código bajo la licencia Apache. Este modelo de licencia de software permite que pueda ser modificado y distribuido libremente por fabricantes, operadores o desarrolladores. La interfaz de usuario de Android se basa en control táctil mediante gestos similares a los usados en el mundo real como tocar, pellizcar, deslizar, etc. La respuesta a los gestos del usuario está diseñada para que sea inmediata y proporcione una experiencia fluida. El sistema también proporciona soporte para hardware interno adicional como acelerómetros, giroscopios y sensores de proximidad que son usados por las aplicaciones para responder a distintas interacciones con el usuario, como por ejemplo, ajustar la pantalla de orientación vertical a horizontal. La pantalla principal del sistema Android consiste en iconos y “widgets” (pequeñas aplicaciones en miniatura a modo de iconos extendidos que se actualizan para mostrar contenido como el pronóstico del tiempo o el correo electrónico del usuario). Las aplicaciones de terceros están disponibles a través de “Google Play” (tienda de aplicaciones oficial de Google), aunque existe la posibilidad de que el usuario instale

Transcript of 3 Tecnologías utilizadasbibing.us.es/proyectos/abreproy/12108/fichero/3_tecnologias_utiliza… ·...

14" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

3 Tecnologías utilizadas

3.1 Android

Es un sistema operativo basado en Linux diseñado para dispositivos móviles táctiles. Fue inicialmente desarrollado por la Android Inc., la cual Google financió hasta que la compró en 2005. Android fue presentado en 2007 junto con la Open Handset Alliance, un consorcio de empresas liderada por Google. Es utilizado por cientos de millones de teléfonos en más de 190 países. Es la plataforma más extendida y con un crecimiento más rápido, cada día un millón de usuarios activan dispositivos Android por primera vez.

Ilustración 1: Activaciones Android en los últimos años

Android es de código abierto (“open source”) y Google libera el código bajo la licencia Apache. Este modelo de licencia de software permite que pueda ser modificado y distribuido libremente por fabricantes, operadores o desarrolladores.

La interfaz de usuario de Android se basa en control táctil mediante gestos similares a los usados en el mundo real como tocar, pellizcar, deslizar, etc. La respuesta a los gestos del usuario está diseñada para que sea inmediata y proporcione una experiencia fluida. El sistema también proporciona soporte para hardware interno adicional como acelerómetros, giroscopios y sensores de proximidad que son usados por las aplicaciones para responder a distintas interacciones con el usuario, como por ejemplo, ajustar la pantalla de orientación vertical a horizontal.

La pantalla principal del sistema Android consiste en iconos y “widgets” (pequeñas aplicaciones en miniatura a modo de iconos extendidos que se actualizan para mostrar contenido como el pronóstico del tiempo o el correo electrónico del usuario). Las aplicaciones de terceros están disponibles a través de “Google Play” (tienda de aplicaciones oficial de Google), aunque existe la posibilidad de que el usuario instale

15" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

tiendas de otras empresas, con menor repercusión en Android. Muchos fabricantes y operadores adaptan el aspecto del sistema para diferenciarse de la competencia.

3.1.1 Estructura del sistema operativo

A modo de introducción, cabe comentar que Android consiste en un “kernel” o núcleo del sistema operativo basado en Linux con librerías y APIs (“Application Programming Interface”) escritas en C, aplicaciones software ejecutándose sobre un “framework” (marco de trabajo) de aplicación que incluye librerías compatibles con Java basadas en “Apache Harmony” (una implementación de código abierto de Java desarrollada por la Apache Software Foundation). Android usa la máquina virtual “Dalvik” que mediante una compilación JIT (“Just-In-Time”) ejecuta “dex-code” (ejecutable Dalvik) que normalmente es traducido desde código de máquina virtual Java o “byte code” Java. El hardware principal para Android es la arquitectura ARM, aunque también hay soporte para la arquitectura x86 de Intel.

Pero, para desarrollar aplicaciones en Android es importante conocer cómo está estructurado este sistema operativo. Esto es lo que denominamos arquitectura y en el caso de Android está formada por varias capas que facilitan al desarrollador la creación de aplicaciones. Además, esta distribución permite acceder a las capas más bajas mediante el uso de librerías para que así el desarrollador no tenga que programar a bajo nivel las funcionalidades necesarias para que una aplicación haga uso de los componentes de hardware de los teléfonos.

Cada una de las capas utiliza elementos de la capa inferior para realizar sus funciones, es por ello que a este tipo de arquitectura se le conoce también como pila. Para verlo con más claridad, a continuación se muestra un diagrama de la arquitectura de Android:

Ilustración 2: Diagrama de la arquitectura Android

16" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Desde abajo hacia arriba, estas capas son:

3.1.1.1 Kernel de Linux

Como hemos mencionado anteriormente, el núcleo del sistema operativo Android está basado en el kernel de Linux, en concreto la versión 2.6, de manera similar a cualquier distribución de Linux, como Ubuntu, solo que adaptado a las características del hardware en el que se ejecutará Android, es decir, para dispositivos móviles.

El núcleo actúa como una capa de abstracción entre el hardware y el resto de las capas de la arquitectura. El desarrollador no accede directamente a esta capa, sino que debe utilizar las librerías disponibles en capas superiores, para que de esta forma, no sea necesario conocer las especificaciones exactas de cada teléfono. Por ejemplo, si necesitamos hacer uso de la cámara, el sistema operativo se encarga de utilizar la que incluya el teléfono, sea cual sea. Para cada elemento del hardware del teléfono existe un controlador (o driver) dentro del kernel que permite utilizarlo desde el software.

El kernel también se encarga de gestionar los diferentes recursos del teléfono (energía, memoria, etc.) y del sistema operativo en sí: procesos, elementos de comunicación (networking), etc.

3.1.1.2 Librerías

La siguiente capa que se sitúa justo sobre el kernel la componen las bibliotecas nativas de Android, también llamadas librerías. Están escritas en C o C++ y compiladas para la arquitectura hardware específica del teléfono. Éstas normalmente están hechas por el fabricante, quien también se encarga de instalarlas en el dispositivo antes de ponerlo a la venta. El objetivo de las librerías es proporcionar funcionalidad a las aplicaciones para tareas que se repiten con frecuencia, evitando tener que codificarlas cada vez y garantizando que se llevan a cabo de la forma “más eficiente”.

Entre las librerías incluidas habitualmente encontramos OpenGL (motor gráfico), Bibliotecas multimedia (formatos de audio, imagen y video), Webkit (navegador), SSL (cifrado de comunicaciones), FreeType (fuentes de texto), SQLite (base de datos), entre otras.

3.1.1.3 Entorno de ejecución

Como podemos apreciar en el diagrama, el entorno de ejecución de Android no se considera una capa en sí mismo, dado que también está formado por librerías. Aquí encontramos las librerías con las funcionalidades habituales de Java así como otras específicas de Android.

El componente principal del entorno de ejecución de Android es la máquina virtual Dalvik. Como ya hemos introducido anteriormente, las aplicaciones se codifican en Java y son compiladas en un formato específico para que esta máquina virtual las ejecute. La ventaja de esto es que las aplicaciones se compilan una única vez y de esta forma estarán listas para distribuirse con la total garantía de que podrán ejecutarse en

17" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

cualquier dispositivo Android que disponga de la versión mínima del sistema operativo que requiera la aplicación.

Cabe aclarar que Dalvik es una variación de la máquina virtual de Java, por lo que no es compatible con el “byte code” Java. Java se usa únicamente como lenguaje de programación, y los ejecutables que se generan con el SDK de Android tienen la extensión .dex que es específico para Dalvik, y por ello no podemos correr aplicaciones Java en Android ni viceversa.

3.1.1.4 Framework de aplicaciones

La siguiente capa está formada por todas las clases y servicios que utilizan directamente las aplicaciones para realizar sus funciones. La mayoría de los componentes de esta capa son librerías Java que acceden a los recursos de las capas anteriores a través de la máquina virtual Dalvik. Dentro de esta capa tenemos:

Activity Manager: se encarga de administrar la pila de actividades de nuestra aplicación así como su ciclo de vida. Una actividad (“activity”) representa una pantalla con una interfaz de usuario. Aunque las actividades trabajen juntas para formar una experiencia de usuario completa, cada una es independiente de las otras.

Windows Manager: se encarga de organizar lo que se mostrará en pantalla. Básicamente crea las superficies en la pantalla que posteriormente pasarán a ser ocupadas por las actividades.

Content Providers: un proveedor de contenido gestiona un conjunto de datos de aplicación compartidos. Se pueden almacenar los datos en un archivo del sistema, en una base de datos SQLite, en la web, o en cualquier otro sistema de archivos persistente que la aplicación pueda acceder.

View System: son los elementos que nos ayudarán a construir las interfaces de usuario: botones, cuadros de texto, listas y hasta elementos más avanzados como un navegador web o un visor de Google Maps.

Notification Manager: engloba los servicios para notificar al usuario cuando algo requiera su atención mostrando alertas en la barra de estado.

Package Manager: esta biblioteca permite obtener información sobre los paquetes instalados en el dispositivo Android, además de gestionar la instalación de nuevos paquetes. Con paquete nos referimos a la forma en que se distribuyen las aplicaciones Android, estos contienen el archivo .apk, que a su vez incluyen los archivos .dex con todos los recursos y archivos adicionales que necesite la aplicación, para facilitar su descarga e instalación.

Telephony Manager: con esta librería podremos realizar llamadas o enviar y recibir SMS/MMS, aunque no permite reemplazar o eliminar la actividad que se muestra cuando una llamada está en curso.

18" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Resource Manager: es útil para gestionar todos los elementos que forman parte de la aplicación y que están fuera del código, es decir, cadenas de texto traducidas a diferentes idiomas, imágenes, sonidos o “layouts” (un layout define la estructura visual de una interfaz, como la interfaz de usuario de una actividad o de un widget).

Location Manager: permite determinar la posición geográfica del dispositivo Android mediante GPS o redes disponibles y trabajar con mapas.

Sensor Manager: nos permite manipular los elementos de hardware del teléfono como el acelerómetro, giroscopio, sensor de luminosidad, sensor de campo magnético, brújula, sensor de presión, sensor de proximidad, sensor de temperatura, etc.

XMPP Service: maneja el protocolo de intercambio de mensajes basados en XML.

3.1.1.5 Aplicaciones

En la última capa se incluyen todas las aplicaciones del dispositivo, tanto las que tienen interfaz de usuario como las que no, las nativas (programadas en C o C++) y las administradas (programadas en Java), las que vienen preinstaladas en el dispositivo y aquellas que el usuario ha instalado.

En esta capa encontramos también la aplicación principal del sistema: Inicio (Home) o lanzador (“launcher”), porque es la que permite ejecutar otras aplicaciones mediante una lista y mostrando diferentes escritorios donde se pueden colocar accesos directos a aplicaciones o incluso widgets, que son también aplicaciones de esta capa.

3.1.2 Fundamentos de las aplicaciones

Las aplicaciones Android están escritas en Java y las herramientas del SDK de Android permiten compilar el código junto con todos los datos y recursos necesarios para generar un paquete Android. Este paquete es una archivo de extensión .apk donde se encuentra todo lo necesario para ejecutar la aplicación.

Una vez instalada la aplicación en el dispositivo, ésta reside en su propia “sandbox” que sirve para aislar el proceso de la aplicación como medida de seguridad. Por defecto, cada aplicación ejecuta sus propios procesos de Linux. Android inicia el proceso cuando algunos de sus componentes de aplicación necesita ser ejecutado, y luego se cierra el proceso cuando ya no es necesario o cuando el sistema necesita liberar memoria para otras aplicaciones.

De esta manera, el sistema implementa el principio del menor privilegio. Esto es, que cada aplicación, por defecto, sólo tiene acceso a los componentes que necesita para hacer su trabajo y nada más. Esto crea un entorno seguro en el que una aplicación no puede acceder a partes del sistema para las cuales no tiene permisos.

19" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Sin embargo, hay formas de que una aplicación comparta datos con otras aplicaciones o que una aplicación acceda a los servicios del sistema, y esto es lo que se va a comentar en los siguientes puntos.

3.1.2.1 Componentes de una aplicación

Las aplicaciones Android se construyen mediante bloques de componentes, cada uno de los cuales existe como una entidad propia y desempeña un papel específico. Cada elemento es una pieza única que ayuda a definir el comportamiento general de la aplicación.

Hay cuatro tipos de componentes en una aplicación Android. Cada uno de ellos tiene un propósito y un ciclo de vida distinto que define cómo se crea y se destruye el componente.

Activities (actividades): es el bloque encargado de construir la interfaz de usuario. Por ejemplo, una aplicación de correo puede tener una actividad que muestre una lista de nuevos correos, otra actividad para redactar un correo y otra más para leer correos. Aunque las actividades trabajan juntas para formar una experiencia de usuario coherente en la aplicación de correo, cada una de ellas es independiente de las otras. De tal manera que, una aplicación diferente puede iniciar cualquiera de las actividades anteriores por separado.

Services (servicios): un servicio es un componente que se ejecuta en segundo plano para realizar una tarea duradera o para realizar un trabajo para un proceso remoto. Los servicios no disponen de interfaz de usuario. Por ejemplo, un reproductor de música en segundo plano mientras el usuario usa otra aplicación. Otro componente, como una actividad, puede iniciar un servicio y dejarlo correr o bien conectarse al mismo para interactuar con él.

Content providers (proveedores de contenido): un proveedor de contenido gestiona un conjunto de datos de aplicación. Se pueden almacenar los datos en el sistema de archivos, en una base de datos SQLite, en la web, o en cualquier otro sistema de almacenamiento persistente que la aplicación pueda acceder. A través del proveedor de contenido, otras aplicaciones pueden consultar o incluso modificar los datos (si el proveedor de contenidos lo permite). Los proveedores de contenido también son útiles para leer y escribir datos que son privados a nuestra aplicación y no se comparten.

Broadcast receivers (receptores de difusión): un receptor de difusión es un componente que responde a un anuncio de difusión del sistema. Por ejemplo, un anuncio de que la pantalla se ha apagado, que queda poca batería, o que se ha tomado una foto. Las aplicaciones también pueden iniciar difusiones, por ejemplo, para hacer saber a otras aplicaciones que se han descargado unos datos y están disponibles. Los receptores de difusión no tienen interfaz de usuario, pero pueden crear notificaciones de la barra de estado para alertar al usuario cuando ocurra un evento.

Un aspecto único y útil del diseño del sistema operativo Android es que cualquier aplicación puede hacer uso de otro componente de otra aplicación. Por ejemplo, si nuestra aplicación requiere que el usuario tome una fotografía con la cámara del teléfono, es probable que exista otra aplicación que haga exactamente eso, por lo que

20" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

resultará más fácil reutilizar esa función que programar una específica en nuestra aplicación. Para ello no es necesario incluir o vincular el código de la aplicación de la cámara, simplemente hará falta iniciar la actividad que se encargue de capturar la foto. Una vez hecho, la foto estará disponible para usarla en nuestra aplicación. Para el usuario parecerá que la cámara de su teléfono es una parte de la aplicación.

Debido a que el sistema Android ejecuta cada una de las aplicaciones en un proceso separado con permisos de archivo restringidos a otras aplicaciones, una aplicación no puede activar de forma directa un componente de otra aplicación. El único que lo puede hacer es el sistema operativo en sí. Por lo tanto, para activar un componente en otra aplicación, es necesario enviar un mensaje al sistema que especifique un “intent” (intención) para iniciar un componente concreto.

Intents (intenciones): tres de los cuatro componentes, actividades, servicios y receptores de difusión, son activados por un mensaje asíncrono denominado “intent”. Los intents conectan los componentes individuales entre sí en tiempo de ejecución. Un intent es creado mediante un objeto Intent que define un mensaje para activar un componente específico o un tipo específico de componente. Para las actividades y los servicios, un intent define una acción a ejecutar y puede especificar la dirección URI (Uniform Resource Identifier) de los datos sobre los que actuar. Por ejemplo, un intent puede realizar una petición sobre una actividad para recibir un resultado, en cuyo caso, la actividad también devuelve el resultado en un Intent.

3.1.2.2 El archivo Manifest

Antes de que el sistema Android pueda iniciar un componente de aplicación, el sistema debe saber si el componente existe leyendo el archivo Manifest de la aplicación, esto es, un archivo “AndroidManifest.xml” donde nuestra aplicación debe declarar todos sus componentes y que debe encontrarse en la raíz del directorio del proyecto al crear la aplicación.

El archivo manifest hace una serie de cosas además de declarar los componentes de la aplicación, como son:

Identificar los permisos que requiere la aplicación, como conexión a Internet o permisos de lectura de los contactos del usuario.

Declarar el nivel mínimo de API requerido por la aplicación, basándonos en qué APIs usa nuestra aplicación.

Declarar las características hardware y software usadas o requeridas por la aplicación, como la cámara, servicios de bluetooth o la pantalla táctil.

Las librerías API con las que la aplicación necesita ser enlazada (además de las propias del sistema Android), como por ejemplo, la de Google Maps.

El archivo manifest para declarar una actividad tiene la siguiente estructura:

21" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

<?xml version="1.0" encoding="utf-8"?> <manifest ... > <application android:icon="@drawable/app_icon.png" ... > <activity android:name="com.example.project.ExampleActivity" android:label="@string/example_label" ... > </activity> ... </application> </manifest>

En el elemento <application>, el atributo “android:icon” apunta a un recurso de la aplicación que consiste en un icono que identifica a la misma.

En el elemento <activity>, el atributo “android:name” especifica el nombre completo por clases de la actividad y el atributo “android:label” especifica una cadena de texto que se usará como identificador de la actividad y será visible al usuario.

3.1.3 Instalación del entorno de desarrollo

Una vez que conocemos mejor la estructura del sistema Android y los fundamentos de las aplicaciones el siguiente paso sería realizar una primera toma de contacto con el desarrollo de aplicaciones, y para ello, el primer paso es instalar las herramientas necesarias, que son:

IDE Eclipse: es el entorno de desarrollo que se puede descargar en el siguiente enlace:

http://www.eclipse.org/downloads/

De esta página nos podemos descargar la última versión de “Eclipse Classic”.

SDK de Android: disponible en la página oficial de “Android Developers”:

http://developer.android.com/

Este kit de desarrollo incluye un conjunto de herramientas tales como un “debugger” (herramienta para testear nuestra aplicación) y un emulador (para poder ejecutar nuestra aplicación en un entorno sin necesidad de disponer de teléfono físico).

Plugin ADT: este complemento extiende las capacidades de Eclipse y permite crear proyectos Android, interfaces de usuario y paquetes basados en el Android Framework API. También permite depurar aplicaciones usando las herramientas del Android SDK e incluso exportar aplicaciones firmadas (o no) en archivos .apk para distribuirlos.

22" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Google nos recomienda encarecidamente usar Eclipse con el plugin ADT que nos proporciona todo lo que necesitamos para empezar a crear aplicaciones Android, así que vamos a explicar cómo instalar los componentes anteriores.

Los requerimientos mínimos de nuestro sistema deberán ser los siguientes, tal y como nos señalan en Android Developers:

Sistemas Operativos Eclipse IDE

- Windows XP (32-bit), Vista (32- o 64-bit), o Windows 7 (32- o 64-bit). - Mac OS X 10.5.8 o posterior (sólo x86). - Linux (probado en Ubuntu Linux, Lucid Lynx). Se requiere la librería “GNU C Library (glibc) 2.7” o posterior.

- Eclipse 3.6.2 (Helios) o superior. - Eclipse JDT plugin (incluído en la mayoría de paquetes de Eclipse IDE). - JDK 6 (JRE por sí solo no es suficiente). - Android Development Tools plugin (recomendado). - No compatible con el compilador para Java “gcj”.

Para la instalación tenemos dos opciones. Por un lado, descargar cada componente por separado desde su origen e instalarlos uno tras otro siguiendo alguno de los múltiples tutoriales que circulan por Internet. Pero existe otra opción más sencilla, Google nos facilita un paquete con todo lo necesario para comenzar a desarrollar, el “Android ADT Bundle”, disponible en el siguiente enlace:

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

Además, también nos facilitan las instrucciones necesarias para su instalación en:

http://developer.android.com/sdk/installing/bundle.html

Que en resumidas cuentas consiste en:

Descomprimir el archivo .zip descargado moverlo a un directorio apropiado como por ejemplo “Desarrollo” en nuestro sistema de archivos.

Abrir el directorio “adt-bundle-<os_platform>/eclipse/” y ejecutar Eclipse.

Y nada más, en este momento ya estamos listos para comenzar a desarrollar nuestra primera aplicación.

3.1.4 Ejemplo de “Hola Mundo” en Android

El primer paso es crear un nuevo proyecto, y para ello, seleccionamos el menú “File/New/Other/Android Proyect” y nos aparecerá la siguiente ventana:

23" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Ilustración 3: Ventana de nuevo proyecto en Android

Donde cada uno de los campos son:

Project Name: es el nombre del directorio del proyecto y el nombre que aparecerá en Eclipse.

Application Name: será el nombre de nuestra aplicación. El que le aparecerá a los usuarios.

Package name: sigue las mismas reglas que los paquetes en Java. Nuestro paquete debe ser único en el sistema Android. Por esta razón, en general, lo mejor es usar un identificador del tipo:

“com.nombredesarrollador.nombreaplicacion”

Minimum Required SDK: es la versión más baja de Android que puede ejecutar nuestra aplicación y se indica utilizando el nivel de API. Para soportar tantos dispositivos como sea posible interesa configurarlo a la mínima versión que ofrezca las características necesarias en nuestra aplicación.

Target SDK: indica la versión más alta de Android (también como nivel API) en la cual hemos probado que nuestra aplicación funciona.

Compile With: es la versión de la plataforma con la que se va a compilar la aplicación. Por defecto, se ajusta a la última versión disponible en nuestro SDK.

Theme: especifica el estilo de la interfaz de usuario que queremos darle a nuestra aplicación. No es necesario definir este campo.

Al finalizar podremos ver el siguiente árbol de archivos:

24" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Ilustración 4: Proyecto recién creado en Android

A continuación describimos cada uno de estos directorios:

/src - directorio para los archivos de código fuente de nuestra aplicación. Por defecto, incluye una clase Activity que se ejecuta cuando se lanza la aplicación.

/assets - en este directorio se puede incluir cualquier tipo de fichero externo que sea necesario para la aplicación. Por ejemplo, archivos HTML sin necesidad de conexión, tipografías, bases de datos, etc. Es un repositorio de archivos.

/res - contiene varios subdirectorios para los recursos de la aplicación. Algunos de estos directorios son:

o /res/drawable-hdpi – directorio para objetos gráficos (como bitmaps) que están diseñados para pantallas de alta densidad de pixels (hdpi). Los otros directorios de gráficos contienen objetos para otras densidades de pantalla.

o /res/layout – aquí van todos los archivos que definen la interfaz de usuario de la aplicación.

o /res/values – directorio para otros archivos XML que contienen una colección de recursos tales como cadenas de texto o definiciones de colores.

25" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

AndroidManifest.xml – archivo que ya tratamos con anterioridad y que incluye una descripción de las características fundamentales de la aplicación y define cada uno de sus componentes.

El proyecto que acabamos de crear ya está listo para ser ejecutado, y podemos hacerlo de dos maneras, en un dispositivo real, o en el emulador.

3.1.4.1 Ejecución en un dispositivo real

Se conecta el dispositivo vía USB. Si usamos Windows debemos asegurarnos de tener instalado el driver apropiado, pero en el caso de Mac OS o Linux no es necesario realizar ninguna comprobación.

En el dispositivo habilitamos la opción “depuración USB”, esta opción suele encontrarse dentro del menú “opciones de desarrollo” en el caso de Android 4.0 y dentro del menú “aplicaciones/desarrollo” en Android 3.2 o anterior. A partir de Android 4.2 la opción de desarrollador está oculta por defecto. Para que se muestre nos vamos al menú “acerca del teléfono” y tocamos siete veces en “número de compilación”.

En Eclipse abrimos un proyecto y pulsamos el menú “Run/Android Application”. Eclipse instalará la aplicación en el dispositivo conectado y la iniciará.

Pero también es posible ejecutar la aplicación desde la línea de comandos. Nos situamos en el directorio raíz de nuestro proyecto Android y ejecutamos:

ant debug

Debemos asegurarnos de que el directorio “platform-tools/” del Android SDK está incluido en el PATH del entorno (esto dependerá del sistema operativo en el que trabajemos), y luego ejecutar:

adb install bin/MyFirstApp-debug.apk

Una vez hecho esto ya podemos localizar la aplicación en el dispositivo e iniciarla.

3.1.4.2 Ejecución en el emulador

Tanto si usamos Eclipse como la línea de comandos, para ejecutar nuestra aplicación en el emulador es necesario crear primero un “Android Virtual Device” (AVD). Un AVD es una configuración para el emulador Android que permite simular diferentes dispositivos.

26" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Ilustración 5: Android Virtual Device Manager

Para crear un AVD hacemos lo siguiente:

1. Lanzamos el “Android Virtual Device Manager”

a. En Eclipse, pulsamos en “Android Virtual Device Manager” en la barra de herramientas.

b. En la línea de comandos, nos movemos al directorio “<sdk>/tools/” y ejecutamos:

android avd

2. En el panel de “Android Virtual Device Manager” pulsamos en “New”.

3. Rellenamos los detalles del AVD. Le damos un nombre, una plataforma objetivo, un tamaño de tarjeta SD, y un skin o aspecto (HVGA por defecto).

4. Pulsamos en crear AVD.

5. Elegimos la nueva AVD creada en el “Android Virtual Device Manager” y pulsamos en “Start”.

6. Una vez que el emulador ha arrancado, desbloqueamos la pantalla de inicio.

7. De la misma forma que para un dispositivo real, ejecutamos nuestra aplicación desde Eclipse (“Run/Android Application”) o desde la línea de comandos.

Si tenemos conectado un dispositivo real y también tenemos abierto un AVD, o bien, tenemos varios AVD, Eclipse nos dará a elegir donde instalar la aplicación cuando pulsemos en “Run”.

27" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

3.1.4.3 Explicación de la aplicación “Hola Mundo”

La aplicación recién creada simplemente se encarga de mostrar un mensaje de “HolaMundo” por pantalla con una única actividad. En este apartado vamos a exponer el contenido de los principales archivos del proyecto que consiguen tal funcionalidad.

Para empezar, nos encontramos con el archivo “AndroidManifest.xml”, cuya estructura ya hemos comentado anteriormente:

// AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.holamundo" android:versionCode="1" android:versionName="1.0.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".HolaMundo" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>

El atributo ‘android:label="@string/app_name"’, sustituye la cadena “app_name” por su valor en el archivo “strings.xml”:

// res/values/strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, HolaMundo</string> <string name="app_name">Hola Mundo</string> </resources>

Este archivo contendrá todas las cadenas de texto de nuestra aplicación en lugar de insertar la cadena dentro del código cada vez que aparezca. Además este archivo facilita la localización de idioma de la aplicación.

El ejemplo “HolaMundo” sólo contiene una actividad, y está definida en el archivo “HolaMundo.java” de la siguiente manera:

// src/com.example.holamundo/HolaMundo.java package com.example.holamundo; import android.app.Activity; import android.os.Bundle; public class HolaMundo extends Activity { /** Called when the activity is first created. */

28" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

@Override public void onCreate(Bundle savedInstanceState) { // Inicializa la actividad super.onCreate(savedInstanceState); // Asignamos la vista setContentView(R.layout.main); } }

Contiene un único método que sobrescribe al de la clase que extiende (“Activity”). Vemos como “setContentView” pasa como parámetro “R.layout.main” que representa a “/res/layout/main.xml”. Este último archivo es el que define la interfaz de usuario o “layout” de la actividad:

// res/layout/main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout>

En este código, “LinearLayout” es un tipo de layout que muestra los elementos uno tras otro, en orientación vertical y horizontal. En este caso se ha definido con orientación vertical y ocupa toda la pantalla tanto a lo alto como a lo ancho. El “ViewGroup” (una vista especial que contiene otras vistas denominadas hijos) de tipo “LinearLayout” es útil para representar objetos que queremos que se ajusten a todo el alto o todo el ancho de la pantalla, y esto se consigue con los atributos ‘android:layout_width="fill_parent"’ y ‘android:layout_height="fill_parent"’. Otros tipos de “ViewGroup”, cada uno con ciertas características concretas son: AbsoluteLayout, FrameLayout, GridLayout, RelativeLayout, etc.

Dentro del “LinearLayout” tenemos un campo de texto (“TextView”) que toma su contenido desde el archivo “strings.xml”.

Este ejemplo es la aplicación más sencilla que podemos crear, pero para entender un poco mejor en los siguientes capítulos el desarrollo del proyecto, vamos a introducir algunos conceptos más del código necesario para realizar funciones básicas.

Respuesta a un botón

El primer elemento básico imprescindible en una aplicación es un botón que responda al toque. El botón se muestra en la aplicación definiéndolo en el layout correspondiente:

29" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_send" android:onClick="sendMessage" />

Donde el atributo “android:onClick” hace referencia a la función que se ejecutará cuando se pulse el botón: "sendMessage". En Android, la mayor parte del código de la aplicación está orientado a realizar ciertas tareas cuando ocurre algún evento provocado por el usuario sobre el dispositivo, y este botón es un ejemplo de cómo se manejan estos eventos. La función “sendMessage” ubicada en la actividad que usa el anterior layout será:

/** Called when the user clicks the Send button */ public void sendMessage(View view) { // Do something in response to button }

Este método requiere importar la clase “View”:

import android.view.View;

Y para que el sistema conecte este método con el atributo “android:onClick”, este método debe:

Ser público;

Devolver un valor “void”, es decir, no devolver nada;

Tener un View como único parámetro, que será el View que fue tocado (el botón).

Iniciar otra actividad

Si recordamos, un Intent es un objeto que facilita la conexión entre componentes en tiempo de ejecución (como por ejemplo, dos actividades). Se pueden usar intents para una gran variedad de cosas, pero muy a menudo se usan para iniciar otra actividad.

Dentro del método sendMessage() que hemos visto antes, vamos a crear un Intent para iniciar otra actividad denominada “DisplayMessageActivity”:

Intent intent = new Intent(this, DisplayMessageActivity.class);

Este constructor usa dos parámetros:

30" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Un “contexto” como primer parámetro. Esto es porque la clase “Activity” es una subclase de “Context”.

El segundo parámetro es la clase del componente al que el sistema debería enviarle el Intent, en este caso, la actividad que queremos iniciar.

Un intent no sólo nos permite iniciar otra actividad, sino que además, puede enviar un paquete de datos a la actividad. Dentro del método “sendMessage()” usamos “findViewById()” para obtener el elemento “EditText” (el campo de texto) y añadir su contenido (el texto) al intent:

Intent intent = new Intent(this, DisplayMessageActivity.class); EditText editText = (EditText) findViewById(R.id.edit_message); String message = editText.getText().toString(); intent.putExtra(EXTRA_MESSAGE, message);

Un Intent puede llevar una colección de varios tipos de datos como pares “código-valor” denominados “extras”. El método “putExtra()” lleva el nombre del parámetro y el valor.

Para iniciar la nueva actividad sólo faltaría llamar a la función encargada de iniciarla pasándole el Intent que acabamos de crear:

/** Called when the user clicks the Send button */ public void sendMessage(View view) { Intent intent = new Intent(this, DisplayMessageActivity.class); EditText editText = (EditText) findViewById(R.id.edit_message); String message = editText.getText().toString(); intent.putExtra(EXTRA_MESSAGE, message); startActivity(intent); }

Donde “EXTRA_MESSAGE” es una constante pública que hemos definido al comienzo de la actividad llamante para usarla como código del valor que vamos a pasar a la nueva actividad:

public class MainActivity extends Activity { public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE"; ... }

Ahora deberíamos crear la nueva actividad que tomará los datos anteriores:

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

31" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

// Get the message from the intent Intent intent = getIntent(); String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE); // Create the text view TextView textView = new TextView(this); textView.setTextSize(40); textView.setText(message); // Set the text view as the activity layout setContentView(textView); }

Esta nueva actividad definiría un “TextView”, un campo para mostrar texto, al que se le pasaría el dato obtenido de la primera actividad.

Por supuesto, en Android hay múltiples elementos que podemos usar además de los ya vistos. Pero en lugar de hacer una descripción de todos los disponibles, o de los más importantes, vamos a esperar al capítulo cuatro en el que detallaremos los que han sido necesarios para este proyecto.

3.2 iOS

iOS, anteriormente denominado “iPhone OS”, es un sistema operativo móvil desarrollado y distribuido por Apple Inc. Fue lanzado en 2007 para los dispositivos “iPhone” y “iPod Touch”, pero ha sido extendido para soportar otros dispositivos como el “iPad” y “Apple TV”.

A diferencia de Google con Android, Apple no licencia iOS para su instalación en dispositivos que no sean de Apple. Ni por supuesto, su código fuente es accesible a todo el mundo. Pero este hecho no ha sido impedimento para que su uso se haya extendido mundialmente hasta obtener un porcentaje importante del mercado. Actualmente Apple ha vendido más de 400 millones de dispositivos con iOS y su tienda de aplicaciones, la “App Store”, contiene más de 700,000 aplicaciones que se han descargado más de 30 billones de veces en su conjunto.

Ilustración 6: Aspecto de la pantalla de inicio en iOS

32" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

La interfaz de usuario, al igual que Android, está basada en el concepto del contacto directo mediante gestos multi-táctiles. Los dispositivos iOS también cuentan con sensores que ayudan a las aplicaciones a recibir información de entrada del usuario.

El iOS SDK contiene las herramientas e interfaces necesarias para desarrollar, instalar, ejecutar, y testear aplicaciones nativas de iOS. Estas aplicaciones están construidas sobre los frameworks del sistema iOS y el lenguaje de programación Objective-C.

Para diseñar e implementar aplicaciones es útil entender las tecnologías y herramientas que conforman el iOS SDK.

3.2.1 Estructura del sistema operativo

La arquitectura iOS está basada en capas. En la capa más alta, iOS actúa como un intermediario entre el hardware y las aplicaciones. Estas aplicaciones rara vez se comunican directamente con el hardware. En su lugar, lo hacen a través de un conjunto bien definido de interfaces del sistema que protegen a la aplicación de cambios en el hardware. Esta abstracción posibilita crear aplicaciones que funcionen bajo dispositivos con distintas especificaciones hardware.

Ilustración 7: Diagrama de la arquitectura iOS

Las capas bajas del sistema se encargan de los servicios fundamentales y las tecnologías sobre las que todas las aplicaciones se apoyan. Las capas altas contienen servicios y tecnologías más sofisticadas. Veámoslas una a una:

3.2.1.1 Cocoa Touch Layer

Esta capa contiene los frameworks imprescindibles para construir aplicaciones iOS. Se define la infraestructura básica de las aplicaciones y se soportan tecnologías como la multitarea, la entrada multi-táctil, las notificaciones del sistema, y otros servicios de alto nivel.

Algunos de los frameworks que se ofrecen en esta capa son:

33" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Address Book UI Framework: es una interfaz de programación necesaria para crear contactos, o bien, editar o seleccionar contactos ya existentes.

Event Kit UI Framework: introducido en iOS 4.0, provee “View Controllers” (que es como se llama a los controladores de interfaz de usuario de la aplicación) para ver y editar eventos del calendario.

Game Kit Framework: ofrece capacidades de redes “peer-to-peer” (punto a punto). Se usan fundamentalmente para los juegos multi-jugador, aunque puede tener otros usos. “Game Center” es una extensión de este framework que implementa una serie de características para el juego en red.

iAd Framework: permite mostrar anuncios del servicio de anuncios de Apple en la aplicación.

Map Kit Framework: proporciona una interfaz de mapas desplazable que se puede integrar en las vistas de nuestra aplicación. Sobre el mapa se pueden marcar direcciones o puntos de interés. Además, es posible realizar anotaciones sobre el mapa con imágenes o contenido personalizado. También es posible colocar “overlays” (capas superpuestas) sobre el mapa para crear anotaciones complejas que comprendan más de un punto, como rutas, límites de un terreno o información del tiempo.

Message UI Framework: soporte para la redacción y encolado de mensajes de usuario.

UIKit Framework: dota de la infraestructura necesaria para implementar aplicaciones gráficas y orientadas a eventos en iOS. Todas las aplicaciones iOS lo usan. Algunas de las características que implementa este framework son:

o Administración de aplicaciones.

o Administración de la interfaz de usuario.

o Soporte gráfico.

o Multi-tarea.

o Impresión.

o Personalización de los controles estándar.

o Soporte para implementar “View Controllers” e incorporar contenido de otros “View Controllers”.

o Manejo de eventos táctiles y basados en movimiento.

o Soporte de texto y contenido web.

o Soporte para animaciones del contenido de las interfaces.

34" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

o Acceso a la cámara.

o Acceso a la librería de fotos del usuario.

o Información de la batería.

o Información de sensores.

3.2.1.2 Media Layer

La capa Media contiene las tecnologías de gráficos, audio y vídeo. Es la parte del sistema que, por ejemplo, posibilita que se muestren imágenes en las vistas de la capa superior. Pero para tareas más complejas existen las siguientes tecnologías disponibles:

Core Graphics (también conocido como “Quartz”): maneja vectores en dos dimensiones y representación de imágenes.

Core Animation (parte del “Quartz Core framework”): provee soporte avanzado para vistas animadas y otros contenidos.

Core Image: ofrece soporte avanzado para la manipulación de vídeo e imágenes fijas.

OpenGL ES y GLKit: soporte para la representación en 2D y 3D usando aceleración por hardware.

Core Text: para el diseño sofisticado de texto y motor de representación.

Image I/O: interfaces para la lectura y escritura de la mayor parte de los formatos de imagen.

The Assets Library framework: permite el acceso a las fotos y vídeos de la biblioteca de usuario.

En el caso de aplicaciones que se ejecutan sobre dispositivos con pantalla “Retina” (un tipo de pantalla con muy alta resolución), todo el contenido que se muestra es escalado automáticamente.

3.2.1.3 Core Services Layer

Esta capa contiene los servicios fundamentales del sistema que todas las aplicaciones usan. Incluso, aunque nuestra aplicación no los utilice directamente, muchas partes del sistema están construidas sobre ellos.

Las tecnologías de alto nivel disponibles en esta capa son:

iCloud Storage: permite al usuario de la aplicación escribir documentos y datos en una localización centralizada y acceder a ellos desde el ordenador de escritorio o desde otro dispositivo iOS.

35" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Automatic Reference Counting: es una característica de compilación que simplifica el proceso de gestionar el tiempo de vida de los objetos en Objective-C. En lugar de que el desarrollador tenga que recordar cuándo reservar o liberar un objeto, ARC (Automatic Reference Counting) evalúa los requisitos de tiempo de vida del objeto y automáticamente inserta el método necesario en tiempo de compilación. Todos los proyectos creados en las últimas versiones de iOS usan ARC por defecto, aunque Xcode facilita herramientas para convertir antiguos proyectos para que usen ARC.

Block Objects: son constructores en lenguaje C que se pueden incorporar al código Objective-C. Son útiles para “callbacks” (funciones que son llamadas tras un evento) o lugares donde es necesario combinar de manera sencilla ambos códigos para ser ejecutados.

Data Protection: permite que las aplicaciones que trabajan con información sensible de usuario hagan uso de la encriptación disponible en el sistema.

File-Sharing Support: sirve para que los archivos del usuario estén disponibles mediante iTunes 9.1 o superior. Una aplicación que declara soporte para archivos compartidos hace que el contenido de su directorio “/Documents” esté disponible para el usuario desde iTunes.

Grand Central Dispatch (GCD): es una tecnología para gestionar la ejecución de tareas en la aplicación. GCD combina un modelo de programación asíncrono con un núcleo optimizado para facilitar una alternativa al manejo de hilos. También provee alternativas para muchas tareas de bajo nivel, como la lectura y escritura de un archivo, implementación de temporizadores y procesado de señales y sus eventos correspondientes.

In-App Purchase: gracias a esta característica es posible vender contenido y servicios desde la misma aplicación. Se implementa usando el “Store Kit framework”, el cual ofrece la infraestructura necesaria para procesar transacciones financieras usando la cuenta de usuario de iTunes.

SQLite: la librería SQLite permite utilizar una base de datos SQL ligera en la aplicación sin necesidad de ejecutar un servidor de bases de datos paralelo. Desde la aplicación es posible crear bases de datos locales y gestionarlas.

XML Support: proporciona la clase NSXMLParser para recuperar elementos de un archivo XML. El soporte adicional para manipular contenido XML se obtiene con la librería “libXML2”. Esta librería permite analizar y escribir datos XML rápidamente y transformar contenido XML a HTML.

Por otro lado, esta capa ofrece una serie de frameworks y servicios, denominados “Core Services Frameworks” que son:

Accounts Framework: ofrece un modelo de inicio de sesión único para ciertas cuentas de usuario.

36" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Address Book Framework: para el acceso a los contactos almacenados en el dispositivo del usuario. En iOS 6 y posteriores requiere permiso explícito del usuario.

Ad Support Framework: provee acceso a un identificador que las aplicaciones pueden usar con fines publicitarios.

CFNetwork Framework: es un conjunto de interfaces de alto rendimiento basadas en C que trabajan con los protocolos de red. Se puede utilizar para simplificar tareas como la comunicación con servidores FTP y HTTP o para resolver DNS (Domain Name System, sistema de nombres de dominio).

Core Data Framework: Core Data está dirigido al uso en aplicaciones en las que el modelo de datos está muy estructurado. En lugar de definir las estructuras en código, es posible usar herramientas gráficas en Xcode para construir un esquema representando el modelo de datos. Durante la ejecución, se crean las instancias del modelo de datos, se gestionan, y se hacen disponibles para su uso a través de este framework.

Core Foundation Framework: es un conjunto de interfaces basadas en C que proporcionan soporte para:

o Colecciones de tipos de datos (por ejemplo, arrays).

o Paquetes.

o Manejo de cadenas de texto.

o Gestión de fecha y hora.

o Gestión de bloques de datos en crudo.

o Gestión de preferencias.

o Manipulación de URL y flujos.

o Hilos y bucles.

o Comunicaciones de puerto y socket (par de direcciones IP local y remota, un protocolo de transporte y un par de números de puerto local y remoto).

Core Location Framework: ofrece información de localización y rumbo a las aplicaciones. Para la información de localización, el framework usa los componentes de GPS, red móvil o Wi-Fi disponibles en el dispositivo para encontrar la ubicación actual del usuario en forma de coordenadas de longitud y latitud.

Core Media Framework: proporciona los formatos de medios de bajo nivel usados por el “AV Foundation framework”. La mayoría de aplicaciones nunca necesitan usar este framework, pero se facilita para aquellos desarrolladores que

37" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

necesitan un control más preciso sobre la creación y presentación de contenido de audio y vídeo.

Core Motion Framework: un conjunto de interfaces para acceder a todos los datos disponibles en el dispositivo relacionados con el movimiento. Soporta el acceso a los datos en crudo o procesados del acelerómetro. Para aquellos dispositivos que cuentan con giroscopio, permite igualmente recuperar la información disponible reflejando la altitud y la relación de rotación.

Core Telephony Framework: facilita las interfaces para la interacción con la información de los dispositivos con servicio de telefonía que tienen hardware de radio móvil. Las aplicaciones pueden obtener información sobre el operador de red o sobre eventos relacionados.

Event Kit Framework: es una interfaz para el acceso a eventos del calendario del usuario. Se pueden leer eventos existentes o añadir nuevos eventos. Desde iOS 6 las aplicaciones requieren permiso explícito del usuario para el acceso.

Foundation Framework: provee un envoltorio Objective-C a muchas de las características que se encuentran en el “Core Foundation framework”.

Mobile Core Services Framework: define los tipos de bajo nivel usados en Uniform Type Identifiers (UTIs).

Newsstand Kit Framework: consiste en un lugar centralizado para que los usuarios puedan leer revistas y periódicos.

Pass Kit Framework: soporte para tarjetas como cupones, tarjetas de embarque, tickets, etc.

Quick Look Framework: interfaz para previsualizar los contenidos de los archivos que nuestra aplicación no soporta directamente.

Social Framework: proporciona un interfaz para el acceso a las cuentas del usuario de redes sociales.

Store Kit Framework: soporte para la compra de contenido y servicios dentro de las aplicaciones.

System Configuration Framework: para determinar la configuración de red de un dispositivo.

3.2.1.4 Core OS Layer

En la capa “Core OS” se encuentran las características de bajo nivel sobre las que la mayoría de las tecnologías son construidas. Incluso aunque nuestra aplicación no haga uso de ellas directamente, es muy probable que estén siendo usadas por otros frameworks. Y es necesaria en aquellas situaciones en las cuales se requiere trabajar explícitamente con la seguridad o las comunicaciones de un hardware externo.

38" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Los frameworks de esta capa son:

Accelerate Framework: interfaces para realizar DSP (Procesamiento digital de señales), álgebra lineal, o procesamiento de imágenes. La ventaja de usar este framework en lugar de escribir nuestras propias versiones de estas interfaces es que está optimizado para todas las configuraciones de hardware de los dispositivos iOS.

Core Bluetooth Framework: permite a los desarrolladores interactuar específicamente con los accesorios bluetooth.

External Accessory Framework: soporte para la comunicación con accesorios de hardware conectados al dispositivo.

Generic Security Services Framework: provee un conjunto estandarizado de servicios de seguridad a las aplicaciones. Las interfaces de este framework están especificadas en el IETF RFC 2743 y el RFC 4401.

Security Framework: además de las características de seguridad incorporadas, iOS facilita este framework que el desarrollador puede utilizar para garantizar la seguridad de los datos que gestione la aplicación. Provee interfaces para gestionar certificados, claves públicas y privadas, y políticas de confianza.

System: es un conjunto de interfaces para acceder a muchas características de bajo nivel del sistema operativo. Nuestra aplicación accede a estas opciones a través de la librería “LibSystem”. Las interfaces soportan:

o Hilos (hilos POSIX, Portable Operating System Interface).

o Red (BSD sockets).

o Acceso al sistema de archivos.

o I/O estándar.

o Bonjour y servicios DNS.

o Información de localización.

o Reserva de memoria.

o Cálculos matemáticos.

3.2.2 Fundamentos de las aplicaciones

A la hora de crear aplicaciones iOS nos enfrentamos a un lenguaje de programación desconocido, generalmente, para el desarrollador. Por esta razón, lo primero que vamos a hacer es introducir los conceptos básicos de programación en Objective-C. Luego hablaremos también de la creación de interfaces de usuario en iOS y finalmente, en el siguiente apartado, expondremos la aplicación de ejemplo “Hola Mundo”.

39" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

3.2.2.1 Objective-C

En el desarrollo de aplicaciones iOS, lo primero que nos llama la atención es el lenguaje Objective-C. Es un lenguaje poco conocido y su uso se limita fundamentalmente al desarrollo en iOS y Mac OS X. Sin embargo, no es complicado, sobre todo si se está familiarizado con C. Objective-C es un lenguaje orientado a objetos que extiende el estándar del lenguaje de programación C mediante sintaxis para la definición de clases y métodos.

Objective-C mantiene la misma sintaxis básica de C. Elementos como los tipos primitivos (int, float, etc.), estructuras, funciones, punteros, cláusulas “if…else”, etc. permanecen igual. También se tiene acceso a las librerías estándar, como las declaradas en “stdlib.h” y “stdio.h”.

Se añade la siguiente sintaxis y características a C:

Definiciones de nuevas clases.

Invocación de métodos (denominado mensajería).

Tipado estático y dinámico.

Bloques: encapsulación de segmentos de código que pueden ser ejecutados en cualquier momento.

Extensiones como protocolos y categorías.

Clases y Objetos

La especificación de una clase en Objective-C requiere dos piezas distintas: la interfaz y la implementación. La interfaz es la parte que contiene la declaración de la clase y define la interfaz pública de la misma. Como en C, se pueden definir archivos de cabecera para separar declaraciones públicas de la implementación. Estos archivos tienen las siguientes extensiones:

Extensión Tipo de archivo .h Archivos de cabecera. Contienen declaraciones de clases, tipos, funciones

y constantes. .m Archivo de la implementación. Un archivo con esta extensión contiene

código tanto Objective-C como C. Se le suele llamar archivo fuente. .mm Archivo de la implementación. Un archivo de implementación con esta

extensión puede contener código C++ además de Objective-c. Se debe usar la extensión sólo si realmente se están usando clases C++.

Cuando se quieren incluir archivos de cabecera en el archivo de implementación, se usa la directiva “#import” seguida del nombre del archivo de cabecera. Es similar a “#include” en C, excepto que en Objective-C se asegura de que el mismo archivo nunca es incluido más de una vez. Si se quieren incluir la mayoría, si no todos, los archivos de cabecera de un framework, la sintaxis que se usa es (suponiendo un hipotético framework denominado “Gizmo”):

40" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

#import <Gizmo/Gizmo.h>

En el siguiente diagrama se muestra la sintaxis para declarar una clase denominada “MyClass”, la cual hereda de la clase raíz NSObject. Una clase raíz es aquella de la cual todas las demás clases heredan directa o indirectamente. La declaración de la clase comienza con la directiva “@interface” y termina con la directiva “@end”. Le sigue el nombre de la clase y, separado por el símbolo “:”, el nombre de la clase padre. En Objective-C, una clase puede tener sólo un padre.

Ilustración 8: Declaración de una clase en Objective-C

Las declaraciones de las “properties” (declaración de variables de la clase) y de los métodos se realiza entre las directivas “@interface” y “@end”. Estas declaraciones forman la interfaz pública de la clase.

La declaración de la clase de un objeto define una interfaz que permite a aquellos que los usan leer y escribir los valores de las variables que define (sus “properties”). Y los métodos que realizan estas acciones se denominan métodos de acceso.

Hay dos tipos de métodos de acceso, uno para la lectura y otro para la escritura, y cada método debe estar de acuerdo a un convenio de nombres. La notación de estos métodos de acceso en Objective-C es de la forma:

@property (nonatomic, copy) NSString *userName;

Esto elimina la necesidad de definir un método de lectura y otro de escritura para cada variable en la clase. En su lugar, se especifica el comportamiento que se desea que tenga la variable en la declaración del “property”.

La declaración básica de una “property” se forma mediante la directiva “@property”, seguida de la información de tipo y nombre de la propiedad. También se pueden configurar opciones adicionales como el comportamiento de los métodos de acceso. Por ejemplo:

// Copia el objeto durante la asignación. @property (copy) MyModelObject *theObject; // Declara sólo un método de acceso. No genera el “setter”, el método que realiza la asignación @property (readonly) NSView *rootView;

41" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

// Declara la variable como una referencia débil. @property (weak) id delegate;

También se especifican semánticas para el almacenamiento como:

“assign”: asignación simple en el método de acceso que establece el valor de la variable. Por ejemplo, una variable tipo “float” (que no es un objeto, y no se puede usar “copy” ni “retain”).

“retain”: realiza una referencia a un objeto creado. Toma la propiedad o posesión de un objeto.

“copy”: hace una copia de un objeto clonando su valor. En aquellos casos en los que nos interesa evitar que el contenido de un objeto sea modificado por otro deberíamos usar esta declaración, ya que con ella nos hacemos dueños de la copia del objeto.

Esencialmente, cuando se usa la directiva “@synthesize” en la implementación, los atributos anteriores determinan cómo se gestiona la memoria en el método de acceso que establece el valor del objeto.

Por defecto, las propiedades son consideradas “atomic”, lo que implica que se realiza un bloqueo para prevenir que múltiples hilos accedan a la misma variable al mismo tiempo. Si se declara la variable como “nonatomic” se elimina este bloqueo.

La sintaxis para la implementación de la clase es similar. Comienza con la primitiva “@implementation” (seguida del nombre de la clase) y termina con la directiva “@end”. La implementación de los métodos se inserta en medio. Una implementación siempre debería importar su interfaz como una de las primeras líneas de código.

#import "MyClass.h" @implementation MyClass - (id)initWithString:(NSString *)aName { // aquí va el código } + (MyClass *)myClassWithString:(NSString *)aName { // aquí va el código } @end

Objective-C soporta tipado dinámico de variables, pero también soporta el tipado estático. Las variables tipadas estáticamente incluyen el nombre de la clase en su declaración. Las variables tipadas dinámicamente en su lugar, usan el tipo “id” para el objeto. Éstas últimas se usan en situaciones concretas como por ejemplo, una colección de objetos como un array (donde los tipos exactos de los objetos contenidos pueden ser desconocidos). Otro ejemplo:

42" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

MyClass *myObject1; // Tipado estático id myObject2; // Tipado dinámico NSString *userName; // Tipado estático

El asterisco “*” de la primera declaración indica que es un puntero. En Objective-C, las referencias a objetos siempre deben ser punteros. El tipo “id” lleva implícito un puntero también.

Métodos y mensajes

Un método es una función orientada al ámbito de un objeto específico. Al enviar un mensaje a un objeto, se llama a un método de ese objeto. Hay dos tipos de métodos en Objective-C: métodos de instancia y métodos de clase.

Método de instancia: es aquel cuya ejecución está limitada al ámbito de una clase particular. O lo que es lo mismo, antes de llamar al método de instancia es preciso crear una instancia de la clase. Son los más comunes.

Método de clase: aquel cuya ejecución está limitada al ámbito de la clase del método. No requieren una instancia de un objeto para recibir un mensaje.

La declaración de un método comprende un identificador de tipo, un tipo devuelto, una o más palabras clave, y el tipo del parámetro y su nombre. Por ejemplo:

Ilustración 9: Declaración de un método de instancia en Objective-C

Para los métodos de instancia, la declaración se precede con un signo menos “-”. Para los métodos de clase, el indicador es un signo más “+”.

El nombre de un método es una concatenación de todas las palabras clave, incluyendo los dos puntos, “:”, que indican la presencia de un parámetro. En el ejemplo anterior, el método toma dos parámetros. Si un método no tiene parámetros se omiten los dos puntos.

Cuando se llama a un método, se hace enviando un mensaje al objeto que implementa el método (o lo que es lo mismo llamando al método del objeto, aunque en la ejecución de Objective-C se produce realmente el envío). El mensaje es el nombre del método junto con los parámetros que necesite.

43" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Para hacer el envío del mensaje se emplea una expresión consistente en dos corchetes “[]” que encierran el mensaje con sus parámetros. Para el ejemplo anterior:

[myArray insertObject:anObject atIndex:0];

Para evitar declarar numerosas variables locales para almacenar los resultados de manera temporal, Objective-C permite anidar las expresiones de los mensajes. El valor devuelto por cada expresión es usado como parámetro de otro mensaje. Por ejemplo, si tuviéramos un objeto llamado “myAppObject” que dispone de métodos para acceder e insertas los objetos en el array, podríamos hacer lo siguiente:

[[myAppObject theArray] insertObject:[myAppObject objectToInsert] atIndex:0];

Objective-C también proporciona sintaxis de notación de punto para acceder a los métodos de acceso:

[myAppObject.theArray insertObject:myAppObject.objectToInsert atIndex:0];

Y también se puede utilizar esta sintaxis para asignación:

myAppObject.theArray = aNewArray;

Esto último es la alternativa a escribir “[myAppObject setTheArray:aNewArray];”. Esta notación no se puede utilizar en un objeto dinámicamente tipado (tipo “id”).

Con esta notación también es posible acceder a una variable definida en la interfaz dentro de una clase:

self.userName = self.textField.text;

Los métodos de clase se usan a menudo como constructores de nuevas instancias de una clase o para acceder a un trozo de información compartida asociada con la clase. Por ejemplo, el método “array” es un método de clase de la clase NSArray (que es heredada por NSMutableArray) que reserva e inicializa una nueva instancia de la clase y lo devuelve:

NSMutableArray *myArray = nil; // nil es lo mismo que NULL // Crea un nuevo array y lo asigna a la variable myArray myArray = [NSMutableArray array];

44" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

3.2.2.2 Foundation framework

Este framework define docenas de protocolos con distintas finalidades, pero podemos destacar tres categorías de protocolos que son imprescindibles:

La clase raíz y sus protocolos relacionados: la clase raíz, NSObject, y su protocolo del mismo nombre, especifica la interfaz básica y el comportamiento de todos los objetos Objective-C.

Clases de valor: generan una instancia (denominada objeto valor) que es un envoltorio orientado a objetos para las primitivas tales como cadenas de texto, números, fechas, o datos binarios. Las instancias de la misma clase valor que encapsulan el mismo valor se consideran iguales.

Clases de colecciones: una instancia de una clase de colección (una colección) gestiona un grupo de objetos. Lo que distingue un tipo particular de colección es cómo te permite acceder a un objeto que contenga. A menudo, los objetos de las colecciones son objetos valor.

Crear objetos

Para crear un objeto, se envía un mensaje “alloc” (de reserva) a la clase del objeto para obtener una instancia de la clase sin inicializar. Justo después de crearlo debemos inicializarlo para que podamos utilizar el objeto.

En los frameworks encontramos muchos métodos de inicialización, que nos devuelven los objetos ya inicializados. Un práctica de programación segura es verificar si el objeto devuelto fue creado. Si ocurre algo en la fase de inicialización del objeto, el método devuelve nil.

También podemos crear objetos llamando al constructor de la clase que tiene como objetivo reservar, inicializar y devolver una instancia de él mismo. Estos métodos son convenientes porque nos permiten crear un objeto en un solo paso en lugar de dos. Por ejemplo, NSString define estos dos métodos:

- (id)initWithFormat:(NSString *)format, ...; + (id)stringWithFormat:(NSString *)format, ...;

Que podríamos usar por ejemplo de la siguiente manera:

NSString *myString = [NSString stringWithFormat:@"Customer: %@", self.record.customerName];

45" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Crear y usar objetos valor

Los objetos de valor representan valores (enteros, cadenas de texto, etc.) en forma de objetos. Las clases existentes que generan objetos de valor en el “Foundation framework” son:

NSString and NSMutableString

NSData and NSMutableData

NSDate

NSNumber

NSValue

Estos objetos permiten realizar ciertas operaciones sobre los valores que encapsulan de forma eficiente. La clase NSString, por ejemplo, tiene métodos para buscar y reemplazar fragmentos en cadenas de texto, para escribir texto a archivos o URLs, o para construir rutas de directorios.

Otro ejemplo interesante para el caso particular de este proyecto es el de fechas y horas. Un objeto NSDate encapsula el intervalo, en segundos, desde una fecha referencia. Este objeto, necesita de otras clases para realizar representaciones de fechas, y éstas son:

NSCalendar y NSDateComponents: se puede asociar la fecha con un calendario.

NSTimeZone: cuando una fecha debe reflejar la zona horaria asociada con el calendario.

NSLocale: este objeto encapsula convenciones lingüísticas y culturales, incluyendo las relacionadas con el tiempo.

Un ejemplo de uso de estos objetos es el siguiente:

NSDate *now = [NSDate date]; // 1 NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; // 2 [calendar setTimeZone:[NSTimeZone systemTimeZone]]; // 3 NSDateComponents *dc = [calendar components:(NSHourCalendarUnit|NSMinuteCalendarUnit| NSSecondCalendarUnit) fromDate:now]; // 4 NSLog(@"The time is %d:%d:%d", [dc hour], [dc minute], [dc second]); // 5

El código anterior realiza lo siguiente:

1. Crea un objeto de fecha representando el instante actual.

2. Crea un objeto representando el calendario Gregoriano.

46" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

3. Establece la zona horaria del objeto calendario con la zona horaria establecida en las preferencias del sistema.

4. Llama al método “components:fromDate:” sobre el objeto calendario, pasándole como parámetro la fecha creada en el primer paso. El método devuelve un objeto que contiene la hora, minutos y segundos del objeto fecha.

5. Imprime por consola la hora actual, minutos y segundos.

Colecciones

Una colección es un objeto que almacena otros objetos y permite acceder a ellos. El “Foundation framework” tiene varios tipos de colecciones, pero hay tres que son particularmente importantes en “Cocoa Touch” y programación “Cocoa”: arrays, “dictionaries” (diccionarios) y “sets” (conjuntos).

Las clases de colecciones pueden ser variables o fijas (“Mutable” o “Immutable”). Las variables permiten añadir y quitar objetos, y las fijas sólo contienen los objetos con los que fueron creadas.

Tipos de colecciones:

NSArray y NSMutableArray: un array es una colección ordenada de objetos. Se puede acceder a los objetos especificando su posición (el índice) en el array. El primer elemento es el 0.

NSDictionary y NSMutableDictionary: un diccionario almacena sus entradas como pares “clave-valor”. La clave es un identificador único, normalmente una cadena de texto, y el valor es el objeto que se almacena. Se puede acceder al objeto especificando la clave.

NSSet y NSMutableSet: un conjunto almacena una colección desordenada de objetos, donde cada objeto sólo aparece una vez. Generalmente se accede a los objetos aplicando filtros al conjunto.

Ejemplos de colecciones:

// Crea un array fijo de objetos de cadenas de texto NSString *objs[3] = {@"One", @"Two", @"Three"}; // Crea un array con el array fijo anterior NSArray *arrayOne = [NSArray arrayWithObjects:objs count:3]; // Crea un array con una lista de objetos terminada en nil NSArray *arrayTwo = [[NSArray alloc] initWithObjects:@"One", @"Two", @"Three", nil]; // Accede a un array NSString *theString = [arrayTwo objectAtIndex:1];

47" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

3.2.2.3 Arquitectura de las aplicaciones

Desde el momento en que la aplicación es ejecutada por el usuario, hasta el momento en que salga de ella, el framework “UIKit” gestiona la mayor parte del comportamiento del núcleo de la aplicación. En el corazón de la aplicación está el objeto “UIApplication”, que recibe eventos del sistema y los reparte al código de la aplicación para ser manejados. Otras clases de UIKit tienen un papel en la gestión del comportamiento de la aplicación también, y todas lo hacen de forma similar con llamadas al código.

Para entender cómo trabaja UIKit con nuestro código puede ser de ayuda conocer un poco más sobre los objetos que componen una aplicación iOS. La siguiente figura muestra los objetos que se encuentran con más frecuencia:

Ilustración 10: Objetos clave en una aplicación iOS

Las aplicaciones iOS están organizadas entorno a un modelo de diseño denominado “Model-View-Controller”. Este esquema separa los objetos de datos de las vistas usadas para presentarlos. Esta separación permite que el código sea reutilizable haciendo posible modificar las vistas cuando sea necesario.

Las tareas que desempeña cada objeto en el diagrama anterior son:

UIApplication object: maneja el ciclo de eventos de la aplicación y coordina otros comportamientos de alto nivel. La lógica de la aplicación reside en el objeto delegado, que trabaja en conjunción con este objeto.

App delegate object: es un objeto personalizado creado en tiempo de ejecución, normalmente por la función “UIApplicationMain”. El trabajo de este objeto es manejar las transiciones de estado dentro de la aplicación.

Documents and data model objects: almacenan el contenido de la aplicación y son específicos de la aplicación desarrollada. Las aplicaciones también pueden usar objetos de documentos.

48" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

View controller objects: gestionan la presentación del contenido de la aplicación en pantalla. Un “view controller” gestiona una única vista y su colección de sub-vistas. Cuando se muestran, el “view controller” hace sus vistas visibles instalándolas en la ventana de la aplicación. Es la clase base para todos los objetos de un “view controller”. UIKit y otros frameworks proporcionan clases adicionales de “view controllers” que implementan interfaces estándar del sistema como una barra de pestañas, una barra de navegación, etc.

UIWindow object: coordina la presentación de una o más vistas en la pantalla. Las vistas se muestran en la ventana correspondiente, pero nunca se reemplaza la ventana en sí misma.

View, control, and layer objects: las vistas y los controles conforman la representación visual del contenido de la aplicación. Una vista es un objeto que dibuja contenido en un área rectangular y responde a eventos dentro de esa área. Los controles son un tipo especial de vistas responsables de la implementación de objetos tales como botones, campos de texto, y conmutadores. Las capas (“layer objects”) son objetos de datos que representan contenido visual y pueden servir por ejemplo para implementar animaciones complejas y otros efectos visuales.

Los métodos y clases vistos hasta ahora son sólo un pequeño grupo de todos los que existen. Pero como introducción a Objective-C parece suficiente, ya que el objetivo de esta memoria no es instruir en el lenguaje de programación usado en el desarrollo de aplicaciones en iOS, sino sentar unas bases para que el lector entienda los sucesivos apartados en los que se explicará la aplicación desarrollada en este proyecto.

Tras exponer los detalles de la instalación del entorno de desarrollo, se mostrará un último ejemplo más, muy básico, para comprender cómo se unen todos los elementos para formar una aplicación.

3.2.3 Instalación del entorno de desarrollo

Para desarrollar aplicaciones en iOS se hace uso del “iOS SDK” y de Xcode, el entorno de desarrollo integrado (IDE) de Apple. Xcode ofrece herramientas como un editor de código fuente, un editor gráfico de interfaces de usuario, etc. El iOS SDK extiende las utilidades de Xcode para incluir las herramientas, compiladores y frameworks necesarios para iOS.

Instalar el entorno de desarrollo completo comprende dos pasos:

Ilustración 11: Pasos instalación de Xcode

49" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

1. Descargar la última versión de Xcode: abrimos la “Mac App Store” en el Mac, buscamos por “Xcode”, y hacemos clic en instalar (el iOS SDK está incluido). La “Mac App Store” viene instalada con Mac OS X versión 10.7 y superior.

2. Registrarnos como “Apple Developer” en el programa “iOS Developer Program”: no es necesario registrarse como desarrollador para escribir aplicaciones y probarlas en el simulador, pero sí que lo es para probarlas en dispositivos reales y distribuirlas. El registro da acceso al “iOS Dev Center” y el “iOS Provisioning Portal”.

3.2.3.1 Xcode

Ilustración 12: Captura de Xcode

Como hemos comentado, Xcode es una IDE que proporciona todas las herramientas necesarias para crear y gestionar los proyectos iOS, construir las interfaces de usuario, compilar el código, y ejecutar o depurar el código tanto en el Simulador como en un dispositivo. Entre las características de Xcode podemos destacar:

Editor de código con realce de sintaxis y auto completado de código.

Editor integrado para crear “StoryBoard” y archivos “nib”. Ambos conceptos relacionados con las interfaces de usuario.

50" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Visor de documentación de ayuda.

Soporte LLVM (Low Level Virtual Machine, o Máquina Virtual de Nivel Bajo) para C, C++ y Objective-C.

Compiladores GCC que soportan C, C++, Objective-C, Objective-C++, y otros lenguajes.

Analizador útil para comprobar el comportamiento de la aplicación desarrollada e identificar posibles problemas.

Depurador integrado que usa GDB.

Soporte para manejar el desarrollo sobre dispositivos iOS.

3.2.3.2 Ejecución en un dispositivo real

Xcode nos deja elegir de manera muy sencilla dónde instalar la aplicación compilada, en el simulador o en un dispositivo. Para ejecutar la aplicación en un dispositivo, debemos obtener previamente un certificado de Apple que se usará para firmar la aplicación. Este certificado se puede obtener mediante la ventana “Organizer” de Xcode, donde se muestran también los dispositivos conectados.

51" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Ilustración 13: Ventana “Organizer” en Xcode

Además, también es necesario instalar un perfil asociado en el dispositivo que habilita a la aplicación para identificarnos como desarrollador mediante el certificado. Si se quiere usar un dispositivo para desarrollo los pasos son:

1. Conectar el dispositivo al Mac.

2. Abrir “Organizer”.

3. Elegir el dispositivo en la sección “Devices”.

4. Pulsar en el botón "Use for Development".

La primera vez que se añade un identificador de dispositivo (“device ID”) a nuestra cuenta, Xcode crea el “iOS Team Provisioning Profile” usando el identificador de aplicación, el certificado de desarrollador y el identificador del dispositivo. El “iOS Team Provisioning Profile” también es instalado en el dispositivo.

Una vez que tenemos un dispositivo real conectado a Xcode, los pasos que tenemos que realizar para ejecutar la aplicación son:

1. Abrimos el menú de Xcode “Product > Edit Scheme” para nuestro proyecto.

2. En el “scheme editor” elegimos el dispositivo que hemos conectado:

Ilustración 14: Selección del dispositivo para ejecución

3. Ejecutamos pulsando en “Run”.

52" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

La selección del “scheme” o sistema también podemos hacerla directamente desde la ventana principal del proyecto, gracias a un botón cercano al de “Run”.

De igual manera se haría para ejecutar la aplicación en el simulador aunque en este caso no es necesario el uso de certificados.

3.2.3.3 Instruments

Xcode integra una herramienta muy interesante y prácticamente indispensable para analizar el rendimiento de nuestra aplicación, tanto en el simulador como en un dispositivo real.

Instruments recoge los datos de la aplicación durante su funcionamiento y los presenta gráficamente en una línea de tiempo.

Ilustración 15: Captura de Instruments

Con esta herramienta es posible recopilar datos de nuestra aplicación tales como el uso de memoria, la actividad del disco, actividad de red y rendimiento gráfico, entre otras mediciones. El hecho de ver todos estos datos reunidos permite analizar diferentes aspectos del rendimiento de la aplicación que son útiles para identificar áreas potencialmente mejorables (por ejemplo, fugas de memoria). Es posible, además, automatizar el testeo de los elementos de la interfaz de la aplicación, y también,

53" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

comparar el comportamiento de la misma en instantes distintos para determinar si los cambios mejoran el rendimiento.

Para analizar una aplicación con Instruments los pasos son:

1. Dentro de nuestro proyecto en Xcode, elegir el menú “Product > Perform Action > Profile Without Building”.

2. En el simulador iOS, en la columna de la izquierda, pulsar “All” para ver todos las plantillas de trazas disponibles.

3. Elegir “Leaks” (fugas) y pulsar en “Profile”.

4. Se iniciará Instruments y nuestra aplicación se ejecutará en el simulador.

5. Tras hacer algunas pruebas con la aplicación en el simulador, lo cerramos para que deje de recoger datos.

6. En Instruments pulsamos en el panel “Allocations” para examinar las reservas de memoria que ha realizado nuestra aplicación. Esto nos permitiría controlar que no haya grandes picos de reserva de memoria por ejemplo.

3.2.4 Ejemplo “Hola Mundo” en iOS

Vamos a exponer un ejemplo sencillo en el que se pretende crear una aplicación con la siguiente interfaz:

Ilustración 16: Interfaz de la aplicación “Hola Mundo”

54" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

En la imagen se presentan tres elementos que son:

Un campo de texto o “text field”, donde el usuario introduce información.

Una etiqueta o “label”, que muestra información.

Un botón (“button”), que provoca que la aplicación muestre la información en la etiqueta.

En el campo de texto el usuario podrá introducir su nombre, y al pulsar el botón, en la etiqueta saldrá el mensaje “Hello, Your Name!“.

Para empezar, creamos un nuevo proyecto en Xcode:

1. Elegimos el menú “File > New > New project”. Xcode abrirá una ventana en la que podemos elegir la plantilla. Están disponibles, por ejemplo, plantillas de pestañas.

Ilustración 17: Ventana de creación de un nuevo proyecto en Xcode

2. En el menú de la izquierda elegimos “Application”, y a la derecha “Single View Application” y pulsamos en “Next”. Aparecerá un nuevo diálogo para introducir el nombre de la aplicación y otros datos del proyecto.

55" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Ilustración 18: Diálogo de nuevo proyecto en Xcode

3. Rellenamos los campos, por ejemplo:

a. Product Name: HelloWorld

b. Company Identifier: el nombre de tu empresa, si lo tienes.

c. Class Prefix: HelloWorld

4. En el menú “Devices”, nos aseguramos que elegimos “iPhone” en este caso.

5. Y marcamos las casillas “Use Storyboard” y “Use Automatic Reference Counting”, pero no “Include Unit Tests”. Las dos primeras son opciones añadidas en las últimas versiones de iOS (que no se tienen en cuenta en iSemanaSanta):

a. El “Storyboard” es una manera unificada de diseñar la interfaz de la aplicación en lugar de crear cada vista por separado (cada archivo nib).

b. Automatic Reference Counting (ARC): es un sistema automático de gestión de la memoria en tiempo de compilación. Nos ahorra tener que llevar la cuenta de las variables que reservamos y su posterior liberación. En iSemanaSanta, esta tarea se hará manualmente.

c. “Include Unit Tests”: para incluir en el proyecto dispositivos reales. Esta opción no es necesaria en el ejemplo.

6. Al pulsar “Next” aparece otro diálogo para indicar dónde guardar el proyecto y finalmente, Xcode abre la ventana de trabajo con el proyecto recién creado.

56" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Ilustración 19: Ventana de trabajo de Xcode

Esta ventana de trabajo está organizada de la siguiente manera:

Ilustración 20: Elementos de la interfaz de Xcode

57" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Si ejecutamos la aplicación en el simulador en este punto, gracias a que hemos usado una plantilla, veremos una vista en blanco sin ningún elemento. La aplicación creada contiene un objeto que, entre otras cosas, establece el ciclo de ejecución que registra los eventos y los reparte. La mayor parte de este trabajo lo realiza la función “UIApplicationMain”, que es parte del “UIKit framework” y que es automáticamente llamada en el archivo fuente “main.m” del proyecto:

@autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([HelloWorldAppDelegate class])); }

La declaración “@autoreleasepool” sirve para soportar el sistema “Automatic Reference Counting” (ARC), que gestiona el tiempo de vida de los objetos de la aplicación, asegurando que no haya fugas de memoria.

La llamada a “UIApplicationMain” crea una instancia de la clase “UIApplication” y una instancia del delegado (“delegate”) de la aplicación, que en este ejemplo es “HelloWorldAppDelegate”, la cual proporciona una plantilla de vista única. La principal tarea del delegado es proveer a la ventana en la que se dibuja el contenido de la aplicación. Y también realiza labores de configuración justo antes de que la aplicación sea mostrada. La “Delegación” es un patrón de diseño en el que un objeto actúa en nombre de, o en coordinación con, otro objeto.

La ventana (objeto “window”), por su parte, es la que proporciona un contenedor para el contenido visible de la aplicación, ayudando a repartir eventos a los objetos, y a responder a la orientación del dispositivo.

La llamada a “UIApplicationMain” también busca el archivo “Info.plist” del proyecto que contiene una lista de propiedades estructuradas en forma de pares “clave-valor”. Estas propiedades contienen información como puede ser el nombre de la aplicación y su icono.

En este ejemplo de “Hola Mundo”, el archivo de “storyboard” se llama “MainStoryboard.storyboard” y es especificado en el archivo “Info.plist”. Cuando la aplicación se inicia, se carga este “storyboard” y se crea una instancia del “view controller” inicial. Un “view controller” es un objeto que gestiona un área de contenido. El “view controller” inicial es simplemente la primera vista que se carga cuando se lanza la aplicación.

El ejemplo contiene sólo un “view controller” (o controlador de vista) (“HelloWorldViewController”), que en el momento de su creación gestiona el contenido de una única vista o “view”. Una vista es un objeto que dibuja contenido en un área rectangular de la pantalla y maneja eventos producidos por los toques del usuario. Una vista también puede contener otras vistas, denominadas sub-vistas (o “subviews”). Cuando se añade una sub-vista a una vista, a ésta última se le llama vista padre (“parent view”) y a la sub-vista se le llama vista hijo (“child view”). La vista padre y sus vistas hijo forman una jerarquía, y un “view controller” gestiona una sola jerarquía de vistas.

58" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

El siguiente paso será añadir los elementos a la vista, pero antes, vamos a describir los elementos que conforman el “storyboard”.

Ilustración 21: Edición de vistas usando el “Storyboard”

Un “storyboard” contiene escenas (“scenes”) y transiciones (“segues”). Una escena representa un “view controller”, y su transición representa el paso entre dos escenas.

Como este ejemplo sólo tiene un “view controller”, el “storyboard” contiene una sola escena y no tiene transiciones. La flecha que apunta al lado izquierdo de la escena en el lienzo (“canvas”) es el indicador de escena inicial, que identifica la escena que debería aparecer por primera vez cuando se inicie la aplicación (el “view controller” inicial).

La escena del ejemplo se denomina “Hello World View Controller” y es gestionada por un objeto “HelloWorldViewController”. Esta escena consiste en unos pocos elementos que se muestran en la barra de la izquierda (“Outline view”). En este momento, el “view controller” tiene los siguientes elementos:

Fisrt Responder: representado por un cubo naranja. Es un marcador dinámico que representa el primer objeto que debería recibir los distintos eventos.

59" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Exit: cuando un usuario cierra una escena, el “view controller” de esa escena devuelve el control a la escena padre (que es la escena desde donde se hizo la transición a la escena que se cierra). Sin embargo, el objeto Exit permite que un “view controller” devuelva el control a una escena cualquiera.

El objeto HelloWorldViewController: representado por un rectángulo en el interior de una esfera amarilla. Cuando se carga el “storyboard”, crea una instancia de la clase del “view controller” que gestiona la escena.

View: una vista que es lo que realmente se ve en la aplicación cuando se ejecuta en el simulador.

Bajo la escena se muestra una barra denominada “scene dock” y que contiene iconos representando a los objetos “First responder”, “Exit” y “view controller”.

Pues bien, para seguir con el ejemplo tendremos que añadir los elementos a la vista. Estos elementos están disponibles en la “Object Library” y una vez elegidos nuestros elementos (“text field”, “Round Rect button”, y “label”) sólo tenemos que arrastrarlos a la vista y ajustar sus propiedades, forma, y posición.

Al insertar los elementos aparece un nuevo elemento en la barra de la izquierda denominado “Constraints”. Esto forma parte del sistema de “Auto Layout” que permite definir unas limitaciones para los elementos. Estas limitaciones representan relaciones entre ellos mismos que afectan a su posición y geometría cuando las vistas son redimensionadas o cuando cambia la orientación. En este ejemplo no se van a modificar estas propiedades.

Si ejecutáramos ahora la aplicación, el botón no haría nada, la etiqueta no mostraría información, y al pulsar en el campo de texto aparecería un teclado que no tenemos forma de volver a ocultar. Para añadir cierta funcionalidad necesitamos realizar las conexiones apropiadas entre los elementos de la vista y el “view controller”. Estas conexiones son las que vamos a explicar a continuación.

3.2.4.1 Crear una acción para el botón

Cuando un usuario activa un elemento de la interfaz, ese elemento puede enviar un mensaje de acción a un objeto que sabe qué hacer con esa acción (como por ejemplo, “añade un contacto a la lista de contactos”).

Cuando el usuario toca el botón “Hello” queremos que envíe el mensaje “cambia el saludo” al “view controller”. Y que éste responda modificando la cadena de texto y luego actualizando el texto mostrado en la etiqueta.

En Xcode se puede añadir una acción a un elemento arrastrando (con la tecla “Control” pulsada) desde él hasta la zona de código fuente apropiada. Cuando añadimos una acción a nuestro botón, lo que realmente hace Xcode es añadir el código necesario y crear la conexión entre el botón y el “view controller”.

La declaración en la interfaz:

60" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

- (IBAction)changeGreeting:(id)sender;

El código en la implementación:

- (IBAction)changeGreeting:(id)sender { }

“IBAction” es una palabra clave usada para decirle a Xcode que trate al método como una acción para conexiones. IBAction está definido a “void”. El parámetro “sender” se refiere al objeto que está mandando el mensaje de acción (en este caso, el sender es el botón).

3.2.4.2 Crear Outlets

También necesitamos crear conexiones entre el view controller y los dos elementos restantes, la etiqueta y el campo de texto.

Un “outlet” describe una conexión entre dos objetos. Cuando queremos que un objeto (como el view controller) se comunique con otro objeto que contiene el anterior (como el campo de texto), designamos el objeto contenido como un outlet.

Queremos que el view controller obtenga el texto del campo de texto y luego lo muestre en la etiqueta. Para asegurarnos de que el view controller pueda comunicarse con estos objetos, creamos conexiones entre ellos.

Para crear la conexiones hacemos lo mismo que hicimos para el botón, pero en este caso arrastramos hasta la interfaz del código del view controller. Y de nuevo, lo que realmente ha hecho Xcode es añadir el código de la declaración y establecer la conexión:

@property (weak, nonatomic) IBOutlet UITextField *textField;

“IBOutlet” es una palabra clave que se usa para decir a Xcode que trate el objeto como un outlet. No tiene efecto en tiempo de compilación.

En versiones antiguas de Xcode se añadía una directiva “@synthesize” en el bloque de implementación para cada propiedad declarada. Pero como el compilador automáticamente hace esa función, estas directivas ya no son necesarias.

Las tres conexiones que hemos creado las podemos ver en el “Connections inspector” para cada objeto:

61" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

Ilustración 22: Inspector de conexiones para el View Controller

Hay una cuarta conexión entre el view controller y su vista. Esta conexión se incluye por defecto.

3.2.4.3 Crear las conexiones con el delegado

Por último, necesitamos conectar el campo de texto a un objeto que especifiquemos como su delegado (un objeto que actúa en nombre de otro objeto). La razón es porque el campo de texto envía un mensaje a su delegado cuando el usuario toca el botón “Done” en el teclado para esconderlo. En este caso, usaremos el mismo view controller como delegado.

Para establecer el delegado, arrastramos (pulsando también la tecla “Control”) desde el campo de texto hasta la esfera amarilla que representa el view controller, y en el menú que aparece elegimos “delegate”.

3.2.4.4 Implementación del View Controller

En el view controller necesitamos añadir una propiedad para el nombre del usuario, implementar el método “changeGreeting:”, y asegurar que el teclado se oculta cuando se pulsa “Done”.

La propiedad a declarar es necesaria para almacenar la cadena de texto con el nombre de usuario, de tal manera que tengamos una referencia a él en todo el código del view controller:

62" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

@property (copy, nonatomic) NSString *userName;

El compilador automáticamente añade la directiva “@synthesize” para cada propiedad que declaremos.

El método “changeGreeting:” es el que se encargará de realizar las acciones pertinentes cuando se pulse el botón:

- (IBAction)changeGreeting:(id)sender { self.userName = self.textField.text; NSString *nameString = self.userName; if ([nameString length] == 0) { nameString = @"World"; } NSString *greeting = [[NSString alloc] initWithFormat:@"Hello, %@!", nameString]; self.label.text = greeting; }

self.userName = self.textField.text;

Recupera el texto del campo de texto y asigna la propiedad “uerName” con el resultado.

En este ejemplo no estamos usando esa cadena de texto en ningún otro punto, pero es importante conocer esta característica. La información de la aplicación no debería ser almacenada en los elementos de la interfaz de usuario.

NSString *nameString = self.userName;

Crea una nueva variable (de tipo NSString) y la asigna con la propiedad userName.

@"World" es una cadena de texto constante representada por una instancia de NSString. Si el usuario ejecuta la aplicación y no introduce ningún texto, “nameString” contendrá la cadena “World”.

initWithFormat:

Este método pertenece al “Foundation framework” y crea una nueva cadena que sigue el formato especificado por la cadena de formateo que se le pasa (similar a printf en C).

Por último, queda ajustar el funcionamiento del teclado. En iOS, el teclado se muestra automáticamente cuando un elemento que permite introducir texto se convierte en “first

63" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

responder”. Y es ocultado automáticamente cuando pierde el estado de “first responder”.

El protocolo “UITextFieldDelegate” definido por el “UIKit framework” incluye el método “textFieldShouldReturn:” al que el campo de texto llama cuando el usuario pulsa la tecla Retorno (sin importar el nombre real de esta tecla que puede variar). Gracias a que establecimos al view controller como delegado del campo de texto, podemos definir este método para que fuerce al campo de texto a perder su estado de “first responder” enviando el mensaje “resignFirstResponder”, que ocultará el teclado.

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField { if (theTextField == self.textField) { [theTextField resignFirstResponder]; } return YES; }

En esta aplicación no es realmente necesario hacer la comprobación “theTextField == self.textField” porque sólo hay un campo de texto, pero es una buena práctica ya que puede ocurrir que haya más de un campo de texto en la vista que tenga como delegado el view controller.

Para indicar que usamos el protocolo “UITextFieldDelegate” hay que añadir lo siguiente a la declaración de la interfaz:

@interface HelloWorldViewController : UIViewController <UITextFieldDelegate> ...

Aquí termina la introducción al desarrollo de aplicaciones para iOS. Se ha ofrecido una visión lo bastante detallada como para empezar a desarrollar nuestras propias aplicaciones iOS, así que será más que suficiente para entender el capítulo cuatro en el que expondremos todo lo relacionado con iSemanaSanta. A continuación, vemos el último apartado de este capítulo, la tecnología empleada para la base de datos: SQLite.

3.3 SQLite

La última tecnología digna de mención que vamos a utilizar en iSemanaSanta es la usada para la gestión de bases de datos.

SQLite es una librería que implementa un motor de base de datos transaccional basada en el lenguaje SQL sin necesidad de servidor ni configuración. A diferencia de otras bases de datos basadas en SQL, SQLite no tiene un proceso separado del programa principal, sino que actúa como una biblioteca que se enlaza con el programa pasando a ser parte del mismo.

64" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

El conjunto de la base de datos (definiciones, tablas, índices, y los propios datos), se guarda como un sólo fichero estándar en memoria. Este diseño simple se logra bloqueando todo el fichero de base de datos al principio de cada transacción.

Una de las principales ventajas de SQLite es que su tamaño puede ser de menos de 350 kilobytes, dependiendo de la plataforma. Este tamaño tan compacto, unido a los pocos recursos que consume, hacen que SQLite sea un motor de bases de datos muy popular en pequeños dispositivos como teléfonos móviles, reproductores MP3, etc.

Por otro lado, el lenguaje SQL (“Structured Query Language”) es un estándar para el acceso a bases de datos relacionales que permite especificar diversos tipos de operaciones.

SQL tiene las siguientes características:

Lenguaje de definición de datos (LDD): proporciona comandos para la definición de esquemas de relación, borrado de relaciones y modificaciones de los esquemas de relación.

Lenguaje interactivo de manipulación de datos (LMD): incluye lenguajes de consultas basado tanto en álgebra relacional como en cálculo relacional de tuplas.

Integridad: El LDD de SQL incluye comandos para especificar las restricciones de integridad que deben cumplir los datos almacenados en la base de datos.

Definición de vistas: El LDD incluye comandos para definir las vistas.

Control de transacciones: SQL tiene comandos para especificar el comienzo y el final de una transacción.

SQL incorporado y dinámico: Esto quiere decir que se pueden incorporar instrucciones de SQL en lenguajes de programación como: C++, C, Java, Cobol, Pascal y Fortran.

Autorización: El LDD incluye comandos para especificar los derechos de acceso a las relaciones y a las vistas.

El lenguaje de definición de datos (LDD, o en inglés “Data Definition Language”, o DDL), es el que se encarga de la modificación de la estructura de los objetos de la base de datos. Incluye órdenes para modificar, borrar o definir las tablas en las que se almacenan los datos de la base de datos. Existen cuatro operaciones básicas: CREATE, ALTER, DROP y TRUNCATE.

CREATE

Crea un objeto dentro del gestor de base de datos. Puede ser una base de datos, tabla, índice, procedimiento almacenado o vista.

Por ejemplo, creamos una tabla llamada “Persons” que contiene cinco columnas: P_Id, LastName, FirstName, Address, and City:

65" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

CREATE TABLE Persons ( P_Id int, LastName varchar(255), FirstName varchar(255), Address varchar(255), City varchar(255) )

ALTER

Este comando permite modificar la estructura de un objeto. Se pueden agregar/quitar campos a una tabla, modificar el tipo de un campo, agregar/quitar índices a una tabla, etc.

En este ejemplo, se añade una columna denominada “DateOfBirth” en la tabla “Persons”:

ALTER TABLE Persons ADD DateOfBirth date

DROP

Elimina un objeto de la base de datos. Puede ser una tabla, vista, índice, o cualquier otro objeto que el motor de la base de datos soporte. Se puede combinar con la sentencia ALTER.

De esta manera borramos una tabla:

DROP TABLE table_name

TRUNCATE

Sirve para borrar todo el contenido dentro de una tabla, pero no la tabla:

TRUNCATE TABLE table_name

El lenguaje de manipulación de datos (LMD, o en inglés, Data Manipulation Language, DML) es un lenguaje proporcionado por el sistema de gestión de base de datos que permite a los usuarios llevar a cabo las tareas de consulta o manipulación de los datos, organizados por el modelo de datos adecuado. Algunos de sus comandos son:

INSERT

Una sentencia INSERT de SQL agrega uno o más registros a una (y sólo una) tabla en una base de datos relacional.

66" iSemanaSanta: aplicación móvil sobre iOS y Android para servicio de mapas, posicionamiento y

base de datos de información"

INSERT INTO table_name (column1, column2, column3,...) VALUES (value1, value2, value3,...)

UPDATE

Es utilizada para modificar los valores de un conjunto de registros existentes en una tabla.

UPDATE table_name SET column1=value, column2=value2,... WHERE some_column=some_value

DELETE

Una sentencia DELETE de SQL borra uno o más registros existentes en una tabla.

DELETE FROM table_name WHERE some_column=some_value

SELECT

Esta sentencia se usa para seleccionar información de una base de datos. El resultado se almacena en una tabla resultado.

SELECT column_name(s) FROM table_name

Con esto finalizamos el repaso a las tecnologías más importantes que se usan en el proyecto iSemanaSanta. Lo visto hasta ahora será la base para entender, a partir del próximo capítulo, la descripción a todos los niveles de la aplicación desarrollada, iSemanaSanta. Se hablará de la interfaz de usuario, de su funcionamiento, y expondremos algunos detalles de su código para ambas plataformas, Android e iOS.