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: