Kitabı oku: «El gran libro de Android»

Yazı tipi:

El gran libro de Android

Jesús Tomás Gironés

Beatriz Tirado Gil

El gran libro de Android

Jesús Tomás Gironés

Beatriz Tirado Gil


El gran libro de Android

Séptima edición, 2018

Primera reimpresión revisada, 2020

© 2018 Jesús Tomás Gironés y Beatriz Tirado Gil

© MARCOMBO, S.A. 2018

www.marcombo.com

Diseño de la cubierta: ENEDENÚ DISEÑO GRÁFICO

Corrección: Raquel Sayas Lloris

Cualquier forma de reproducción, distribución, comunicación pública o transformación de esta obra solo puede ser realizada con la autorización de sus titulares, salvo excepción prevista por la ley. Diríjase a CEDRO (Centro Español de Derechos Reprográficos, www.cedro.org) si necesita fotocopiar o escanear algún fragmento de esta obra.

ISBN: 978-84-26727-37-4

Producción del ebook: booqlab.com

Para Bea, con amor y gratitud.

Mis agradecimientos a los alumnos y lectores que con sus sugerencias y correcciones han ayudado a mejorar este libro.

Índice general

Lista de siglas y acrónimos

¿Cómo leer este libro?

CAPÍTULO 1. Visión general y entorno de desarrollo

1.1. ¿Qué hace que Android sea especial?

1.2. Los orígenes

1.3. Comparativa con otras plataformas

1.4. Arquitectura de Android

1.4.1. El núcleo Linux

1.4.2. Runtime de Android

1.4.3. Librerías nativas

1.4.4. Entorno de aplicación

1.4.5. Aplicaciones

1.5. Instalación del entorno de desarrollo

1.5.1. Instalación de la máquina virtual Java

1.5.2. Instalación de Android Studio

1.5.3. Creación de un dispositivo virtual Android (AVD)

1.6. Las versiones de Android y niveles de API

1.6.1. Las primeras versiones

1.6.2. Cupcake

1.6.3. Donut

1.6.4. Éclair

1.6.5. Froyo

1.6.6. Gingerbread

1.6.7. Honeycomb

1.6.8. Ice Cream Sandwich

1.6.9. Jelly Bean

1.6.10. KitKat

1.6.11. Lollipop

1.6.12. Marshmallow

1.6.13. Android Nougat

1.6.14. Android Oreo

1.6.15. Android Pie

1.6.16. Android 10

1.6.17. Elección de la plataforma de desarrollo

1.6.18. Las librerías de compatibilidad (support library)

1.7. Creación de un primer programa

1.8. Ejecución del programa

1.8.1. Ejecución en el emulador

1.8.2. Ejecución en un terminal real

1.9. Ficheros y carpetas de un proyecto Android

1.10. Componentes de una aplicación

1.10.1. Vista (View)

1.10.2. Layout

1.10.3. Actividad (Activity)

1.10.4. Fragmentos (Fragment)

1.10.5. Servicio (Service)

1.10.6. Intención (Intent)

1.10.7. Receptor de anuncios (Broadcast Receiver)

1.10.8. Proveedores de contenido (Content Provider)

1.11. Documentación y aplicaciones de ejemplo

1.11.1. Dónde encontrar documentación

1.11.2. Repositorio de ejemplos en GitHub

1.12. Depurar

1.12.1. Depurar con el entorno de desarrollo

1.12.2. Depurar con mensajes Log

1.13. Introducción Java/Kotlin y aplicación Mis Lugares

1.13.1. La clase Lugar

1.13.2. Tipos enumerados

1.13.3. Las colecciones I

1.13.4. Las colecciones II

CAPÍTULO 2. Diseño de la interfaz de usuario: vistas y layouts

2.1. Creación de una interfaz de usuario por código

2.2. Creación de una interfaz de usuario usando XML

2.2.1. Edición visual de las vistas

2.2.2. Los atributos de las vistas

2.3. Layouts

2.3.1. Uso de ConstraitLayout

2.4. Una aplicación de ejemplo: Asteroides

2.5. La aplicación Mis Lugares

2.6. Recursos alternativos

2.7. Tipos de recursos y recursos del sistema

2.7.1. Tipos de recursos

2.7.2. Acceso a los recursos

2.7.3. Recursos del sistema

2.8. Estilos y temas

2.8.1. Los estilos

Heredar de un estilo propio

2.8.2. Los temas

2.9. Uso práctico de vistas y layouts

2.9.1. Acceder y modificar propiedades de las vistas por código

2.10. Uso de tabs (pestañas)

CAPÍTULO 3. Actividades e intenciones

3.1. Creación de nuevas actividades

3.2. Comunicación entre actividades

3.3. Añadiendo un menú a una actividad

3.4. La barra de acciones (Toolbar)

3.5. Acceder a objetos globales de la aplicación

3.5.1. La clase Application

3.5.2. Uso del patrón Singleton

3.6. Uso de la arquitectura Clean en Mis Lugares

Capa de Modelo

Capa de Datos

Capa de Casos de Uso

Capa de Presentación

Organizando las clases en paquetes

3.7. Creando actividades en Mis Lugares

3.7.1. Creando la actividad VistaLugarActivity

3.7.2. Creando la actividad EdicionLugarActivity

3.8. Creación y uso de iconos

3.9. Añadiendo preferencias de usuario

3.9.1. Organizando preferencias

3.9.2. Cómo se almacenan las preferencias de usuario

3.9.3. Accediendo a los valores de las preferencias

3.9.4. Verificar valores correctos<opcional>

3.10. Añadiendo una lista de puntaciones en Asteroides

3.11. Creación de listas con RecyclerView

3.12. Las intenciones

3.12.1. Añadiendo fotografías en Mis Lugares

Cargar fotografías grandes de forma eficiente

CAPÍTULO 4. Gráficos en Android

4.1. Clases para gráficos en Android

4.1.1. Canvas

4.1.2. Paint

Definición de colores

4.1.3. Path

4.1.4. Drawable

BitmapDrawable

VectorDrawable

GradientDrawable

TransitionDrawable

ShapeDrawable

AnimationDrawable

4.2. Creación de una vista en un fichero independiente

4.3. Creando la actividad principal de Asteroides

4.3.1. La clase Gráfico

4.3.2. La clase VistaJuego

4.3.3. Introduciendo la nave en VistaJuego

4.4. Representación de gráficos vectoriales en Asteroides

4.5. Animaciones

4.5.1. Animaciones de vistas

4.5.2. Animaciones de propiedades

CAPÍTULO 5. Hilos de ejecución, pantalla táctil y sensores

5.1. Uso de hilos de ejecución (threads)

5.1.1. Introducción a los procesos e hilos de ejecución

5.1.2. Hilos de ejecución en Android

5.1.3. Creación de nuevos hilos con la clase Thread

5.1.4. Introduciendo movimiento en Asteroides

5.1.5. Ejecutar una tarea en un nuevo hilo con AsyncTask

5.1.6. Mostrar un cuadro de progreso en un AsyncTask

5.1.7. El método get() de AsyncTask

5.2. Manejando eventos de usuario

5.2.1. Escuchador de eventos de la clase View

5.2.2. Manejadores de eventos

5.3. El teclado

5.4. La pantalla táctil

5.4.1. Manejo de la pantalla táctil multi-touch

5.4.2. Manejo de la nave con la pantalla táctil

5.5. Los sensores

5.5.1. Un programa que muestra los sensores disponibles y sus valores en tiempo real

5.5.2. Utilización de los sensores en Asteroides

5.5.3. Restricciones al uso de sensores en segundo plano en Android 9

5.6. Introduciendo un misil en Asteroides

CAPÍTULO 6. Multimedia y ciclo de vida de una actividad

6.1. Ciclo de vida de una actividad

6.1.1. ¿Qué proceso se elimina?

6.1.2. Guardando el estado de una actividad

6.2. Utilizando multimedia en Android

6.3. La vista VideoView

6.4. La clase MediaPlayer

6.4.1. Reproducción de audio con MediaPlayer

6.5. Un reproductor multimedia paso a paso

6.6. Introduciendo efectos de audio con SoundPool

6.7. Grabación de audio

CAPÍTULO 7. Seguridad y posicionamiento

7.1. Los tres pilares de la seguridad en Android

7.1.1. Ejecución en procesos independientes Linux

7.1.2. Firma digital de los apks

7.1.3. El esquema de permisos en Android

7.1.4. Permisos desde Android 6 Marshmallow

7.1.5. Permisos definidos por el programador en Android

7.1.6. Cambios relacionados con la privacidad en Android 9

7.2. Localización

7.2.1. Sistemas de geolocalización en dispositivos móviles

7.2.2. La API de localización de Android

7.2.3. Emulación del GPS con Android Studio

7.2.4. Estrategias para escoger un proveedor de localización

7.2.5. Límites de ubicación en segundo plano

7.3. Google Maps

7.3.1. Obtención de una clave Google Maps

7.4. Fragmentando los asteroides

CAPÍTULO 8. Servicios, notificaciones y receptores de anuncios

8.1. Introducción a los servicios en Android

8.1.1. Ciclo de vida de un servicio

8.1.2. Permisos

8.2. Un servicio para ejecución en segundo plano

8.2.1. El método onStartCommand()

8.3. Un servicio en un nuevo hilo con IntentService

8.3.1. La clase IntentService

8.4. Las notificaciones de la barra de estado

8.4.1. Configurando tipos de avisos en las notificaciones

Asociar un sonido

Añadiendo vibración

Añadiendo parpadeo de LED

8.4.2. Servicios en primer plano

8.5. Receptores de anuncios

8.5.1. Receptor de anuncios registrado en AndroidManifest.xml

8.5.2. Arrancar una actividad en una nueva tarea desde un receptor de anuncio

8.5.3. Arrancar un servicio tras cargar el sistema operativo

8.5.4. Anuncios broadcast permanentes

8.6. Un receptor de anuncios como mecanismo de comunicación

8.7. Un servicio como mecanismo de comunicación entre aplicaciones

8.7.1. Crear la interfaz en AIDL

8.7.2. Implementar la interfaz

8.7.3. Publicar la interfaz en un servicio

8.7.4. Llamar a una interfaz remota

CAPÍTULO 9. Almacenamiento de datos

9.1. Alternativas para guardar datos permanentemente en Android

9.2. Añadiendo puntuaciones en Asteroides

9.3. Preferencias

9.4. Accediendo a ficheros

9.4.1. Sistema interno de ficheros

9.4.2. Sistema de almacenamiento externo

Verificando acceso a la memoria externa

Almacenando ficheros específicos de tu aplicación en el almacenamiento externo

Almacenando ficheros compartidos en el almacenamiento externo

Almacenando externo con varias unidades

9.4.3. Acceder a un fichero de los recursos

9.5. Trabajando con XML

9.5.1. Procesando XML con SAX

9.5.2. Procesando XML con DOM

9.6. Trabajando con JSON

9.6.1. Procesando JSON con la librería Gson

9.6.2. Procesando JSON con la librería org.json

9.7. Bases de datos con SQLite

9.7.1. Los métodos query() y rawQuery()

9.7.2. Uso de bases de datos en Mis Lugares

9.7.3. Adaptadores para bases de datos

Operaciones con bases de datos en Mis Lugares

Loaders y LoaderManager

9.7.4. Bases de datos relacionales

9.7.5. El método onUpgrade de la clase SQLiteOpenHelper

9.8. Content Provider

9.8.1. Conceptos básicos

El modelo de datos

Las URI

9.8.2. Acceder a la información de un ContentProvider

Leer información de un ContentProvider

Escribir información en un ContentProvider

Borrar y modificar elementos de un ContentProvider

9.8.3. Creación de un ContentProvider

Definir la estructura de almacenamiento del ContentProvider

Extendiendo la clase ContentProvider

Declarar el ContentProvider en AndroidManifest.xml

9.8.4. Acceso a PuntuacionesProvider desde Asteroides

CAPÍTULO 10. Internet: sockets, HTTP y servicios web

10.1. Comunicaciones en Internet mediante sockets

10.1.1. La arquitectura cliente/servidor

10.1.2. ¿Qué es un socket?

Sockets stream (TCP)

Sockets datagram (UDP)

10.1.3. Un ejemplo de un cliente/servidor de ECHO

10.1.4. Un servidor por sockets para las puntuaciones

10.2. La web y el protocolo HTTP

10.2.1. El protocolo HTTP

10.2.2. Versión 1.0 del protocolo HTTP

10.2.3. Utilizando HTTP desde Android

10.2.4. Uso de HTTP con AsyncTask

10.3. La librería Volley

10.3.1. Descargar un String con Volley

10.3.2. Paso de parámetros con el método POST

10.3.3. Descargar imágenes con Volley

10.4. Servicios web

10.4.1. Alternativas en los servicios web

Servicios web basados en SOAP

Servicios web basados en REST

10.4.2. Acceso a servicios web de terceros

10.4.3. Un servicio web con Apache, PHP y MySQL

Utilizando el servicio web PHP desde Asteroides

Creación de un servicio web en un servidor de hosting

Utilizando AsyncTask de forma síncrona

10.4.4. Comparativa sockets/servicios web

ANEXO A. Fragments

ANEXO B. Diálogos de fecha y hora

Clases para trabajar con fechas en Java

ANEXO C. Referencia Java

ANEXO D. Referencia de la clase View y sus descendientes

ANEXO E. Sufijos utilizados en recursos alternativos

Lista de siglas y acrónimos


AIDLAndroid Interface Definition Language
APIApplication Programming Interface
AVDAndroid Virtual Device
ARTAndroid RunTime
CSSCascading Style Sheets
CORBACommon Object Request Broker Architecture
CPUCentral Processing Unit
DOMDocument Object Model
DTDDocument Type Definition
FTPFile Transfer Protocol
GPUGraphic Processing Unit
GPSGlobal Positioning System
GSMGlobal System for Mobile communications
HTMLHyperText Markup Language
HTTPHyperText Transfer Protocol
IDEIntegrated Development Environment
IMEIInternational Mobile Equipment Identity
IMSIInternational Mobile Subscriber Identity
IUInterfaz de Usuario
JARJava ARchive
JDKJava Development Kit
JREJava Runtime Environment
JSONJavaScript Object Notation
JVMJava Virtual Machine
MCCMobile Country Code
MNCMobile Network Code
MIMEMultipurpose Internet Mail Extensions
MTPMedia Transfer Protocol
NFCNear Field Communication
NDKNative Development Kit
OpenGLOpen Graphic Library
PCMPulse-Code Modulation
PDAPersonal Digital Assistant
PNGPortable Network Graphics
PHPHypertext Pre-processor
PTPPicture Transfer Protocol
RAMRandom Access Memory
RESTRepresentational State Transfer
RMIRemote Method Invocation
RPCRemote Procedure Calls
SAXSimple API for XML
SDSecure Digital
SDKSoftware Developers Kit
SMSShort Message Service
SIMSubscriber Identity Module
SOSistema Operativo
SOAService-Oriented Architecture
SOAPSimple Object Access Protocol
SQLStructured Query Language
SVGScalable Vector Graphics
TCPTransmission Control Protocol
UIUser Interface
URLUniversal Resource Locator
URIUniform Resource Identifier
USBUniversal Serial Bus
UTCUniversal Time Coordinate
UICCUniversal Integrated Circuit Card
W3CWorld Wide Web Consortium
WSDLWeb Services Description Language
WWWWorld Wide Web
XMLExtensible Markup Language

¿Cómo leer este libro?

Este libro quiere ser una guía para aquellos lectores que pretendan introducirse en la programación de Android. Se ha estructurado en 10 capítulos que abordan aspectos específicos del desarrollo de aplicaciones. Resulta conveniente realizar una lectura secuencial de estos capítulos, dado que muchos de los conceptos que se abordan se comprenderán mejor si se han leído los capítulos anteriores. Además, a lo largo del libro se desarrollan dos proyectos de ejemplo: el mítico juego Asteroides y la aplicación Mis Lugares. Para que muchos de los ejercicios funcionen correctamente, resulta imprescindible realizar los anteriores. Si el lector está interesado en un texto que aborde aspectos específicos de la programación en Android, le recomendamos otros libros de esta misma colección: El gran libro de Android Avanzado, Firebase: Trabajando en la nube, Plataformas Android: Wear, TV, Auto y Google Play Games y Android Things y Visión Artificial. Todos publicados en esta misma editorial.

El libro que tienes entre las manos no ha sido concebido solo para ser leído. Es más bien una guía estructurada que te irá proponiendo una serie de ejercicios, actividades, vídeos explicativos, test de autoevaluación, etc. Todo este material y muchos más recursos adicionales están disponibles en la web www.androidcurso.com. En ella se publicarán las novedades, erratas e información complementaria relativas a este libro. Por lo tanto, resulta imprescindible para sacarle partido a este libro un ordenador con el SDK de Android instalado para hacer los ejercicios y acceso a Internet para el material en línea.

A lo largo del libro se utilizan los siguientes iconos para indicar los tipos de actividades:

Objetivos: Antes de empezar cada capítulo, lee con detenimiento la introducción y los objetivos.

Vídeo[tutorial]: Más de 80 vídeos grabados por el autor del libro donde se exponen de forma didáctica los aspectos clave del sistema Android. Se utiliza una moderna herramienta desarrollada en la Universidad Politécnica de Valencia que te permitirá ver simultáneamente las presentaciones y al profesor mientras se desarrollan los conceptos de cada capítulo.

Ejercicio: La mejor forma de aprender es haciendo. No tendrás más que ir siguiendo los pasos uno tras otro para descubrir cómo se resuelve el ejercicio propuesto. Para que no se te haga pesado teclear todo el código, te proponemos que lo copies y pegues desde la página web del curso.

Práctica: Este será el momento de que tomes la iniciativa y trates de resolver el problema que se propone. Recuerda que para aprender hay que practicar.

Asteroides: Ejercicios y prácticas que te permitirán desarrollar el videojuego Asteroides.

Mis Lugares: Ejercicios y prácticas que te permitirán desarrollar la aplicación Mis Lugares.

Solución: Te será de ayuda si tienes problemas al resolver una práctica, o si simplemente quieres comparar tu solución con otra diferente.

Nota sobre Java: Si no dominas el lenguaje de programación Java, podrás seguir este libro. Cada vez que aparezca algún concepto complejo sobre Java trataremos de aclararlo. NOTA: Sí que resulta imprescindible disponer de conocimientos sobre programación.

Recursos adicionales: Te proporcionamos la información clave que te ayudará en el desarrollo de tus aplicaciones.

Enlaces de interés: Internet te será de gran ayuda para completar la información necesaria para programar en Android. Te proponemos las páginas más interesantes de cada apartado.

Preguntas de repaso: ¿Has comprendido correctamente los aspectos clave? Sal de dudas haciendo los test de autoevaluación.

Referencias rápidas: Utiliza los anexos para localizar rápidamente esa palabra clave o esa clase que no recuerdas.

Trivial programación Android: Instálate esta app y mide tus conocimientos jugando en red contra otros oponentes.

De forma adicional, en la web www.androidcurso.com encontrarás:

• Tutoriales sobre Java: ¿Sabes lo que es la herencia, el polimorfismo o la sobrecarga en Java? Si no dominas el lenguaje de programación Java, te recomendamos que realices alguno de los tutoriales propuestos.

• Código abierto de proyectos Android: Muchos alumnos que han realizado un curso basado en este libro han tenido la generosidad de compartir sus proyectos con todos nosotros. Te recomendamos que consultes la lista de proyectos disponibles de código abierto: puedes aprender mucho estudiando su código. Cuando termines de leer este libro, también tú podrás hacer un proyecto como los que se muestran.

• Material adicional sobre Android: Encontrarás, además, nuevos tutoriales, vídeos, referencias, etc., no incluidos en el libro.

• Cursos online: Si te interesa ampliar tu formación, puedes matricularte en cursos sobre Android impartidos por la Universidad Politécnica de Valencia en la plataforma EdX. Incluso puedes obtener un título de Especialización o de Máster de forma 100 % online.

CAPÍTULO 1.
Visión general y entorno de desarrollo

La telefonía móvil está cambiando la sociedad actual de una forma tan significativa como lo ha hecho Internet. Esta revolución no ha hecho más que empezar; los nuevos terminales ofrecen unas capacidades similares a un ordenador personal, lo que permite que puedan ser utilizados para leer el correo o navegar por Internet. Pero, a diferencia de un ordenador, un teléfono móvil siempre está en el bolsillo del usuario. Esto permite un nuevo abanico de aplicaciones mucho más cercanas al usuario. De hecho, muchos autores coinciden en afirmar que el nuevo ordenador personal del siglo XXI será un terminal móvil.

El lanzamiento de Android como nueva plataforma para el desarrollo de aplicaciones móviles ha causado una gran expectación y ha tenido una importante aceptación tanto por parte de los usuarios como por parte de la industria. En la actualidad se ha convertido en la alternativa dominante frente a otras plataformas como iPhone o Windows Phone.

A lo largo de este capítulo veremos las características de Android que lo hacen diferente de sus competidores. Se explicará también cómo instalar y trabajar con el entorno de desarrollo (Android Studio).

Objetivos:

• Conocer las características de Android, destacando los aspectos que lo hacen diferente de sus competidores.

• Estudiar la arquitectura interna de Android.

• Aprender a instalar y trabajar con el entorno de desarrollo (Android SDK).

• Enumerar las principales versiones de Android y aprender a elegir la más idónea para desarrollar nuestras aplicaciones.

• Crear una primera aplicación y estudiar su estructura de un proyecto en Android.

• Conocer dónde podemos conseguir documentación sobre Android.

• Aprender a utilizar herramientas para detectar errores en el código.

1.1. ¿Qué hace que Android sea especial?

Como hemos comentado, existen muchas plataformas para móviles (Apple iOS, Windows Phone, BlackBerry, Palm, Java Micro Edition, Linux Mobile (LiMo), Firefox OS, etc.); sin embargo, Android presenta una serie de características que lo hacen diferente. Es el primero que combina en una misma solución las siguientes cualidades:

• Plataforma abierta. Es una plataforma de desarrollo libre basada en Linux y de código abierto. Una de sus grandes ventajas es que se puede usar y customizar el sistema sin pagar royalties.

• Adaptable a diversos tipos de hardware. Android no ha sido diseñado exclusivamente para su uso en teléfonos y tabletas. Hoy en día podemos encontrar relojes, gafas, cámaras, TV, sistema para automóviles, electrodomésticos y una gran variedad de sistemas empotrados que se basan en este sistema operativo, lo cual tiene sus evidentes ventajas, pero también va a suponer un esfuerzo adicional para el programador. La aplicación ha de funcionar correctamente en dispositivos con una gran variedad de tipos de entrada, pantalla, memoria, etc. Esta característica contrasta con la estrategia de Apple: en iOS tenemos que desarrollar una aplicación para iPhone y otra diferente para iPad.

• Portabilidad asegurada. Las aplicaciones finales son desarrolladas en Java, lo que nos asegura que podrán ser ejecutadas en cualquier tipo de CPU, tanto presente como futuro. Esto se consigue gracias al concepto de máquina virtual.

• Arquitectura basada en componentes inspirados en Internet. Por ejemplo, el diseño de la interfaz de usuario se hace en XML, lo que permite que una misma aplicación se ejecute en un reloj de pantalla reducida o en un televisor.

• Filosofía de dispositivo siempre conectado a Internet. Muchas aplicaciones solo funcionan si disponemos de una conexión permanente a Internet. Por ejemplo, comunicaciones interpersonales o navegación con mapas.

• Gran cantidad de servicios incorporados. Por ejemplo, localización basada tanto en GPS como en redes, bases de datos con SQL, reconocimiento y síntesis de voz, navegador, multimedia, etc.

• Aceptable nivel de seguridad. Los programas se encuentran aislados unos de otros gracias al concepto de ejecución dentro de una caja, que hereda de Linux. Además, cada aplicación dispone de una serie de permisos que limitan su rango de actuación (servicios de localización, acceso a Internet, etc.). Desde la versión 6.0 el usuario puede conceder o retirar permisos a las aplicaciones en cualquier momento.

• Optimizado para baja potencia y poca memoria. En el diseño de Android se ha tenido en cuenta el hardware específico de los dispositivos móviles. Por ejemplo, Android utiliza la máquina virtual ART (o Dalvik en versiones antiguas). Se trata de una implementación de Google de la máquina virtual Java optimizada para dispositivos móviles.

• Alta calidad de gráficos y sonido. Gráficos vectoriales suavizados, animaciones, gráficos en 3D basados en OpenGL. Incorpora los códecs estándares más comunes de audio y vídeo, incluyendo H.264 (AVC), MP3, AAC, etc.

Como hemos visto, Android combina características muy interesantes. No obstante, la pregunta del millón es: ¿se convertirá Android en el sistema operativo (SO) estándar para dispositivos móviles? Para contestar a esta pregunta habrá que ver la evolución del iPhone de Apple y cuál es la respuesta de Windows con el lanzamiento de su SO para móviles. No obstante, Android ha alcanzado un 85 % de cuota de mercado (90 % en España), cosa que lo deja en una posición predominante que es difícil que pierda a corto plazo.

En conclusión, Android nos ofrece una forma sencilla y novedosa de implementar potentes aplicaciones para diferentes tipos de dispositivos. A lo largo de este texto trataremos de mostrar de la forma más sencilla posible cómo conseguirlo.

1.2. Los orígenes

Google adquiere Android Inc. en el año 2005. Se trataba de una pequeña compañía, recién creada, orientada a la producción de aplicaciones para terminales móviles. Ese mismo año empiezan a trabajar en la creación de una máquina virtual Java optimizada para móviles (Dalvik VM).

En el año 2007 se crea el consorcio Open Handset Alliance1 con el objetivo de desarrollar estándares abiertos para móviles. Está formado por Google, Intel, Texas Instruments, Motorola, T-Mobile, Samsung, Ericsson, Toshiba, Vodafone, NTT DoCoMo, Sprint Nextel y otros. Uno de los objetivos fundamentales de esta alianza es promover el diseño y la difusión de la plataforma Android. Sus miembros se han comprometido a publicar una parte importante de su propiedad intelectual como código abierto bajo licencia Apache v2.0.

En noviembre de 2007 se lanza una primera versión del Android SDK. Al año siguiente aparece el primer móvil con Android (T-Mobile G1). En octubre, Google libera el código fuente de Android, principalmente bajo licencia de código abierto Apache (licencia GPL v2 para el núcleo). Ese mismo mes se abre Android Market, para la descarga de aplicaciones. En abril de 2009, Google lanza la versión 1.5 del SDK, que incorpora nuevas características como el teclado en pantalla. A finales de 2009 se lanza la versión 2.0 y a lo largo de 2010, las versiones 2.1, 2.2 y 2.3.

Durante el año 2010, Android se consolida como uno de los sistemas operativos para móviles más utilizados, con resultados cercanos a iOS e incluso superando al sistema de Apple en EE.UU.

En el año 2011 se lanza la versión 3.x (Honeycomb), específica para tabletas, y la 4.0 (Ice Cream Sandwich), tanto para móviles como para tabletas. Durante ese año, Android se consolida como la plataforma para móviles más importante y alcanza una cuota de mercado superior al 50 %.

En 2012, Google cambia su estrategia en su tienda de descargas online, reemplazando Android Market por Google Play Store, donde en un solo portal unifica tanto la descarga de aplicaciones como la de contenidos. Ese año aparecen las versiones 4.1 y 4.2 (Jelly Bean). Android mantiene su espectacular crecimiento y alcanza, a finales de año, una cuota de mercado del 70 %.

En 2013 se lanzan las versiones 4.3 y 4.4 (KitKat). En 2014 se lanza la versión 5.0 (Lollipop). A finales de ese año, la cuota de mercado de Android llega al 85 %. En octubre de 2015 ha aparecido la versión 6.0, con el nombre de Marshmallow. En 2016 se lanzó la versión 7.0, Android Nougat. A finales de 2017 aparece la versión 8.0, con nombre Android Oreo. En agosto de 2018 se lanza la versión 9.0, Android Pie. En 2019 se lanza Android 10 y se abandonan así los nombres de dulces.

Vídeo[tutorial]: Introducción a la plataforma Android

Preguntas de repaso: Características y orígenes de Android

1.3. Comparativa con otras plataformas

En este apartado vamos a describir las características de las principales plataformas móviles disponibles en la actualidad. Dado la gran cantidad de datos que se indican, hemos utilizado una tabla para representar la información. De esta forma resulta más sencillo comparar las plataformas.



Tabla 1: Comparativa de las principales plataformas móviles (*Fuente www.statista.com).

Otro aspecto fundamental a la hora de comparar las plataformas móviles es su cuota de mercado. En la siguiente gráfica podemos ver un estudio realizado por la empresa Gartner Group, donde se muestra la evolución del mercado de los sistemas operativos para móviles según el número de terminales vendidos. Podemos destacar la desaparición de la plataforma Symbian de Nokia, el declive continuo de BlackBerry, el estancamiento de la plataforma de Windows, que parece que no despega, y el afianzamiento de la cuota de mercado de Apple en torno al 15 %. En la gráfica se puede apreciar como Apple consigue anualmente un aumento significativo de ventas coincidiendo con el lanzamiento de un nuevo terminal. Finalmente, cabe señalar el espectacular ascenso de la plataforma Android, que en seis años ha alcanzado una cuota de mercado superior al 80 %.


Figura 1: Porcentaje de teléfonos inteligentes vendidos en todo el mundo, hasta el primer trimestre de 2018, según su sistema operativo (fuente: Gartner Group).

Vídeo[tutorial]: Comparativa de las plataformas para móviles

Preguntas de repaso: Plataformas para móviles

1.4. Arquitectura de Android

El siguiente gráfico muestra la arquitectura de Android. Como se puede ver, está formada por cuatro capas. Una de las características más importantes es que todas las capas están basadas en software libre.


Figura 2: Arquitectura de Android.

1.4.1. El núcleo Linux

El núcleo de Android está formado por el sistema operativo Linux, versión 2.6. Esta capa proporciona servicios como la seguridad, el manejo de la memoria, el multiproceso, la pila de protocolos y el soporte de drivers para dispositivos.

Esta capa del modelo actúa como capa de abstracción entre el hardware y el resto de la pila. Por lo tanto, es la única dependiente del hardware.

1.4.2. Runtime de Android

Está basado en el concepto de máquina virtual utilizado en Java. Dadas las limitaciones de los dispositivos donde ha de correr Android (poca memoria y procesador limitado), no fue posible utilizar una máquina virtual Java estándar. Google tomó la decisión de crear una nueva, la máquina virtual Dalvik, que respondiera mejor a estas limitaciones.

Entre las características de la máquina virtual Dalvik que facilitan esta optimización de recursos se encuentra la ejecución de ficheros Dalvik ejecutables (.dex) –formato optimizado para ahorrar memoria–. Además, está basada en registros. Cada aplicación corre en su propio proceso Linux con su propia instancia de la máquina virtual Dalvik. Delega al kernel de Linux algunas funciones como threading y el manejo de la memoria a bajo nivel.

A partir de Android 5.0 se reemplaza Dalvik por ART. Esta nueva máquina virtual consigue reducir el tiempo de ejecución del código Java hasta en un 33 %.

También se incluye en el runtime de Android el módulo Core Libraries, con la mayoría de las librerías disponibles en el lenguaje Java.

1.4.3. Librerías nativas

Incluye un conjunto de librerías en C/C++ usadas en varios componentes de Android. Están compiladas en código nativo del procesador. Muchas de las librerías utilizan proyectos de código abierto. Algunas de estas librerías son:

• System C library: una derivación de la librería BSD de C estándar (libc), adaptada para dispositivos embebidos basados en Linux.

• Media Framework: librería basada en OpenCORE de PacketVideo. Soporta códecs de reproducción y grabación de multitud de formatos de audio y vídeo e imágenes MPEG4, H.264, MP3, AAC, AMR, JPG y PNG.

• Surface Manager: maneja el acceso al subsistema de representación gráfica en 2D y 3D.

• WebKit/Chromium: soporta el navegador web utilizado en Android y en la vista WebView. En la versión 4.4, WebKit ha sido reemplazada por Chromium/Blink, que es la base del navegador Chrome de Google.

• SGL: motor de gráficos 2D.

• Librerías 3D: implementación basada en OpenGL ES 1.0 API. Las librerías utilizan el acelerador hardware 3D si está disponible, o el software altamente optimizado de proyección 3D.

• FreeType: fuentes en bitmap y renderizado vectorial.

• SQLite: potente y ligero motor de bases de datos relacionales disponible para todas las aplicaciones.

• SSL: proporciona servicios de encriptación Secure Socket Layer (capa de conexión segura).

1.4.4. Entorno de aplicación

Proporciona una plataforma de desarrollo libre para aplicaciones con gran riqueza e innovaciones (sensores, localización, servicios, barra de notificaciones, etc.).

Esta capa ha sido diseñada para simplificar la reutilización de componentes. Las aplicaciones pueden publicar sus capacidades y otras pueden hacer uso de ellas (sujetas a las restricciones de seguridad). Este mismo mecanismo permite a los usuarios reemplazar componentes.

Los servicios más importantes que incluye son:

• Views: extenso conjunto de vistas (parte visual de los componentes).

• Resource Manager: proporciona acceso a recursos que no son en código.

• Activity Manager: maneja el ciclo de vida de las aplicaciones y proporciona un sistema de navegación entre ellas.

• Notification Manager: permite a las aplicaciones mostrar alertas personalizadas en la barra de estado.

• Content Providers: mecanismo sencillo para acceder a datos de otras aplicaciones (como los contactos).

Una de las mayores fortalezas del entorno de aplicación de Android es que se aprovecha el lenguaje de programación Java. El SDK de Android no acaba de ofrecer para su estándar todo lo disponible del entorno de ejecución Java (JRE), pero es compatible con una fracción muy significativa de este.

1.4.5. Aplicaciones

Este nivel está formado por el conjunto de aplicaciones instaladas en una máquina Android. Todas las aplicaciones han de correr en la máquina virtual ART para garantizar la seguridad del sistema.

Normalmente las aplicaciones Android están escritas en Java o Kotlin. Para desarrollar este tipo de aplicaciones podemos utilizar el Android SDK. Existe otra opción consistente en desarrollar las aplicaciones utilizando C/C++. Para esta opción podemos utilizar el Android NDK (Native Development Kit)2.

Vídeo[tutorial]: La arquitectura de Android

Preguntas de repaso: La arquitectura de Android

1.5. Instalación del entorno de desarrollo

Google ha preparado el paquete de software Android SDK, que incorpora todas las herramientas necesarias para el desarrollo de aplicaciones en Android. En él se incluye: conversor de código, depurador, librerías, emuladores, documentación, etc. Todas estas herramientas son accesibles desde la línea de comandos.

No obstante, la mayoría de los desarrolladores prefieren utilizar un IDE (entorno de desarrollo integrado). Un IDE agrupa, en un entorno visual, un editor de código con todas las herramientas de desarrollo. Google recomienda utilizar Android Studio (basado en el IDE IntelliJ IDEA).

1.5.1. Instalación de la máquina virtual Java

Las aplicaciones Android están basadas en Java, por lo que necesitas instalar un software para ejecutar código Java en tu equipo. Este software se conoce como máquina virtual Java, entorno de ejecución Java, Java Runtime Environment (JRE) o Java Virtual Machine (JVM).

Es muy posible que ya tengas instalada la máquina virtual Java en tu equipo. Si es así, puedes pasar directamente a uno de los apartados siguientes. En caso de dudas, puedes pasar también al punto siguiente. Al concluirlo te indicará si la versión de la máquina virtual Java es incorrecta. En caso necesario, regresa a este punto para instalar una que sea adecuada.

Para instalar la máquina virtual Java accede a http://www.java.com/es/download/, descarga e instala el fichero correspondiente a tu sistema operativo.

1.5.2. Instalación de Android Studio

En la edición de Google I/O 2014 se lanzó la primera versión estable de Android Studio. Se trata de un entorno de desarrollo para Android basado en el IDE IntelliJ IDEA. Entre las novedades introducidas destacamos:

• Construcción de proyectos usando la herramienta Gradle.

• Previsualización simultánea de un layout en varios tipos de dispositivos.

• Facilidades para el testeo de código basado en JUnit.

• Integración con herramientas de gestión de versiones (como GitHub).

• Desarrollo en un mismo proyecto de diferentes versiones (como Android Wear, Android TV y Android Auto).

Ejercicio: Instalación de Android Studio

NOTA: Puedes encontrar una descripción más detallada de la instalación en https://developer.android.com/studio/install.html

1. Descarga el paquete correspondiente a tu versión de la siguiente dirección:

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

2. Ejecuta el fichero obtenido en el paso anterior:

3. Selecciona todos los componentes a instalar y pulsa Next.


4. Acepta el contrato de licencia y selecciona las carpetas donde quieres instalar el IDE Android Studio y el SDK. En el resto de ventanas puedes utilizar las opciones por defecto. En la última ventana indica que quieres arrancar Android Studio.

5. Primero te preguntará si quieres importar la configuración desde una instalación anterior. Luego verificará si hay actualizaciones del SDK.

6. Tras pulsar en Finish pasamos a la ventana de bienvenida:


7. Comienza pulsando en Configure. Aparecerán varias opciones, selecciona SDK Manager. Esta herramienta es de gran utilidad para verificar si existen actualizaciones del SDK o nuevas versiones de la plataforma. Podrás acceder a ella desde la ventana principal de Android Studio pulsando en el botón SDK Manager:


8. Al entrar en el SDK Manager te muestra los paquetes instalados y los que puedes instalar o actualizar:


En la lengüeta SDK Plataforms se muestran los paquetes de plataforma. Pulsa en Show Package Details para ver los diferentes paquetes. Siempre es conveniente que tengas instalados los siguientes paquetes de la última plataforma disponible:

• Android SDK Platform X (donde X es la última versión disponible)

• Sources for Android X (no es imprescindible)

• Google APIs … System Image (para crear emuladores con Google APIs)

• Google Play … System Image (para crear emuladores con Google APIs + Google Play)

En la lengüeta SDK Tools se muestran paquetes con herramientas de la plataforma. Siempre es conveniente que tengas actualizados los siguientes paquetes:

• Android SDK Build-Tools

• Android SDK Platform-tools

• Android SDK Tools

• Google Play services

• Support Repository

Recursos adicionales: Teclas de acceso rápido en Android Studio

Alt-Intro: Solución rápida (Ej. añade imports de las clases no resueltas).

Shift-F10 (Ctrl-R en Mac): Ejecuta el proyecto.

Shift-F9 (Ctrl-D en Mac): Depura el proyecto.

Shift-F6: Cambia el nombre de un identificador.

Ctrl-Alt-L (Option-Cmd-L en Mac): Formatea automáticamente el código.

Ctrl-Q (F1 en Mac): Muestra documentación del código.

Ctrl-P: Muestra parámetros del método seleccionado.

F4 (Cmd-↓ en Mac): Salta a declaración.

Ctrl-Y (Cmd-Espacio en Mac): Borra línea.

Alt-Insert (Cmd-N en Mac): Inserta método.

Enlaces de interés: Conoce Android Studio

https://developer.android.com/studio/intro/index.html?hl=es-419

Preguntas de repaso: Instalación y entorno de desarrollo

1.5.3. Creación de un dispositivo virtual Android (AVD)

Un dispositivo virtual Android (AVD) te va a permitir emular en tu ordenador diferentes tipos de dispositivos basados en Android. De esta forma podrás probar tus aplicaciones en una gran variedad de teléfonos, tabletas, relojes o TV con cualquier versión de Android, tamaño de pantalla o tipo de entrada.

Ejercicio: Creación de un dispositivo virtual Android (AVD)

1. Pulsa el botón AVD Manager:


Aparecerá la lista con los AVD creados. La primera vez estará vacía.

2. Pulsa a continuación el botón Create Virtual Device... para crear un nuevo AVD. Aparecerá la siguiente ventana:


3. En la primera columna podremos seleccionar el tipo de dispositivo a emular (móvil, tableta, dispositivo wearable o Google TV). A la derecha, se muestran distintos dispositivos que emulan dispositivos reales de la familia Nexus y también otros genéricos. Junto al nombre de cada dispositivo, se indica si tiene la posibilidad de incorporar Google Play, el tamaño de la pantalla en pulgadas, la resolución y el tipo de densidad gráfica. NOTA: Los tipos de pantalla se clasifican en Android según su densidad gráfica: ldpi, mdpi, hdpi, xhdpi, ... Véase sección 2.6 Recursos alternativos.

Si quisieras añadir a esta lista crear un nuevo tipo de dispositivo, puedes seleccionar New Hardware Profile. Podrás indicar las principales características del dispositivo y ponerle un nombre. Usando Clone Device podrás crear un nuevo tipo de AVD a partir del actual. Pulsando con el botón derecho sobre un tipo de dispositivo podrás eliminarlos o exportarlos a un fichero.

4. Pulsa Next para pasar a la siguiente ventana, donde podrás seleccionar la imagen del sistema que tendrá el dispositivo y el tipo de procesador:


Observa cómo las distintas versiones de Android se pueden seleccionar, solo con el código abierto de Android, añadiendo las API de Google (para utilizar servicios como Google Maps) o incluso incorporando Google Play (para poder instalar apps desde la tienda de Google).

5. Pulsa Next para pasar a la última ventana. Se nos mostrará un resumen con las opciones seleccionadas; además, podremos seleccionar la orientación inicial del AVD, si queremos usar el coprocesador gráfico (GPU) de nuestro ordenador o si queremos que dibuje un marco alrededor del emulador simulando un dispositivo real.

6. Pulsa en el botón Show Avanced Settings para que se muestren algunas configuraciones adicionales:


Podemos hacer que el emulador utilice la cámara o teclado de nuestro ordenador. También podemos limitar la velocidad y latencia en el acceso a la red. Finalmente, podremos ajustar la memoria utilizada: RAM total del dispositivo, memoria dinámica usada por Java y memoria para almacenamiento, tanto interna como externa.

7. Una vez introducida la configuración deseada, pulsa el botón Finish. Aparecerá el dispositivo creado en la lista:


8. Para arrancarlo, pulsa el botón con forma de triángulo verde que encontrarás en la columna de la derecha. Es posible que te pregunte por la entrada de vídeo para emular la cámara del AVD.


NOTA: Algunas características de hardware no están disponibles en el emulador; por ejemplo, el multi-touch o los sensores.

Vídeo[tutorial]: Creación de dispositivos virtuales (AVD)

Recursos adicionales: Teclas de acceso rápido en un emulador

Inicio: Tecla Home.

F2: Tecla Menú.

Esc: Tecla de volver.

F7: Tecla On/Off

Ctrl-F5/Ctrl-F6 o KeyPad +/-: Control de volumen de audio.

Ctrl-F11 o KeyPad 7: Cambia la orientación entre horizontal y vertical.

1.6. Las versiones de Android y niveles de API

Antes de empezar a programar en Android hay que elegir la versión del sistema para la que deseamos realizar la aplicación. Es muy importante observar que hay clases y métodos que están disponibles a partir de una versión; si las vamos a usar, hemos de conocer la versión mínima necesaria.

Cuando se ha lanzado una nueva plataforma, siempre ha sido compatible con las versiones anteriores. Es decir, solo se añaden nuevas funcionalidades, y en el caso de modificar alguna funcionalidad, no se elimina, si no que se etiqueta como obsoleta, pero normalmente se puede continuar utilizando.

A continuación se describen las plataformas lanzadas hasta la fecha, con una breve descripción de las novedades introducidas. Las plataformas se identifican de tres formas alternativas: versión, nivel de API y nombre comercial. El nivel de API corresponde a números enteros, comenzando desde 1. Para los nombres comerciales se han elegido postres en orden alfabético: Cupcake (v1.5), Donut (v1.6), Éclair (v2.0), Froyo (v2.2), Gingerbread (v2.3), etc. Las dos primeras versiones, que hubieran correspondido a las letras A y B, no recibieron nombre.

Vídeo[tutorial]: Descripción de las versiones de Android

1.6.1. Las primeras versiones
Android 1.0 Nivel de API 1 (septiembre 2008)

Primera versión de Android. Nunca se utilizó comercialmente, por lo que no tiene mucho sentido desarrollarla para esta plataforma.

Android 1.1 Nivel de API 2 (febrero 2009)

No se añadieron apenas funcionalidades: simplemente se arreglaron algunos errores de la versión anterior. Es la opción a escoger si queremos desarrollar una aplicación compatible con todos los dispositivos Android. No obstante, apenas existen usuarios con esta versión.

1.6.2. Cupcake
Android 1.5 Nivel de API 3 (abril 2009)

Es la primera versión con algún usuario, aunque en la actualidad apenas quedan. Como novedades, se incorpora la posibilidad de teclado en pantalla con predicción de texto (ya no es necesario que los terminales tengan un teclado físico), así como la capacidad de grabación avanzada de audio y vídeo. También aparecen los widgets de escritorio y live folders. Incorpora soporte para Bluetooth estéreo, por lo que permite conectarse automáticamente a auriculares Bluetooth. Las transiciones entre ventanas se realizan mediante animaciones.


1.6.3. Donut
Android 1.6 Nivel de API 4 (septiembre 2009)

Permite capacidades de búsqueda avanzada en todo el dispositivo. También se incorpora gestures y la síntesis de texto a voz. Asimismo, se facilita que una aplicación pueda trabajar con diferentes densidades de pantalla. Soporte para resolución de pantallas WVGA. Aparece un nuevo atributo XML, onClick, que puede especificarse en una vista. Soporte para CDMA/EVDO, 802.1x y VPNs.


1.6.4. Éclair
Android 2.0 Nivel de API 5 (octubre 2009)

Esta versión de API apenas cuenta con usuarios, dado que la mayoría de los fabricantes pasaron directamente de la versión 1.6 a la 2.1. Como novedades cabría destacar que incorpora una API para manejar el Bluetooth 2.1. Ofrece un servicio centralizado de manejo de cuentas. Se aumenta el número de tamaños de ventana y resoluciones soportadas. Nueva interfaz del navegador y soporte para HTML5. Mejoras en el calendario y soporte para Microsoft Exchange. La clase MotionEvent ahora soporta eventos en pantallas multitáctil.


Android 2.1 Nivel de API 7 (enero 2010)

Se considera una actualización menor, por lo que la siguieron llamando Éclair. Destacamos el reconocimiento de voz, que permite introducir un campo de texto dictando sin necesidad de utilizar el teclado. También permite desarrollar fondos de pantalla animados. Se puede obtener información sobre la señal de la red actual que posea el dispositivo. En el paquete WebKit se incluyen nuevos métodos para manipular bases de datos almacenadas en Internet.

1.6.5. Froyo
Android 2.2 Nivel de API 8 (mayo 2010)

Como característica más destacada se puede indicar la mejora de velocidad de ejecución de las aplicaciones (ejecución del código de la CPU de 2 a 5 veces más rápido que en la versión 2.1, de acuerdo con varios benchmarks). Esto se consigue con la introducción de un nuevo compilador JIT de la máquina Dalvik.


Se añaden varias mejoras relacionadas con el navegador web, como el soporte de Adobe Flash 10.1 y la incorporación del motor Javascript V8 utilizado en Chrome.

El desarrollo de aplicaciones permite las siguientes novedades: se puede preguntar al usuario si desea instalar una aplicación en un medio de almacenamiento externo (como una tarjeta SD), como alternativa a la instalación en la memoria interna del dispositivo; las aplicaciones se actualizan de forma automática cuando aparece una nueva versión; proporciona un servicio para la copia de seguridad de datos que se puede realizar desde la propia aplicación para garantizar al usuario el mantenimiento de sus datos; y por último, se facilita que las aplicaciones interaccionen con el reconocimiento de voz y que terceras partes proporcionen nuevos motores de reconocimiento.

Se mejora la conectividad: ahora podemos utilizar nuestro teléfono para dar acceso a Internet a otros dispositivos (tethering), tanto por USB como por Wi-Fi. También se añade el soporte a Wi-Fi IEEE 802.11n y notificaciones push.

Se añaden varias mejoras en diferentes componentes: en la API gráfica OpenGL ES; por ejemplo, se pasa a soportar la versión 2.0. Para finalizar, permite definir modos de interfaz de usuario («automóvil» y «noche») para que las aplicaciones se configuren según el modo seleccionado por el usuario.

1.6.6. Gingerbread
Android 2.3 Nivel de API 9 (diciembre 2010)

Debido al éxito de Android en las nuevas tabletas, ahora soporta mayores tamaños de pantalla y resoluciones (WXGA y superiores).


Incorpora una nueva interfaz de usuario con un diseño actualizado. Dentro de las mejoras de la interfaz de usuario destacamos la mejora de la funcionalidad de cortar, copiar y pegar y un teclado en pantalla con capacidad multitáctil. Se incluye soporte nativo para varias cámaras, pensado en la segunda cámara usada en videoconferencia. La incorporación de esta segunda cámara ha propiciado la inclusión de reconocimiento facial para identificar al usuario del terminal.

La máquina virtual Dalvik introduce un nuevo recolector de basura que minimiza las pausas de la aplicación, ayudando a garantizar una mejor animación y el aumento de la capacidad de respuesta en juegos y aplicaciones similares. Se trata de corregir, así, una de las lacras de este sistema operativo móvil, que en versiones previas no ha sido capaz de cerrar bien las aplicaciones en desuso. Se dispone de un mayor apoyo para el desarrollo de código nativo (NDK). También se mejora la gestión de energía y el control de aplicaciones, y se cambia el sistema de ficheros, que pasa de YAFFS a ext4.

Entre otras novedades destacamos: el soporte nativo para telefonía sobre Internet VoIP/SIP; el soporte para reproducción de vídeo WebM/VP8 y codificación de audio AAC; el soporte para la tecnología NFC; las facilidades en el audio, los gráficos y las entradas para los desarrolladores de juegos; el soporte nativo para más sensores (como giroscopios y barómetros), y un gestor de descargas para las descargas largas.

1.6.7. Honeycomb
Android 3.0 Nivel de API 11 (febrero 2011)

Para mejorar la experiencia de Android en las nuevas tabletas se lanza la versión 3.0 optimizada para dispositivos con pantallas grandes. La nueva interfaz de usuario ha sido completamente rediseñada con paradigmas nuevos para la interacción y navegación. Entre las novedades introducidas destacan: los fragments, con los que podemos diseñar diferentes elementos de la interfaz de usuario; la barra de acciones, donde las aplicaciones pueden mostrar un menú siempre visible; las teclas físicas son reemplazadas por teclas en pantalla; se mejoran las notificaciones, arrastrar y soltar y las operaciones de cortar y pegar.


La nueva interfaz se pone a disposición de todas las aplicaciones, incluso las construidas para versiones anteriores de la plataforma. Esto se consigue gracias a la introducción de librerías de compatibilidad3 que pueden ser utilizadas en versiones anteriores a la 3.0.

Se mejoran los gráficos 2D/3D gracias al renderizador OpenGL acelerado por hardware. Aparecerá el nuevo motor de gráficos Renderscript, que saca mayor rendimiento al hardware e incorpora su propia API. Se incorpora un nuevo motor de animaciones mucho más flexible, conocido como animación de propiedades.

Primera versión de la plataforma que soporta procesadores multinúcleo. La máquina virtual Dalvik ha sido optimizada para permitir multiprocesado, lo que permite una ejecución más rápida de las aplicaciones, incluso aquellas que son de hilo único.

Se incorporan varias mejoras multimedia, como listas de reproducción M3U a través de HTTP Live Streaming, soporte a la protección de derechos musicales (DRM) y soporte para la transferencia de archivos multimedia a través de USB con los protocolos MTP y PTP.

En esta versión se añaden nuevas alternativas de conectividad, como las nuevas API de Bluetooth A2DP para streaming de audio y HSP para conexiones seguras con dispositivos. También, se permite conectar teclados completos por USB o Bluetooth.

Se mejora el uso de los dispositivos en un entorno empresarial. Entre las novedades introducidas destacamos las nuevas políticas administrativas con encriptación del almacenamiento, caducidad de contraseña y mejoras para administrar los dispositivos de empresa de forma eficaz.

A pesar de la nueva interfaz gráfica optimizada para tabletas, Android 3.0 es compatible con las aplicaciones creadas para versiones anteriores.

Android 3.1 Nivel de API 12 (mayo 2011)

Se permite manejar dispositivos conectados por USB (tanto host como dispositivo). Protocolo de transferencia de fotos y vídeo (PTP/MTP) y de tiempo real (RTP).

Android 3.2 Nivel de API 13 (julio 2011)

Optimizaciones para distintos tipos de tableta. Zum compatible para aplicaciones de tamaño fijo. Sincronización multimedia desde SD.

1.6.8. Ice Cream Sandwich
Android 4.0 Nivel de API 14 (octubre 2011)

La característica más importante es que se unifican las dos versiones anteriores (2.x para teléfonos y 3.x para tabletas) en una sola compatible con cualquier tipo de dispositivo. A continuación destacamos algunas de las características más interesantes.


Se introduce una nueva interfaz de usuario totalmente renovada; por ejemplo, se reemplazan los botones físicos por botones en pantalla (como ocurría en las versiones 3.x). Nueva API de reconocimiento facial que, entre otras muchas aplicaciones, permite al propietario desbloquear el teléfono. También se mejora en el reconocimiento de voz; por ejemplo, se puede empezar a hablar sin esperar la conexión con el servidor.

Aparece un nuevo gestor de tráfico de datos por Internet, donde podremos ver el consumo de forma gráfica y donde podemos definir los límites de ese consumo para evitar cargos inesperados con la operadora. Incorpora herramientas para la edición de imágenes en tiempo real, para distorsionar, manipular e interactuar con la imagen en el momento de ser capturada. Se mejora la API para comunicaciones por NFC y la integración con redes sociales.

En diciembre de 2011 aparece una actualización de mantenimiento (versión 4.0.2) que no aumenta el nivel de API.

Android 4.0.3 Nivel de API 15 (diciembre 2011)

Se introducen ligeras mejoras en algunas API, incluyendo las de redes sociales, calendario, revisor ortográfico, texto a voz y bases de datos, entre otras. En marzo de 2012 aparece la actualización 4.0.4.

1.6.9. Jelly Bean
Android 4.1 Nivel de API 16 (julio 2012)

En esta versión se hace hincapié en mejorar un punto débil de Android: la fluidez de la interfaz de usuario. Con este propósito se incorporan varias técnicas: sincronismo vertical, triple búfer y aumento de la velocidad del procesador al tocar la pantalla.


Se mejoran las notificaciones con un sistema de información expandible personalizada. Los widgets de escritorio pueden ajustar su tamaño y hacerse sitio de forma automática al situarlos en el escritorio. El dictado por voz puede realizarse sin conexión a Internet (de momento, solo en inglés).

Se introducen varias mejoras en Google Search. Se potencia la búsqueda por voz con resultados en forma de ficha. La función Google Now permite utilizar información de posición, agenda y hora en las búsquedas.

Se incorporan nuevos soportes para usuarios internacionales, como texto bidireccional y teclados instalables. Para mejorar la seguridad, las aplicaciones son cifradas. También se permiten actualizaciones parciales de aplicaciones.

Android 4.2 Nivel de API 17 (noviembre 2012)

Una de las novedades más importantes es que podemos crear varias cuentas de usuario en el mismo dispositivo. Aunque esta característica solo está disponible en tabletas. Cada cuenta tendrá sus propias aplicaciones y su propia configuración.

Los widgets de escritorio pueden aparecer en la pantalla de bloqueo. Se incorpora un nuevo teclado predictivo deslizante al estilo Swype. Posibilidad de conectar dispositivo y TVHD mediante Wi-Fi (Miracast). Mejoras menores en las notificaciones. Nueva aplicación de cámara que incorpora la funcionalidad Photo Sphere para hacer fotos panorámicas inmersivas (en 360º).

Android 4.3 Nivel de API 18 (julio 2013)

Esta versión introduce mejoras en múltiples áreas. Entre ellas los perfiles restringidos (disponible solo en tabletas), que permiten controlar los derechos de los usuarios para ejecutar aplicaciones específicas y para tener acceso a datos específicos. Igualmente, los programadores pueden definir restricciones en las apps, que los propietarios pueden activar si quieren. Se da soporte para Bluetooth Low Energy (BLE), que permite a los dispositivos Android comunicarse con los periféricos con bajo consumo de energía. Se agregan nuevas características para la codificación, transmisión y multiplexación de datos multimedia. Se da soporte para OpenGL ES 3.0. Se mejora la seguridad para gestionar y ocultar las claves privadas y credenciales.

1.6.10. KitKat
Android 4.4 Nivel de API 19 (octubre 2013)

Aunque se esperaba la versión 5.0 y con el nombre de Key Lime Pie, Google sorprendió con el cambio de nombre, que se debió a un acuerdo con Nestlé para asociar ambas marcas.


El principal objetivo de la versión 4.4 es hacer que Android esté disponible en una gama aún más amplia de dispositivos, incluyendo aquellos con tamaños de memoria RAM de solo 512 MB. Para ello, todos los componentes principales de Android han sido recortados para reducir sus requerimientos de memoria, y se ha creado una nueva API que permite adaptar el comportamiento de la aplicación en dispositivos con poca memoria.

Más visibles son algunas nuevas características de la interfaz de usuario. El modo de inmersión en pantalla completa oculta todas las interfaces del sistema (barras de navegación y de estado), de tal manera que una aplicación puede aprovechar el tamaño de la pantalla completa. WebViews (componente de la interfaz de usuario para mostrar las páginas web) se basa ahora en el software de Chrome de Google y, por lo tanto, puede mostrar contenido basado en HTM5.

Se mejora la conectividad con soporte de NFC para emular tarjetas de pago tipo HCE, varios protocolos sobre Bluetooth y soporte para mandos infrarrojos. También se mejoran los sensores para disminuir su consumo y se incorpora un sensor contador de pasos.

Se facilita el acceso de las aplicaciones a la nube con un nuevo marco de almacenamiento. Este marco incorpora un tipo específico de content provider conocido como document provider, nuevas intenciones para abrir y crear documentos y una ventana de diálogo que permite al usuario seleccionar ficheros. Se incorpora un administrador de impresión para enviar documentos a través de Wi-Fi a una impresora. También se añade un content provider para gestionar los SMS.

Desde una perspectiva técnica, hay que destacar la introducción de la nueva máquina virtual ART, que consigue tiempos de ejecución muy superiores a la máquina Dalvik. Sin embargo, todavía está en una etapa experimental. Por defecto se utiliza la máquina virtual Dalvik, y se permite a los programadores activar opcionalmente ART para verificar que sus aplicaciones funcionan correctamente.

Vídeo[tutorial]: Android 4.4 KitKat

1.6.11. Lollipop
Android 5.0 Nivel de API 21 (noviembre 2014)

La novedad más importante de Lollipop es la extensión de Android a nuevas plataformas, incluyendo Android Wear, Android TV y Android Auto. Hay un cambio significativo en la arquitectura, al utilizar la máquina virtual ART en lugar de Dalvik. Esta novedad ya había sido incorporada en la versión anterior a modo de prueba. ART mejora de forma considerable el tiempo de ejecución del código escrito en Java. Además se soporta dispositivos de 64 bits en procesadores ARM, x86, y MIPS. Muchas aplicaciones del sistema (Chrome, Gmail, …) se han incorporado en código nativo para una ejecución más rápida.


Desde el punto de vista del consumo de batería, hay que resaltar que en Lollipop el modo de ahorro de batería se activa por defecto. Este modo desconecta algunos componentes en caso de que la batería esté baja. Se incorpora una nueva API (android.app.job.JobScheduler) que nos permite que ciertos trabajos se realicen solo cuando se cumplan determinadas condiciones (por ejemplo con el dispositivo cargando). También se incluyen completas estadísticas para analizar el consumo que nuestras aplicaciones hacen de la batería.

En el campo Gráfico Android Lollipop incorpora soporte nativo para OpenGL ES 3.1. Además esta versión permite añadir a nuestras aplicaciones un paquete de extensión con funcionalidades gráficas avanzadas (fragment shader, tessellation, geometry shaders, ASTC, …).

Otro aspecto innovador de la nueva versión lo encontramos en el diseño de la interfaz de usuario. Se han cambiado los iconos, incluyendo los de la parte inferior (Retroceder, Inicio y Aplicaciones), que ahora son un triángulo, un círculo y un cuadrado. El nuevo enfoque se centra en Material Design (http://www.google.com/design/material-design.pdf). Consiste en una guía completa para el diseño visual, el movimiento y las interacciones a través de plataformas y dispositivos. Google pretende aplicar esta iniciativa a todas las plataformas, incluyendo wearables y Google TV. La nueva versión también incluye varias mejoras para controlar las notificaciones. Ahora son más parecidas a las tarjetas de Google Now y pueden verse en la pantalla de bloqueo.


Se incorporan nuevos sensores como el de pulso cardiaco, el de inclinación (para reconocer el tipo de actividad del usuario), y sensores de interacción compuestos para detectar ciertos gestos.

Como curiosidad la nueva versión introduce un modo de bloqueo que impide al usuario salir de una aplicación y bloquea las notificaciones. Esto podría utilizarse, por ejemplo, para que mientras un usuario realiza un examen, no pueda ver las notificaciones, acceder a otras aplicaciones, o volver a la pantalla de inicio.

Vídeo[tutorial]: Android 5.0 Lollipop

Android 5.1 Nivel de API 22 (marzo 2015)

Se añaden algunas mejoras a nivel de usuario en los ajustes rápidos. A nivel de API se añade soporte para varias tarjetas SIM en un mismo teléfono; la clase AndroidHttpClient se marca como obsoleta; y se añade un API para que las empresas proveedoras de servicios de telecomunicación puedan distribuir software de forma segura a través de Google Play. La característica más interesante es que para poder acceder a esta API la aplicación ha de estar firmada con un certificado que coincida con el que el usuario tiene en su tarjeta UICC.

1.6.12. Marshmallow
Android 6.0 Nivel de API 23 (octubre 2015)

Una de las novedades más interesantes es el administrador de permisos. Los usuarios podrán conceder o retirar ciertos permisos a cada aplicación. Con esto el sistema da mucha más protección a la privacidad de los usuarios.


Ahora, el sistema realiza una copia de seguridad automática de todos los datos de las aplicaciones. Esto resulta muy útil al cambiar de dispositivo o tras restaurar valores de fábrica. Para disponer de esta funcionalidad simplemente usa el targer Android 6.0. No es necesario agregar código adicional.

Android 6.0 integra el asistente por voz Now on Tap. Es una evolución de Google Now más integrada con las aplicaciones. Se activa con pulsación larga de home. Aparecerán tarjetas sobre la aplicación actual y lo que muestra. La aplicación actual podrá aportar información al asistente. En esta misma línea, se añade un API que permite interacciones basadas en voz. Es decir, si nuestra aplicación ha sido lanzada por voz, podremos solicitar una confirmación de voz del usuario, seleccionar de una lista de opciones o cualquier información que necesite.

Se introducen los enlaces de aplicación con los que podremos asociar la aplicación que abre una URL en función de su dominio web. Aunque muchos dispositivos ya lo permitían, en esta actualización se añade autentificación por huella digital a la API. Tu aplicación puede autentificar al usuario usando las credenciales para desbloquear su dispositivo (pin, patrón o contraseña). Esto libera al usuario de tener que recordar contraseñas específicas de la aplicación. Y te evita tener que implementar tu propia interfaz de autenticación.

Compartir con otros usuarios ahora es más fácil con Direct Share. Permite no solo escoger la aplicación con la que compartes, si no también el usuario. Si tu aplicación es un posible destino para compartir vas a poder indicar al sistema la lista de usuarios que pueden recibir información.

En Android 6.0 podemos utilizar parte de un dispositivo de almacenamiento externo, para que sea usado como almacenamiento interno. Podemos fragmentar, formatear y encriptar una tarjeta SD para ser usada como memoria interna. También podemos montar y extraer lápices de memoria USB de forma nativa.

Se incorpora la plataforma de pagos abierta Android Pay que combina NFC y Host Card Emulation. El nuevo gestor de batería, Doze, realiza un uso más eficiente de los recursos cuando el dispositivo está en reposo, con lo que podemos obtener dos horas extras de autonomía. Se da soporte de forma nativa a pantallas 4 K, lápices Bluetooth, múltiples tarjetas SIM y linterna. Mejoras de posicionamiento utilizando redes WiFi y dispositivos Bluetooth.

Vídeo[tutorial]: Android 6.0 Marshmallow

1.6.13. Android Nougat
Android 7.0 Nivel de API 24 (julio 2016)

Ahora los usuarios pueden abrir varias aplicaciones al mismo tiempo en la pantalla. Puedes configurar tu aplicación para que se visualice con unas dimensiones mínimas o inhabilitar la visualización de ventanas múltiples.


Las notificaciones han sido rediseñadas para un uso más ágil. Hay más opciones para personalizar el estilo de los mensajes (MessageStyle). Puedes agrupar notificaciones por temas o programar una respuesta directa.

En la versión anterior se utilizaba una estrategia de compilación Ahead of Time (AOT): cuando se descargaba una aplicación, su código era traducido de bytecodes a código nativo, lo que mejoraba los tiempos de ejecución. En la nueva versión se incorpora también la compilación Just in Time (JIT), donde no se compila hasta que el código va a ser ejecutado. Android 7.0 propone un planteamiento mixto según el perfil del código. Los métodos directos se compilan previamente (AOT), mientras que otras partes no se compilan hasta que se usan (JIT). Aunque AOT puede introducir retardos en ejecución, ahorra tiempo en la precompilación y en memoria. El mayor impacto de esta técnica se nota en la instalación de las aplicaciones y actualizaciones del sistema. Mientras que en Android 6.0 una actualización podría usar varios minutos, ahora se instala en cuestión de segundos.

Android Nougat incorpora la plataforma de realidad virtual Daydream. Se trata de una propuesta de Google que complementa la iniciativa Cardboard. Incluye especificaciones software y hardware que nos permitirán diferenciar a los dispositivos compatibles. Los principales fabricantes de móviles se han unido a esta iniciativa.

En la versión anterior, el gestor de batería Doze solo se activaba cuando el dispositivo estaba en reposo. Ahora, se activa poco tiempo después de apagarse la pantalla. Esto permite ahorrar batería cuando llevamos el dispositivo en el bolsillo.

También se ha añadido la nueva API para gráficos 3D, Vulcan, como alternativa a OpenGL. Minimiza la sobrecarga de CPU en el controlador, lo que permite aumentar la velocidad de los juegos.

El usuario va a poder activar el modo de ahorro de datos cuando se encuentre en itinerancia o cuando esté a punto de agotar un paquete de datos. En este caso, tanto el sistema como las aplicaciones han de tratar de minimizar al máximo las transferencias de datos.

Android 7.1 Nivel de API 25 (diciembre 2016)

La principal novedad son los accesos directos a aplicaciones. Desde el icono de la aplicación, con una pulsación prolongada, aparecen varias opciones que podremos seleccionar. Por ejemplo, podremos iniciar una navegación privada con Chrome de forma directa. Los accesos directos que quieras incorporar a tu aplicación, los podrás configurar por medio de intens, que deben especificarse en un fichero de configuración4.

Se incorporan otras novedades como la posibilidad de insertar imágenes desde el teclado, de la misma forma que ahora insertamos emoticonos.

Vídeo[tutorial]: Android 7.0

1.6.14. Android Oreo
Android 8.0 Nivel de API 26 (agosto 2017)

Destacan las siguientes mejoras en seguridad: se introduce Google Play Protect, que escanea regularmente las aplicaciones en busca de malware. La opción "Orígenes desconocidos" desaparece. Ahora podemos indicar qué aplicaciones pueden instalar apks y cuáles no. Desde la opción “Acceso especial de aplicaciones” podemos configurar qué aplicaciones pueden realizar ciertas acciones.


El sistema limita más los procesos en segundo plano para conseguir ahorro en la batería. Se mejora el tiempo de arranque del sistema.

Pensando en los países emergentes, se lanza Android Go: Una distribución adaptada para dispositivos de gama baja (1 GB de RAM o menos). Se preinstalan apps ligeras y en Google Play Store destacan aplicaciones ligeras adecuadas para estos dispositivos. Estas aplicaciones han de cubrir 3 requisitos: trabajar sin red, pesar menos de 10 MB y proporcionar un buen rendimiento de batería.

Con el fin de reducir la fragmentación de Android, aparece el proyecto Treble, que facilitará las actualizaciones a los fabricantes. Se reestructura la arquitectura de Android para definir una interfaz clara entre la capa del Núcleo Linux (con sus drivers) y las capas del Framework. Esto permite actualizar Android sin tener que tocar la capa del Núcleo Linux.

Las notificaciones presentan varias mejoras: Podemos añadir color de fondo. Se ordenan por importancia. Las aplicaciones pueden crear canales de notificaciones y el usuario decidir cuáles quiere recibir. Podemos posponer una notificación o verlas pulsando sobre el icono de la aplicación.

Los iconos tendrán que estar diseñados en dos capas: El icono y el fondo del icono. Esto permite adaptarse al dispositivo. Además, el usuario podrá escoger entre iconos circulares, cuadrados o de esquinas redondeadas.

Ahora podemos reproducir un vídeo en una ventana flotante mientras utilizamos otras aplicaciones. Al seleccionar un texto se nos sugieren acciones cuando se trata de un número de teléfono o una dirección. El Autocompletar de Google, que antes estaba disponible en Chrome para guardar contraseñas, ahora se puede usar en cualquier aplicación Android.

1.6.15. Android Pie
Android 9.0 Nivel de API 28 (agosto 2018)

Una de las novedades más interesantes es el nuevo API WiFi RTT introducido en IEEE 802.11mc. Permite estimar la distancia entre nuestro dispositivo y los puntos de acceso cercanos, lo que permite sistemas de posicionamiento en interiores con una precisión de 1 a 2 metros. Otro importante cambio es la navegación por gestos. Se reemplazan los tres botones en pantalla (triangulo, círculo y cuadrado) por solo 2 (retroceder e inicio). El botón de inicio admite diferentes gestos para ir al asistente de Google, cambiar entre apps recientes o abrir el menú de apps.


Una interesante innovación es el uso de Inteligencia Artificial, para mejorar diferentes aspectos. La idea consiste en aprender nuestros hábitos a la hora de usar las aplicaciones. Con esta información se puede quitar preferencia sobre el uso de la CPU a las apps menos utilizadas, consiguiendo una reducción de hasta un 30 %. Este menor uso de la CPU prolongará la vida de la batería. Usando técnicas similares se pretende aprender cuando el usuario va a arrancar una aplicación o una acción de esta. De esta forma el sistema puede cargar en memoria la aplicación antes incluso que el usuario decida utilizarla.

Se introducen algunas mejoras que fomentan un uso responsable y saludable del móvil. Por ejemplo, desde el Dashboard podemos consultar el uso que hacemos cada día, en cada aplicación. Podemos establecer alarmas de uso excesivo muy interesantes para el control parental. En esta línea, se introducen nuevos modos de relajación y no molestar para favorecer la desconexión digital.

1.6.16. Android 10
Android 10.0 Nivel de API 29 (septiembre 2019)

A partir de la versión 10, Google quiere simplificar la marca y los nombres de las versiones. Se abandonan los nombres de postre, para utilizar un simple número entero. Para el logo se usa solo la cabeza del robot, en un tono de verde algo más claro.


Ya no son necesarios los botones para la navegación a través del sistema operativo. Siguiendo la pauta propuesta en iOS, ahora se utiliza un control por gestos. Por ejemplo, para volver a la actividad anterior deslizaremos desde el extremo derecho a la izquierda.

Se introduce el Focus Mode que activaremos cuando queramos concentrarnos en una determinada tarea o juego y no queramos ser molestados. En este modo podemos configurar qué aplicaciones pueden lanzar una notificación y cuáles no. Implantación nativa del modo oscuro que permite un significativo ahorro de batería en pantallas OLED.

La función Live Caption permite que el sistema introduzca subtítulos de manera automática cuando se reproduce cualquier contenido de audio o vídeo. Está pensado para reproducir estos contenidos cuando estamos en público y no queremos usar auriculares. Se obtienen de forma local por lo que no es necesario conexión a Internet. No obstante, solo puede activarse si disponemos de un procesador de gran potencia.

Para reducir la fragmentación, las actualizaciones de seguridad se instalan a través de Google Play, sin la intervención del fabricante. Aumentan las restricciones a las aplicaciones de fondo y se mejoran los permisos. Por ejemplo, podemos indicar que una aplicación tenga acceso a nuestra localización solo cuando esté en primer plano.

Se introduce soporte para 5G, WiFi 6, WPA3, teléfonos plegables y presión en pantallas táctiles.

Preguntas de repaso: Las versiones de Android

1.6.17. Elección de la plataforma de desarrollo

Vídeo[tutorial]: Elegir la versión en una aplicación Android

A la hora de seleccionar la plataforma de desarrollo hay que consultar si necesitamos alguna característica especial que solo esté disponible a partir de una versión. Todos los usuarios con versiones inferiores a la seleccionada no podrán instalar la aplicación. Por lo tanto, es recomendable seleccionar la menor versión posible que nuestra aplicación pueda soportar. Por ejemplo, si en nuestra aplicación queremos utilizar el motor de animaciones de propiedades, tendremos que utilizar la versión 3.0, al ser la primera que lo soporta. El problema es que la aplicación no podrá ser instalada en dispositivos que tengan una versión anterior a la 3.0. Para ayudarnos a tomar la decisión de qué plataforma utilizar, puede ser interesante consultar los porcentajes de utilización:


Figura 3: Dispositivos Android, según la plataforma instalada, que han accedido a Google Play Store el 27 de julio de 2018 y los 7 días anteriores. Las versiones con porcentajes inferiores al 0,1 % no se muestran.

Tras estudiar la gráfica podemos destacar el reducido número de usuarios que utilizan la versión 2.3 (0,2 %). Por lo tanto, puede ser buena idea utilizar como versión mínima la 4.1, 4.2 o 4.4 para desarrollar nuestro proyecto, dado que daríamos cobertura al 99 %, 98 % o 96 % de los terminales. Las versiones 3.x han tenido muy poca difusión, por lo que no aparecen en la tabla. Las versiones 6.0 y 7.x son mayoritarias. La versión 8.x todavía no dispone de un número importante de usuarios. No obstante, estas cifras cambian mes a mes, por lo que recomendamos consultar los siguientes enlaces antes de tomar decisiones sobre las versiones a utilizar.

Enlaces de interés:

• Android Developers: Plataform Versions: Estadística de dispositivos Android, según la plataforma instalada, que han accedido a Android Market.

http://developer.android.com/about/dashboards/index.html

• Android Developers: En el menú de la izquierda aparecen enlaces a las principales versiones de la plataforma. Si pulsas sobre ellos, encontrarás una descripción exhaustiva de cada plataforma.

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

Preguntas de repaso: Elegir una versión de Android

1.6.18. Las librerías de compatibilidad (support library)

Tal y como se ha descrito, la filosofía tradicional de Android ha sido que las novedades que aparecen en una API solo puedan usarse en dispositivos que soporten esa API. Como acabamos de ver, la fragmentación de las versiones de Android es muy grande, es decir, actualmente podemos encontrar dispositivos con una gran variedad de versiones. Con el fin de que la aplicación pueda ser usada por el mayor número posible de usuarios hemos de ser muy conservadores a la hora de escoger la versión mínima de API de nuestra aplicación. La consecuencia es que las novedades que aparecen en las últimas versiones de Android no pueden ser usadas.

En la versión 3.0 aparecieron importantes novedades que Google quería que se incorporaran en las aplicaciones lo antes posible (fragments, nuevas notificaciones, etc.). Con este fin creó las librerías de compatibilidad para poder incorporar ciertas funcionalidades en cualquier versión de Android.

Vídeo[tutorial]: Las librerías de compatibilidad (support library)

Desde la versión 9.0 las librerías de compatibilidad también se incluyen en las librerías AndroidX5, que son parte del proyecto Jetpack6. En las librerías AndroidX se incluye tanto las librerías de compatibilidad como los componentes de Jetpack.

A diferencia de la librería de compatibilidad, cada paquete de AndroidX tiene su propia versión, y se mantienen y actualizan de manera separada. Todos los paquetes están en un espacio de nombre que empieza por androidx.*.

Algunos paquetes muy usados se muestran a continuación:

• v4 Support Library: (androidx.legacy:legacy-support-v4) Esta librería permitía utilizar muchas clases introducidas en la versión 3.0 cuando trabajábamos con un API mínimo. En la actualidad ya no es necesaria utilizarla, dado que ya es recomendable utilizar como API mínimo la versión 4.0 o, superior. Puede usarse en una aplicación con nivel de API 4 (v1.6) o superior. Incorpora las clases: Fragment, NotificationCompat, LocalBroadcastManager, ViewPager, PagerTitleStrip, PagerTabStrip, DrawerLayout, SlidingPaneLayout, ExploreByTouchHelper, Loader y FileProvider.

• appcompat: (androidx.appcompat) Permite utilizar un IU basado en la Barra de Acciones siguiendo especificaciones de Material Design. Se añade por defecto cuando creamos un nuevo proyecto. Incorpora las clases: ActionBar, AppCompatActivity, AppCompatDialog y ShareActionProvider.

• recyclerview: (androidx.recyclerview) Incorpora la vista RecyclerView, una versión mejorada que reemplaza a ListView y GridView.

• constraintlayout: Da soporte al layout ConstraintLayout.

• preference: (androidx.preference) Incorpora las clases CheckBoxPreference y ListPreference usadas en preferencias.

• cardview: (androidx.cardview) Incorpora la vista CardView, una forma estándar de mostrar información especialmente útil en Android Wear y TV.

• palette: (androidx.palette) Incorpora la clase Palette, que permite extraer los colores principales de una imagen.

• mediarouter: (androidx.mediarouter) Da soporte a Google Cast.

• Design Support Library: (com.google.android.material) Librería que incorpora varios componentes de Material Design.

Si tienes dudas sobre los nuevos paquetes utilizados consulta la siguiente tabla: https://developer.android.com/jetpack/androidx/migrate

1.7. Creación de un primer proyecto

Utilizar un entorno de desarrollo nos facilita mucho la creación de aplicaciones. Esto es especialmente importante en Android dado que tendremos que utilizar una gran variedad de ficheros. Gracias a Android Studio, la creación y gestión de proyectos se realizará de forma muy rápida, acelerando los ciclos de desarrollo.

Ejercicio: Crear un primer proyecto

Para crear un primer proyecto Android, con Android Studio sigue los siguientes pasos:

1. Selecciona File > New > New Project...

2. En primer lugar, podrás indicar la plataforma para la que quieres desarrollar (teléfonos y tabletas, Wear OS, TV, ...) y el tipo de actividad inicial que quieres en tu aplicación:


En este curso nos centraremos en las aplicaciones para teléfonos y tabletas, por lo que has de seleccionar siempre la primera pestaña. Has de saber que la plataforma Android también permite desarrollar aplicaciones para dispositivos wearables, Google TV, Android Auto o dispositivos de internet de las cosas.

Observa cómo para este tipo de aplicación puedes elegir diferentes clases de actividades que incorporen ciertos elementos de uso habitual, como menús, botones, anuncios, etc. El concepto de actividad será explicado más adelante. Selecciona Empty Activity para añadir una actividad inicial.

3. Pulsa Next para pasar a la pantalla donde se rellenan los detalles del proyecto. Puedes dejar los valores por defecto:


A continuación, vemos una descripción para cada campo:

Name: Es el nombre de la aplicación que aparecerá en el dispositivo Android. Tanto en la barra superior, cuando esté en ejecución, como en el icono que se instalará en el menú de programas.

Package name: Indicamos el nombre de paquete de la aplicación. Las clases Java que creemos pertenecerán a este paquete. Como veremos a lo largo del curso, el nombre del paquete también es utilizado por Android para múltiples funciones. Por ejemplo, para determinar en qué directorio se instala la aplicación.

Nota sobre Java/Kotlin: El nombre del paquete debe ser único en todos los paquetes instalados en un sistema. Por ello, cuando quieras distribuir una aplicación, es muy importante utilizar un dominio que no puedan estar utilizando otras empresas (por ejemplo: es.upv.elgranlibroandroid.proyecto1). El espacio de nombres “com.example” está reservado para la documentación de ejemplos (como en este libro) y nunca puede ser utilizado para distribuir aplicaciones. De hecho, Google Play no permite publicar una aplicación si su paquete comienza por “com.example”.

Save location: Permite configurar la carpeta donde se almacenarán todos los ficheros del proyecto.

Language: Selecciona Java o Kotlin, según el lenguaje con el que quieres programar la aplicación.

Minimum API level: Este valor especifica el mínimo nivel de la API que requiere tu aplicación. Por lo tanto, la aplicación no podrá ser instalada en dispositivos con una versión inferior. Procura escoger valores pequeños para que tu aplicación pueda instalarse en la mayoría de los dispositivos. Un valor adecuado puede ser el nivel de API 16 (v4.1), dado que cubriría prácticamente el 100% de los dispositivos. O el nivel de API 19 (v4.4), que cubriría más del 95% de los dispositivos.

Escoger valores pequeños para este parámetro tiene un inconveniente: no podremos utilizar ninguna de las mejoras que aparezcan en los siguientes niveles de API. Por ejemplo, si queremos utilizar el motor de animaciones de propiedades en nuestra aplicación, tendremos que indicar en este campo la versión 3.0, dado que esta API no aparece hasta esta versión. Pero, en este caso, nuestra aplicación no se podrá instalar en la versión 2.3.

Como se acaba de indicar escoger la versión mínima del SDK es un aspecto clave a la hora de crear un proyecto. Para ayudarnos a tomar esta decisión se indica en negrita el porcentaje de dispositivo donde se podrá instalar nuestra aplicación. En el apartado anterior se explica cómo se obtiene esta información. Pulsa en Help Me chosee para visualizar una gráfica donde se muestra los diferentes niveles de API y el porcentaje de usuarios que podrán instalarla la aplicación. Además si pulsas sobre un nivel te mostrará un resumen con las nuevas características introducidas en este nivel.


4. Deja el resto de valores por defecto y pulsa Finish para crear el proyecto. Deberías tener visible el explorador del proyecto (Project) a la izquierda. Abre el fichero MainActivity (situado en app / java / com.example.myapplication). Debe tener este aspecto:


Observa que la clase MainActivity extiende AppCompactActivity que a su vez es un descendiente de Activity. Una actividad es una entidad de aplicación que se utiliza para representar cada una de las pantallas de nuestra aplicación. Es decir, el usuario interactúa con solo una de estas actividades y va navegando entre ellas. El sistema llamará al método onCreate() cuando comience su ejecución. Es donde se debe realizar la inicialización y la configuración de la interfaz del usuario. Las actividades van a ser las encargadas de interactuar con el usuario.

Nota sobre Java/Kotlin: Antes de este método se ha utilizado la anotación @Override (sobrescribir). Esto indica al compilador que el método ya existe en la clase padre y queremos reemplazarlo. Es opcional, aunque conviene incluirlo para evitar errores.

Lo primero que hay que hacer al sobrescribir un método suele ser llamar al método de la clase de la que hemos heredado. Para referirnos a nuestra clase padre usaremos la palabra reservada super. El método termina indicando que la actividad va a visualizarse en una determinada vista. Esta vista está definida en los recursos. Más adelante se describe la finalidad de cada fichero y carpeta de este proyecto.

Vídeo[tutorial]: Un primer proyecto Android

1.8. Ejecución del programa

Una vez creada esta primera aplicación, vamos a ver dos alternativas para ejecutarla: en un emulador y en un dispositivo real.

1.8.1. Ejecución en el emulador

Ejercicio: Ejecución en el emulador

1. Selecciona Run > Run ‘app’ (Mayús-F10) o pulsa el icono de la barra de herramientas.

2. Te preguntará sobre que dispositivo quieres ejecutar la aplicación:


Te permite escoger entre dispositivos conectados (AVD o reales), lanzar un AVD ya creado o crear uno nuevo.

3. Una vez que el emulador esté cargado, debes ver algo así:


1.8.2. Ejecución en un terminal real

También es posible ejecutar y depurar tus programas en un terminal real. Incluso es una opción más rápida y fiable que utilizar un emulador. No tienes más que usar un cable USB para conectar el terminal al PC. Resulta imprescindible haber instalado un driver especial en el PC. Puedes encontrar un driver genérico que se encuentra en la carpeta de instalación del SDK \sdk\extras\google\usb_driver. Aunque lo más probable es que tengas que utilizar el driver del fabricante.

Ejercicio: Ejecución en un terminal real

1. Abre Android SDK Manager y asegúrate de que está instalado el paquete USB Driver. En caso contrario, instálalo.


2. Posiblemente, este driver genérico no sea adecuado para tu terminal y tengas que utilizar el del fabricante. Si no dispones de él, puedes buscarlo en:

http://developer.android.com/tools/extras/oem-usb.html

3. A partir de Android 4.2 las opciones para desarrolladores vienen ocultas por defecto. De esta forma, un usuario sin experiencia no podrá activar estas opciones de forma accidental. Para activar las opciones de desarrollo tienes que ir a Ajustes > Información del teléfono y pulsar siete veces sobre el número de compilación. Tras esto aparecerá el mensaje “¡Ahora eres un desarrollador!” y nos mostrará más ajustes.

4. En el terminal accede al menú Ajustes > Opciones de desarrollador y asegúrate de que la opción Depuración de USB está activada.


5. Conecta el cable USB.

6. Se indicará que hay un nuevo hardware y te pedirá que le indiques el controlador.

NOTA: En Windows, si indicas un controlador incorrecto no funcionará. Además, la próxima vez que conectes el cable no te pedirá la instalación del controlador. Para desinstalar el controlador sigue los siguientes pasos:

1. Asegúrate de haber desinstalado el controlador incorrecto.

2. Accede al registro del sistema (Inicio > ejecutar > RegEdit). Busca la siguiente clave y bórrala: “vid_0bb4&pid_0c02”.

3. Vuelve al paso 3 del ejercicio.

7. Selecciona de nuevo Run > Run ‘app’ (Mayús-F10) o pulsa el icono Aparecerá una ventana que te permite escoger en qué dispositivo o emulador quieres ejecutar la aplicación.

8. Selecciona el dispositivo real y pulsa OK.

1.9. Ficheros y carpetas de un proyecto Android

Lo primero que conviene que conozcas es que un proyecto en Android Studio puede contener varios módulos. Cada módulo corresponde a una aplicación o ejecutable diferente. Disponer de varios módulos en un mismo proyecto nos será muy útil cuando queramos crear varias versiones de nuestra aplicación, para dispositivo móvil, Wear, TV, Things, etc. También si queremos crear varias versiones de nuestra aplicación con nivel mínimo de SDK diferentes. En este libro solo vamos a desarrollar aplicaciones para móviles, por lo que no vamos a necesitar un módulo. Este módulo ha sido creado con el nombre app.

Cada módulo en Android está formado por un descriptor de la aplicación (manifests), el código fuente en Java (java), una serie de ficheros con recursos (res) y ficheros para construir el módulo (Gradle Scripts). Cada elemento se almacena en una carpeta específica, que hemos indicado entre paréntesis. Aprovecharemos el proyecto que acabamos de crear para estudiar la estructura de un proyecto en Android Studio. No te asustes con el exceso de información. Más adelante se dará más detalles sobre la finalidad de cada fichero.

AndroidManifest.xml: Este fichero describe la aplicación Android. Se define su nombre, paquete, icono, estilos, etc. Se indican las actividades, las intenciones, los servicios y los proveedores de contenido de la aplicación. También se declaran los permisos que requerirá la aplicación. Se indica el paquete Java, la versión de la aplicación, etc.

java: Carpeta que contiene el código fuente de la aplicación. Como puedes observar los ficheros Java se almacenan en carpetas según el nombre de su paquete.

MainActivity: Clase con el código de la actividad inicial.

ExampleInstrumentTest: Clase para insertar código de testeo de la aplicación.

ExampleUnitTest: Clase para insertar test unitarios sobre otras clases.

res: Carpeta que contiene los recursos usados por la aplicación.

drawable: En esta carpeta se almacenan los ficheros de imágenes (JPG o PNG) y descriptores de imágenes en XML.

mipmap: En una carpeta guardaremos el icono de la aplicación. En el proyecto se ha incluido el fichero ic_launcher.png que será utilizado como icono de la aplicación. Observa cómo este recurso se ha añadido en seis versiones diferentes. Como veremos en el siguiente capítulo, usaremos un sufijo especial si queremos tener varias versiones de un recurso, de forma que solo se cargue al cumplirse una determinada condición. Por ejemplo: (hdpi) significa que solo ha de cargar los recursos contenidos en esta carpeta cuando el dispositivo donde se instala la aplicación tenga una densidad gráfica alta (180- dpi); (mdpi) se utilizará con densidad gráfica alta (180- dpi). Si pulsas sobre las diferentes versiones del recurso, observarás como se trata del mismo icono, pero con más o menos resolución de forma que, en función de la densidad gráfica del dispositivo, se ocupe un tamaño similar en la pantalla. El fichero ic_launcher_round.png es similar, pero se utiliza cuando se quieren usar iconos redondos.

layout: Contiene ficheros XML con vistas de la aplicación. Las vistas nos permitirán configurar las diferentes pantallas que compondrán la interfaz de usuario de la aplicación. Se utiliza un formato similar al HTML usado para diseñar páginas web. Se tratarán en el siguiente capítulo.

menu: Ficheros XML con los menús de cada actividad. En el proyecto no hay ningún menú por lo que no se muestra esta carpeta.

values: También utilizaremos ficheros XML para indicar valores usados en la aplicación, de esta manera podremos cambiarlos desde estos ficheros sin necesidad de ir al código fuente. En colors.xml se definen los tres colores primarios de la aplicación. En dimens.xml se pueden definir dimensiones como el margen por defecto o el ancho de los botones. En el fichero strings.xml, tendrás que definir todas las cadenas de caracteres de tu aplicación. Creando recursos alternativos resultará muy sencillo traducir una aplicación a otro idioma. Finalmente, en styles.xml, podrás definir los estilos y temas de tu aplicación. Se estudian en el siguiente capítulo.

anim: Contiene ficheros XML con animaciones de vistas (Tween). Las animaciones se describen al final del capítulo 4.

animator: Contiene ficheros XML con animaciones de propiedades.

xml: Otros ficheros XML requeridos por la aplicación.

raw: Ficheros adicionales que no se encuentran en formato XML.

Gradle Scripts: En esta carpeta se almacenan una serie de ficheros Gradle que permiten compilar y construir la aplicación. Observa como algunos hacen referencia al módulo app y el resto son para configurar todo el proyecto. El fichero más importante es build.gradle (Module:app) que es donde se configuran las opciones de compilación del módulo:



El primer parámetro que podemos configurar es compileSdkVersion que nos permite definir la versión del sdk con la que compilamos la aplicación. Las nuevas versiones no solo añaden funcionalidades al API, también añaden mejoras en los procesos. Por ejemplo, a partir de la versión 3.0 (API 11) solo se permite el acceso a Internet desde un hilo auxiliar7. applicationId suele coincidir con el nombre del paquete Java creado para la aplicación. Se utiliza como identificador único de la aplicación, de forma que no se permite instalar una aplicación si ya existe otra con el mismo id. minSdkVersion especifica el nivel mínimo de API que requiere la aplicación. Es un parámetro de gran importancia, la aplicación no podrá ser instalada en dispositivos con versiones anteriores y solo podremos usar las funcionalidades del API hasta este nivel (con excepción de las librerías de compatibilidad). targetSdkVersion indica la versión más alta con la que se ha puesto a prueba la aplicación. Cuando salgan nuevas versiones del SDK tendrás que comprobar la aplicación con estas versiones y actualizar el valor. versionCode y versionName indica la versión de tu aplicación. Cada vez que publiques una nueva versión incrementa en uno el valor de versionCode y aumenta el valor de versionName según la importancia de la actualización. Si es una actualización menor el nuevo valor podría ser "1.1" y si es mayor "2.0".

Dentro de buildTypes se añaden otras configuraciones dependiendo del tipo de compilación que queramos (relase para distribución, debug para depuración, etc.). Los comandos que aparecen configuran la ofuscación de código. Para más información leer el capítulo «Ingeniería Inversa en Android» de El Gran Libro de Android Avanzado.

Un apartado importante es el de dependencies. En él has de indicar todas las librerías que han de ser incluidas en nuestro proyecto. Si necesitas usar alguna librería de compatibilidad adicional has de incluirla aquí.

Preguntas de repaso: Elementos de un proyecto

1.10. Componentes de una aplicación

Existe una serie de elementos clave que resultan imprescindibles para desarrollar aplicaciones en Android. En este apartado vamos a realizar una descripción inicial de algunos de los más importantes. A lo largo del libro se describirán con más detalle las clases Java que implementan cada uno de estos componentes.

1.10.1. Vista (View)

Las vistas son los elementos que componen la interfaz de usuario de una aplicación: por ejemplo, un botón o una entrada de texto. Todas las vistas van a ser objetos descendientes de la clase View y, por tanto, pueden ser definidas utilizando código Java. Sin embargo, lo habitual será definir las vistas utilizando un fichero XML y dejar que el sistema cree los objetos por nosotros a partir de este fichero. Esta forma de trabajar es muy similar a la definición de una página web utilizando código HTML.

1.10.2. Layout

Un layout es un conjunto de vistas agrupadas de una determinada forma. Vamos a disponer de diferentes tipos de layouts para organizar las vistas de forma lineal, en cuadrícula o indicando la posición absoluta de cada vista. Los layouts también son objetos descendientes de la clase View. Igual que las vistas, los layouts pueden ser definidos en código, aunque la forma habitual de definirlos es utilizando código XML.

1.10.3. Actividad (Activity)

Una aplicación en Android va a estar formada por un conjunto de elementos básicos de visualización, coloquialmente conocidos como pantallas de la aplicación. En Android cada uno de estos elementos, o pantallas, se conoce como actividad. Su función principal es la creación de la interfaz de usuario. Una aplicación suele necesitar varias actividades para crear la interfaz de usuario. Las diferentes actividades creadas serán independientes entre sí, aunque todas trabajarán para un objetivo común. Una actividad se define en una clase descendiente de Activity y utiliza un layout para que define su apariencia.

1.10.4. Fragmentos (Fragment)

La llegada de las tabletas trajo el problema de que las aplicaciones de Android ahora deben soportar pantallas más grandes. Si diseñamos una aplicación pensada para un dispositivo móvil y luego la ejecutamos en una tableta, el resultado no suele resultar satisfactorio.

Para ayudar al diseñador a resolver este problema, en la versión 3.0 de Android aparecen los fragments. Un fragment está formado por la unión de varias vistas para crear un bloque funcional de la interfaz de usuario. Una vez creados los fragments, podemos combinar uno o varios fragments dentro de una actividad, según el tamaño de pantalla disponible.

Vídeo[tutorial]: Los fragments en Android

El uso de fragments puede ser algo complejo, por lo que recomendamos dominar primero conceptos como actividad, vista y layout antes de abordar su aprendizaje. No obstante, es un concepto importante en Android y todo programador en esta plataforma ha de saber utilizarlos. Véase el anexo A para aprender más sobre fragments.

1.10.5. Servicio (Service)

Un servicio es un proceso que se ejecuta “detrás”, sin la necesidad de una interacción con el usuario. Es algo parecido a un demonio en Unix o a un servicio en Windows. Se utilizan cuando queramos tener en ejecución un código de manera continua, aunque el usuario cambie de actividad. En Android disponemos de dos tipos de servicios: servicios locales, que son ejecutados en el mismo proceso, y servicios remotos, que son ejecutados en procesos separados. Los servicios se estudian en el capítulo 8.

1.10.6. Intención (Intent)

Una intención representa la voluntad de realizar alguna acción, como realizar una llamada de teléfono o visualizar una página web. Se utiliza cada vez que queramos:

■ Lanzar una actividad

■ Lanzar un servicio

■ Enviar un anuncio broadcast

■ Comunicarnos con un servicio

Los componentes lanzados pueden ser internos o externos a nuestra aplicación. También utilizaremos las intenciones para el intercambio de información entre estos componentes.

1.10.7. Receptor de anuncios (Broadcast Receiver)

Un receptor de anuncios recibe anuncios broadcast y reacciona ante ellos. Los anuncios broadcast pueden ser originados por el sistema (por ejemplo: Batería baja, Llamada entrante) o por las aplicaciones. Las aplicaciones también pueden crear y lanzar nuevos tipos de anuncios broadcast. Los receptores de anuncios no disponen de interfaz de usuario, aunque pueden iniciar una actividad si lo estiman oportuno. Los receptores de anuncios se estudian en el CAPÍTULO 8.

1.10.8. Proveedores de contenido (Content Provider)

En muchas ocasiones, las aplicaciones instaladas en un terminal Android necesitan compartir información. Android define un mecanismo estándar para que las aplicaciones puedan compartir datos sin necesidad de comprometer la seguridad del sistema de ficheros. Con este mecanismo podremos acceder a datos de otras aplicaciones, como la lista de contactos, o proporcionar datos a otras aplicaciones. Los ContentProvider se estudian en el capítulo 9.

Preguntas de repaso: Componentes de una aplicación

1.11. Documentación y aplicaciones de ejemplo

Aunque en este libro vas a aprender mucho, resultaría imposible tocar todos los aspectos de Android y con un elevado nivel de profundidad. Por lo tanto, resulta imprescindible que dispongas de fuentes de información para consultar los aspectos que vayas necesitando. En este apartado te proponemos dos alternativas: el acceso a documentación sobre Android y el estudio de ejemplos.

1.11.1. Dónde encontrar documentación

Puedes encontrar una completa documentación del SDK localmente en:

…\sdk\docs\index.html

Se incluye la descripción de todas las clases (Develop > Reference), conceptos clave y otros tipos de recursos. Esta documentación también está disponible en línea a través de Internet:

http://developer.android.com/

Muchos de los recursos utilizados en este libro puedes encontrarlos en:

http://www.androidcurso.com/

Para resolver dudas puntuales sobre programación te recomendamos la siguiente web de preguntas y respuestas:

http://stackoverflow.com/

1.11.2. Repositorio de ejemplos en GitHub

Otra opción muy interesante para aprender nuevos aspectos de programación consiste en estudiar ejemplos. Google ha preparado un repositorio de ejemplos en GitHub que pueden ser instalados desde Android Studio.

Ejercicio: Instalación de un ejemplo desde GitHub

1. Selecciona File > New > Import Sample… Aparecerá la siguiente ventana:


Los proyectos se encuentran clasificados en categorías: Admin, Background, Connectivity, Content, Input, Media, Notification, … Selecciona un proyecto de alguna de estas categorías. A la derecha podrás leer una breve descripción o ver una vista previa.

2. Pulsa Next para pasar a la siguiente ventana. Podrás configurar el nombre de la aplicación, explorar el proyecto accediendo a su sitio web en GitHub e indicar la carpeta donde quieres descargarlo:


3. Pulsa Finish y a continuación ejecuta el proyecto seleccionado.

1.12. Depurar

Programación y errores de código son un binomio inseparable. Por lo tanto, resulta fundamental sacar el máximo provecho a las herramientas de depuración.

1.12.1. Depurar con el entorno de desarrollo

Android Studio integra excelentes herramientas para la depuración de código. Para probarlas, introduce un error en tu código modificando MainActivity de forma que en método onCreate() tenga este código:


Este cambio introduce en Java un NullPointerException y en Kotlin un UninitializedPropertyAccessException. Si ahora ejecutas tu aplicación, te aparecerá algo similar a:


Pulsa Cerrar para finalizar la aplicación. Para averiguar más sobre el error, inserta un punto de ruptura (breakpoint) en el código fuente en la línea o.toString() (el breakpoint se introduce haciendo clic en la barra de la izquierda).


Entonces selecciona Run > Debug ‘app’ (Mayús+F9) o pulse en para ejecutarlo en modo Debug. Tu aplicación se reiniciará mostrando el siguiente mensaje:


Pero esta vez quedará suspendida cuando alcance el punto de ruptura que has introducido. Entonces puedes recorrer el código en modo Debug, igual que se haría en cualquier otro entorno de programación. Pulsa en Run > Step Over (F8) para ir ejecutando las líneas una a una.

Vídeo[tutorial]: Depurar con Android Studio

1.12.2. Depurar con mensajes Log

El sistema Android utiliza el fichero LogCat para registrar todos los problemas y eventos principales que ocurren en el sistema. Ante cualquier error resulta muy interesante consultarlo para tratar de encontrar su origen.

La clase Log proporciona un mecanismo para introducir mensajes desde nuestro código en este fichero. Puede ser muy útil para depurar nuestros programas o para verificar el funcionamiento del código. Disponemos de varios métodos para generar distintos tipos de mensajes:

Log.e(): Errors

Log.w(): Warnings

Log.i(): Information

Log.d(): Debugging

Log.v(): Verbose

Ejercicio: Depurar con mensajes Log

1. Modifica la clase MainActivity introduciendo la línea que aparece subrayada:


Nota sobre Java/Kotlin: Para poder utilizar la clase Log has de importar un nuevo paquete. Para ello añade al principio import android.util.Log; Otra alternativa es pulsar Alt-Intro para que se añadan automáticamente los paquetes que faltan. En algunos casos, el sistema puede encontrar dos paquetes con la clase Log, y puede tener dudas sobre cual importar. En estos casos te preguntará.

2. Ejecuta la aplicación. Aparecerá un error.

3. En Android Studio aparecerá automáticamente en la parte inferior:


En la primera línea de la captura anterior, comprobamos que se pudo entrar dentro de onCreate(). Dos líneas más abajo se indica una excepción. La información mostrada suele ser excesiva. Te recomendamos que busques las palabras “Caused by” para ver el tipo de excepción y la primera referencia a un paquete escrito por nosotros, “com.example.jtomas.myapplication”. En este ejemplo, las líneas clave son: en Java “Cased by: java.lang.NullPointerException at conm.example.jtomas.myapplication.MainActivity.onCreate(MainActivity.java:17)”. En Kotlin “Caused by: kotlin.UninitializedPropertyAccessException: lateinit property o has not been initialized at com.example.myapplication.MainActivity.onCreate (MainActivity.kt:14)”

4. Haz clic en (MainActivity.java:17) o (MainActivity.kt:14). Te abrirá la actividad MainActivity y te situará en la línea donde se ha producido el error.

Vídeo[tutorial]: LogCat con Android Studio

1.13. Introducción Java/Kotlin y aplicación Mis Lugares

Si no dominas el lenguaje de programación Java o Kotlin, puede ser una buena idea repasar los conceptos más importantes de uno de estos lenguajes antes de comenzar a realizar aplicaciones en Android. Existe una gran cantidad de libros8 y tutoriales en Internet que pueden ayudarte en este propósito. También puede ser de utilidad una consulta al Anexo C.

Hemos preparado un conjunto de breves tutoriales que te mostrarán lo esencial de Java y Kotlin. Suponemos que ya tienes conocimientos de programación. De no ser así, puede que tengas dificultades en seguirlos.

Vídeo[tutorial]: Características de Java

Vídeo[tutorial]: Creación y utilización de clases9

Enlaces de interés: Comentarios y documentación javadoc

http://www.androidcurso.com/index.php/27

Vídeo[tutorial]: Encapsulamiento y visibilidad en Java10

A lo largo de este libro vamos a crear un par de aplicaciones. Una de ellas será Mis Lugares, que nos permitirá recordar los lugares donde hemos estado o que más nos gustan. Tras realizar los tutoriales que aparecen en este apartado, dispondrás de varias clases que te serán de utilidad en la aplicación Mis Lugares (estas clases son: Lugar, RepositorioLugares, TipoLugar y Geopunto).

Vídeo[tutorial]: La aplicación Mis Lugares

Aunque ya tengas experiencia en Java o Kotlin, te recomendamos que realices los tutoriales que incluimos a continuación. De esta forma, podrás familiarizarte con las clases que usaremos en Mis Lugares.

1.13.1. La clase Lugar

La aplicación Mis Lugares permite gestionar una colección de lugares. Para cada lugar vamos a poder almacenar mucha información: nombre, dirección, posición geográfica, etc. El primer paso a realizar va a ser crear una clase que nos permita trabajar con este tipo de información. Este tipo de clase se conoce muchas veces como POJO o clase de datos.

Ejercicio: Creación de la clase Lugar en Android Studio

Android Studio está pensado exclusivamente para crear aplicaciones Android. Sin embargo, si sigues los siguientes pasos podrás crear una aplicación 100% Java o Kotlin.

1. Crea un nuevo proyecto (File > New > New Project...) con los siguientes datos:

Phone and Tablet / Add No Activity

Name: Mis Lugares Java ó Mis Lugares Kotlin

Package name: com.example.mislugares

Language: Java ó Kotlin

Minimum API level: API 19 Android 4.4 (KitKat)

NOTA: Deja el resto de los parámetros con su valor por defecto.

2. Pulsa en File > New > New Module. Selecciona Java Library y pulsa Next.

3. Introduce en Library name: MisLugares, como Java pakage name: com.example.mislugares y en Java class name: Lugar. Pulsa el botón Finish. Se creará un nuevo módulo Java dentro de tu proyecto Android.

4. Para Kotlin, en el explorador de proyecto busca la clase Java y, con el botón derecho, selecciona Convert Java File to Kotlin File.

5. Reemplaza el código de la clase Lugar por el siguiente:



Para Java observa cómo se definen los atributos de la clase y como en el constructor se inicializa para un objeto concreto según los parámetros indicados. En estos parámetros no se indica el atributo fecha. Este representa el día y la hora en que visitamos ese lugar por última vez. Se codifica mediante un long (número entero de 64 bits), que supondremos en formato Epoch time o tiempo Unix11. Es decir, número de milisegundos transcurridos desde 1970. El método System.currentTimeMillis() nos devuelve la fecha y la hora actuales en este formato. Por lo tanto, siempre que usemos este constructor, en fecha se almacenará el instante en que el objeto fue creado.

Para Kotlin en el constructor principal indicamos directamente los atributos de la clase y en algunos casos los valores por defecto. Los getters y setters son creados automáticamente. Además, al haber indicado data class se crean otras funciones como toString(). Por lo tanto, podrás saltarte los siguientes dos puntos.

6. Solo para Java, crea los métodos getters y setters para acceder a todos los atributos de la clase. Solo tienes que pulsar con el botón derecho y seleccionar la opción Generate… > Getter and Setter y selecciona todos los atributos mientras mantienes pulsada la tecla Ctrl.

7. Solo para Java, pulsa con el botón derecho sobre el código y selecciona la opción Generate… > toString(). Selecciona todos los atributos y pulsa OK. Se añadirá un método similar a:


NOTA: El significado de @Override se explica más adelante.

8. Dentro del explorador del módulo MisLugares / java / com.example.mislugares pulsa con el botón derecho y selecciona New > Java Class o Kotlin File/Class.

9. Introduce en el campo Name: GeoPunto y pulsa Ok. Reemplaza el código por el siguiente (dejando la línea del package):



El objeto SIN_POSICION será utilizado cuando se quiera indicar que un lugar no tiene posición asignada. Observa que es un objeto de tipo estático. En Java se indica con static y en Kotlin con companion object. Esto significa que solo va a haber una instancia de este objeto creada desde el principio. Para acceder a ella usaremos GeoPunto.SIN_POSICION.

10. Solo para Java, crea en esta clase los métodos getters y setters para acceder a los dos atributos. Igual que antes, pulsa con el botón derecho y seleccionar la opción Generate… > Getter and Setter. Realiza la misma operación para equals() and hasCode().

11. Para Java y Kotlin, crea una nueva clase Java con nombre: Principal. Android Studio no permite que la clase principal esté en Kotlin.

12. Reemplaza el código por el mostrado (dejando la línea del package):


La clase Principal es algo atípica: no tiene atributos ni constructor, únicamente el método main. Cuando en un proyecto existe una clase que tiene un método con este perfil, es el que se llama para comenzar la ejecución. Como parámetros, este método recibe un array de Strings. Esta información tiene interés cuando el programa se ejecuta desde la línea de comandos con parámetros.

13. Pulsa en el botón desplegable a la derecha del botón Run . Selecciona Edit Configurations...

14. En la nueva ventana, haz clic en el signo + de la esquina superior izquierda y selecciona Application. Aparecerá una nueva configuración de aplicación. Selecciona en Name: mislugares, en Main class: com.example.mislugares.Principal y en Use classpath of module: MisLugares. Pulsa en OK.

15. Pulsa el botón Ejecución y verifica que el resultado que aparece en la ventana de Run es similar a:

“C\Program ...

Lugar {nombre=Escuela Politécnica Superior de Gandía,

direccion=C/ Paranimf, 1 46730 Gandia (SPAIN),

posicion=longitud:-0.166093, latitud:38.995656, foto=null,

telefono=962849300, url=http://www.epsg.upv.es,

comentario=Uno de los mejores lugares para formarse.,

fecha=1392332854758, valoracion=3.0}

Process finished with exit code 0

Vídeo[tutorial]: La Herencia en Java12

Enlaces de interés: Sobrecarga:

http://www.androidcurso.com/index.php/30

Vídeo[tutorial]: El polimorfismo en Java13 14

1.13.2. Tipos enumerados

Vídeo[tutorial]: Tipos enumerados en Java15

Vídeo[tutorial]: Clases enumeradas en Kotlin

Ejercicio: El enumerado TipoLugar

En este ejercicio vamos a crear un tipo enumerado para diferenciar entre diferentes tipos de establecimientos en la aplicación Mis Lugares. Además, a cada tipo de lugar le asociaremos un String con el nombre y un recurso gráfico.

1. Vamos a crear un nuevo tipo enumerado. Para ello pulsa con el botón derecho en el paquete com.example.mislugares. Selecciona New > Java Class e introduce en Name: TipoLugar, en Kind: Enum y pulsa OK.

2. Reemplaza el código por el siguiente (dejando la línea del package):



Si quieres puedes definir otros tipos de lugares para adaptar la aplicación a tus necesidades. Observa como a cada constante le asociamos un String con el nombre del tipo de lugar y un entero. El entero se utilizará más adelante para indicar un recurso gráfico en Android con un icono representativo del tipo.

3. Abre la clase Lugar. En Kotlin añade el código subrayado y salta al punto 8:


En Java añade el siguiente atributo a la clase:


4. Añade el parámetro TipoLugar en el constructor de la clase e inicializa el atributo anterior con este parámetro:


5. Añade los métodos getter y setter correspondientes. Para ello pulsa con el botón derecho y seleccionar la opción Generate > Getter and Setter.

6. Vamos a volver a generar el método toString(). Para ello pulsa con el botón derecho y seleccionar la opción Generate > toString(). Pulsa Yes para reemplazar el método actual.

7. Abre la clase Principal y modifica la inicialización del objeto para que se incluya el nuevo parámetro, TipoLugar.EDUCACION, en el constructor.

8. Verifica el resultado ejecutando el proyecto.

1.13.3. Las colecciones I

Ejercicio: La interfaz RepositorioLugares

En este ejercicio vamos a crear una interfaz que nos permita almacenar una lista de objetos Lugar. A lo largo del curso esta interfaz será implementada por dos clases. En esta unidad usaremos una lista almacenada en memoria y en la última unidad una base de datos. Usar esta interface nos va a permitir desacoplar la forma en la que almacenamos los datos del resto de la aplicación. Por ejemplo, si en un futuro queremos que los datos se almacenen en la nube, solo será necesario cambiar la implementación de esta interface, dejando idéntica el resto de la aplicación.

1. Dentro del explorador del proyecto mislugares / java / com.example.mislugares, pulsa con el botón derecho y selecciona New > Java Class o New > Kotlin File/Class.

2. Introduce en el campo Name: RepositorioLugares y en Kind: Interface.

3. Reemplaza el código por el siguiente (dejando la línea del package):



Una clase que implemente esta interfaz va a almacenar una lista de objetos de tipo Lugar. Mediante los métodos indicados vamos a poder acceder y modificar esta lista. Una interfaz también puede tener funciones estáticas, como añadeEjemplos(). En Java solo está permitido con API mínima >24, por lo que lo añadiremos esta función en una clase no abstracta.

4. Esta interface será usada en uno de los siguientes apartados.

1.13.4. Las colecciones II

Vídeo[tutorial]: Las colecciones en Java16

Vídeo[tutorial]: Colecciones en Kotlin: introducción

Vídeo[tutorial]: Colecciones en Kotlin: List, Set y Map

Ejercicio: La clase LugaresLista

En este ejercicio vamos a crear la clase LugaresLista, que tiene como finalidad almacenar y gestionar un conjunto de objetos Lugar dentro de una lista.

1. Dentro del paquete com.example.mislugares añade la clase LugaresLista y reemplaza el código por el siguiente:



2. Pulsa Alt-Intro para que se añadan los import de las clases utilizadas.


3. Para Java, añade la siguiente sobrecarga al constructor a la clase Lugar:


Esto nos permitirá crear un nuevo lugar sin indicar sus atributos.

4. Abre la clase Principal y reemplaza el código del método main() por:


5. Verifica que el resultado es similar al siguiente:


__________

1 http://www.openhandsetalliance.com

2 Para más información consultar el Gran Libro de Android Avanzado

3 http://developer.android.com/tools/support-library

4 https://developer.android.com/guide/topics/ui/shortcuts.html

5 https://developer.android.com/jetpack/androidx?hl=ES

6 https://developer.android.com/jetpack?hl=ES

7 Se describe con detalle en el capítulo 10.

8 Recomendamos: Piensa en Java, de Bruce Eckel, Ed.Prentice Hall y Kotlin for Android Developers de Antonio Leiva.

9 Tutorial web: http://www.androidcurso.com/index.php/24 y http://www.androidcurso.com/index.php/25

10 Tutorial web: http://www.androidcurso.com/index.php/32

11 http://es.wikipedia.org/wiki/Tiempo_Unix

12 Tutorial web: http://www.androidcurso.com/index.php/29

13 Tutorial web: http://www.androidcurso.com/index.php/31

14 Tutorial web: http://www.androidcurso.com/index.php/31

15 Tutorial web: http://www.androidcurso.com/index.php/461

16 Tutorial web: http://www.androidcurso.com/index.php/462

CAPÍTULO 2.
Diseño de la interfaz de usuario: vistas y layouts

El diseño de la interfaz de usuario cobra cada día más importancia en el desarrollo de una aplicación. La calidad de la interfaz de usuario puede ser uno de los factores que conduzca al éxito o al fracaso de todo el proyecto.

Si has realizado alguna aplicación utilizando otras plataformas, advertirás que el diseño de la interfaz de usuario en Android sigue una filosofía muy diferente. En Android la interfaz de usuario no se diseña en código, si no utilizando un lenguaje de marcado en XML similar al HTML.

A lo largo de este capítulo mostraremos una serie de ejemplos que te permitirán entender el diseño de la interfaz de usuario en Android. Aunque no será la forma habitual de trabajar, comenzaremos creando la interfaz de usuario mediante código. De esta forma comprobaremos que cada uno de los elementos de la interfaz de usuario (las vistas) realmente son objetos Java. Continuaremos mostrando cómo se define la interfaz de usuario utilizando código XML. Pasaremos luego a ver las herramientas de diseño integradas en Android Studio. Se describirá el uso de layouts, que nos permitirá una correcta organización de las vistas, y el uso de recursos alternativos nos permitirá adaptar nuestra interfaz a diferentes circunstancias y tipos de dispositivos.

En este capítulo también comenzaremos creando la aplicación de ejemplo desarrollada a lo largo del curso, Asteroides. Crearemos la actividad principal, donde simplemente mostraremos cuatro botones, con los que se podrán arrancar diferentes actividades A continuación aprenderemos a crear estilos y temas y los aplicaremos a estas actividades. Para terminar el capítulo propondremos varias prácticas para aprender a utilizar diferentes tipos de vistas y layouts.

Objetivos:

• Entender cómo se realiza el diseño de la interfaz de usuario en una aplicación Android.

• Aprender a trabajar con vistas y mostrar sus atributos más importantes.

• Enumerar los tipos de layouts que nos permitirán organizar las vistas.

• Mostrar cómo se utilizan los recursos alternativos.

• Aprender a crear estilos y temas para personalizar nuestras aplicaciones.

• Mostrar cómo interactuar con las vistas desde el código Java o Kotlin.

• Describir el uso de layouts basados en pestañas (tabs).

2.1. Creación de una interfaz de usuario por código

Veamos un primer ejemplo de cómo crear una interfaz de usuario utilizando exclusivamente código Java. Aunque esta no es la forma recomendable de trabajar con Android, resulta interesante para resaltar algunos conceptos.

Ejercicio: Creación de la interfaz de usuario por código

1. Abre el proyecto creado en el capítulo anterior y visualiza MainActivity.java.

2. Comenta la última sentencia del método onCreate() y añade las subrayadas:


Nota sobre Java/Kotlin: Para poder utilizar el objeto TextView has de importar un nuevo paquete. Para ello añade al principio import android.widget.TextView;. Otra alternativa es pulsar Alt-Intro para que se añadan automáticamente los paquetes que faltan.

La interfaz de usuario de Android está basada en una jerarquía de clases descendientes de la clase View (vista). Una vista es un objeto que se puede dibujar y se utiliza como un elemento en el diseño de la interfaz de usuario (un botón, una imagen, una etiqueta de texto como la que se ha utilizado en el ejemplo, etc.). Cada uno de estos elementos se define como una subclase de la clase View; la subclase para representar un texto es TextView.

El ejemplo comienza creando un objeto de la clase TextView. El constructor de la clase acepta como parámetro una instancia de la clase Context (contexto). Un contexto es un manejador del sistema que proporciona servicios como la resolución de recursos, la obtención de acceso a bases de datos o las preferencias. La clase Activity es una subclase de Context, y como la clase MainActivity es una subclase de Activity, también es de tipo Context. Por ello, puedes pasar this (el objeto actual de la clase MainActivity) como contexto del TextView.

3. Después se define el texto que se visualizará en el TextView mediante setText(). Finalmente, mediante setContentView() se indica la vista que visualizará la actividad.

4. Ejecuta el proyecto para verificar que funciona.

2.2. Creación de una interfaz de usuario usando XML

En el ejemplo anterior hemos creado la interfaz de usuario directamente en el código. A veces puede ser muy complicado programar interfaces de usuario, ya que pequeños cambios en el diseño pueden corresponder a complicadas modificaciones en el código. Un principio importante en el diseño de software es que conviene separar todo lo posible el diseño, los datos y la lógica de la aplicación.

Android proporciona una alternativa para el diseño de interfaces de usuario: los ficheros de diseño basados en XML. Veamos uno de estos ficheros. Para ello accede al fichero res/layout/activity_main.xml de nuestro proyecto. Se muestra a continuación. Este layout o fichero de diseño proporciona un resultado similar al del ejemplo de diseño por código anterior:


NOTA: Cuando haces doble clic en el explorador del proyecto sobre activity_main.xml, probablemente lo abra en modo gráfico. Para verlo en modo texto, selecciona la pestaña Text.

Resulta sencillo interpretar su significado. Se introduce un elemento de tipo CoinstraintLayout, cuya función, como se estudiará más adelante, es contener otros elementos de tipo View. Este CoinstraintLayout tiene seis atributos. Los tres primeros, xmlns:android, xmlns:app y xmlns:tools, son declaraciones de espacios de nombres de XML que utilizaremos en este fichero (este tipo de parámetro solo es necesario especificarlo en el primer elemento). Los dos siguientes permiten definir la anchura y altura de la vista. En el ejemplo se ocupará todo el espacio disponible. El último atributo indica la actividad asociada a este layout.

Dentro del CoinstraintLayout solo tenemos un elemento de tipo TextView. Este dispone de varios atributos. Los dos primeros definen el alto y el ancho (se ajustarán al texto contenido). El siguiente indica el texto a mostrar. Los cuatro siguientes indican la posición de la vista dentro del CoinstraintLayout.

Ejercicio: Creación de la interfaz de usuario con XML

1. Para utilizar el diseño en XML regresa al fichero MainActivity.java y deshaz los cambios que hicimos antes (elimina las tres últimas líneas y quita el comentario).

2. Ejecuta la aplicación y verifica el resultado. Ha de ser muy similar al anterior.

3. Modifica el valor de hello_world en el fichero res/values/strings.xml.

4. Vuelve a ejecutar la aplicación y visualiza el resultado.

Analicemos ahora la línea en la que acabas de quitar el comentario:

setContentView(R.layout.activity_main)

Aquí, R.layout.main corresponde a un objeto View que se creará en tiempo de ejecución a partir del recurso activity_main.xml. Trabajar de esta forma, en comparación con el diseño basado en código, no quita velocidad y requiere menos memoria. Este identificador es creado automáticamente en la clase R del proyecto a partir de los elementos de la carpeta res. La definición de la clase R puede ser similar a:

public final class R {

public static final class attr {

}

public static final class drawable {

public static final int ic_launcher=0x7f020000;

}

public static final class id {

public static final int action_settings=0x7f070000;

}

public static final class layout {

public static final int activity_main=0x7f030000;

}

public static final class menu {

public static final int main=0x7f060000;

}

public static final class string {

public static final int app_name=0x7f040000;

...

NOTA: Este fichero se genera automáticamente. Nunca debes editarlo.

Has de tener claro que los identificadores de la clase R son meros números que informan al gestor de recursos sobre qué datos ha de cargar. Por lo tanto, no se trata de verdaderos objetos; estos se crearán en tiempo de ejecución solo cuando sea necesario usarlos.

Ejercicio: El fichero R.java

1. En Android Studio, el fichero R.java no es accesible desde el explorador del proyecto. No obstante, puedes acceder a él si pulsas con el botón derecho sobre app y seleccionas Show in Explorer (o Show in Dolfin). Desde esta carpeta abre el fichero:

app\build\generated\not_namespaced_r_class_sources\debug\r\nombre\del\paquete\R.java

Donde nombre\del\paquete has de reemplazarlo por el que corresponda al paquete de tu aplicación.

2. Compáralo con el fichero mostrado previamente. ¿Qué diferencias encuentras? (RESPUESTA: cambian los valores numéricos en hexadecimal y contiene muchos más identificadores.)

3. Abre el fichero MainActivity.java y reemplaza R.layout.activity_main por el valor numérico al que corresponde en R.java.

4. Ejecuta de nuevo el proyecto. ¿Funciona? ¿Crees que sería adecuado dejar este valor numérico?

5. Aunque haya funcionado, este valor puede cambiar en un futuro. Por lo tanto, para evitar problemas futuros vuelve a reemplazarlo por R.layout.activity_main.

Preguntas de repaso: Interfaz de usuario en XML y en código

Preguntas de repaso: El fichero R.java

2.2.1. Edición visual de las vistas

Veamos ahora como editar los layouts o ficheros de diseño en XML. En el explorador del proyecto abre el fichero res/layout/activity_main.xml. Verás que en la parte inferior de la ventana central aparecen dos lengüetas: Design y Text. Podrás usar dos tipos de diseño: editar directamente el código XML (lengüeta Text) o realizar este diseño de forma visual (lengüeta Design). Veamos cómo se realizaría el diseño visual. La herramienta de edición de layouts se muestra a continuación:


NOTA: Si aparece un error con problemas de renderizado prueba otros niveles de API, en el desplegable que aparece junto al pequeño robot verde, o con otro tema, en el botón con forma de círculo.

En la parte inferior izquierda encontramos el marco Component Tree con una lista con todos los elementos del layout. Este layout tiene solo dos vistas: un ConstraintLayout que contiene un TextView. En el marco central aparece una representación de cómo se verá el resultado y a su derecha, con fondo azul, una representación con los nombres de cada vista y su tamaño. En la parte superior aparecen varios controles para representar este layout en diferentes configuraciones. Cuando diseñamos una vista en Android, hay que tener en cuenta que desconocemos el dispositivo final donde se visualizará y la configuración específica elegida por el usuario. Por esta razón, resulta importante que verifiques que el layout se ve de forma adecuada en cualquier configuración.

En la parte superior, de izquierda a derecha, encontramos los siguientes botones: El primero permite mostrar solo la visualización de diseño, solo la visualización esquemática de vistas o ambas. El botón muestra la orientación horizontal (landscape), vertical (portrait) y también podemos escoger el tipo de interfaz de usuario (coche, TV, reloj…), con escogemos el tipo de dispositivo (tamaño y resolución de la pantalla), con la versión de Android, con cómo se verá nuestra vista tras aplicar un tema y con editar las traducciones.

Para editar un elemento, selecciónalo en el marco Component Tree o pincha directamente sobre él en la ventana de previsualización. Al seleccionarlo, puedes modificar alguna de sus propiedades en el marco Properties, situado a la derecha. Echa un vistazo a las propiedades disponibles para TextView y modifica alguna de ellas. En muchos casos te aparecerá un desplegable con las opciones disponibles. Aquí solo se muestra una pequeña parte de las propiedades disponibles. Pulsa en View all properties para mostrarlas todas.

El marco de la izquierda, Palette, te permite insertar de forma rápida nuevas vistas al layout. Puedes arrastrar cualquier elemento a la ventana de previsualización o al marco Component Tree. En el anexo D se ha incluido una lista con las vistas disponibles.

NOTA: El siguiente vídeo corresponde a una versión anterior de la herramienta. Aunque cambian algunos iconos el funcionamiento continúa siendo similar. Para crear un nuevo layout pulsa con el botón derecho en el explorador de proyecto sobre app y selecciona la opción: New > Android resource file

Vídeo[tutorial]: Diseño visual de layouts: visión general

Ejercicio: Creación visual de vistas

1. Crea un nuevo proyecto con los siguientes datos:

Phone and Tablet / Empty Activity

Name: Primeras Vistas

Minimum API level: API 19 Android 4.4 (KitKat)

Use androidx.* artifacts

Deja el resto de los parámetros con los valores por defecto.

6. Abre el fichero res/layout/activity_main.xml.

7. Vamos a hacer que la raíz del layout se base en un LinearLayout vertical. Este tipo de layout es uno de los más sencillos de utilizar. Te permite representar las vistas una debajo de la otra. En el marco Component Tree pulsa con el botón derecho sobre ConstraintLayout y selecciona Covert View… Indica que quieres usar el layout, LinearLayout. El layout que ha añadido es de tipo horizontal. En nuestro caso lo queremos de tipo vertical, para cambiarlo pulsa con el botón derecho sobre LinearLayout. y selecciona LinearLayout/Convert orientation to vertical.

Todas las operaciones que hacemos en modo diseño visual (lengüeta Design) también las podemos hacer con el editor de texto. Para probarlo, deshaz el trabajo anterior, pulsando el botón Undo (Ctrl+Z). Selecciona la lengüeta Text y cambia la etiqueta ConstraintLayout por LinearLayout. Añade el atributo orientation a LinearLayout para que la orientación sea vertical. Elimina los atributos innecesarios del TextView. que utiliza con ConstraintLayout. El resultado ha de ser similar a:


Regresa a la lengüeta Design.

8. Desde la paleta de la izquierda arrastra, al área de diseño, los siguientes elementos: ToggleButton, CheckBox, SeekBar y RatingBar.


9. Selecciona la primera vista que estaba ya creada (TextView) y pulsa <Supr> para eliminarla.

10. Selecciona la vista ToggleButton. Pulsa ahora (Set layout width to wrap_content). Conseguirás que la anchura del botón se ajuste a la anchura de su texto. Pulsa el botón (Set layout width to match_parent) para que el ancho del botón se ajuste a su contenedor. Observa en el marco Attribues cómo cambia la propiedad layout_width. Si el botón anterior no funciona cámbialo desde este marco. Deja el valor wrap_content.

11. Pulsa el botón (Convert orientation to horizontal), para conseguir que el LinearLayout donde están las diferentes vistas tenga una orientación horizontal. Comprobarás que no caben todos los elementos. Pulsa el botón (Convert orientation to vertical), para volver a una orientación vertical.

12. Con la vista ToggleButton seleccionada, pulsa el botón (Set layoutheight to match_parent). Conseguirás que la altura del botón se ajuste a la altura de su contenedor. El problema es que el resto de los elementos dejan de verse. Vuelve a pulsar este botón para regresar a la configuración anterior (también puedes pulsar Ctrl-Z).

13. Selecciona la vista CheckBox. Ve al marco Attributes y en la parte inferior pulsa en All attributes. Busca la propiedad layout_margin en el campo all introduce “20dp”. Se añadirá un margen alrededor de la vista.


14. Busca la propiedad gravity y selecciona center.


15. Observa que hay un espacio sin usar en la parte inferior del layout. Vamos a distribuir este espacio entre las vistas. Desde el marco Commponet Tree selecciona las cuatro vistas que has introducido dentro del LinearLayout. Para una selección múltiple mantén pulsada la tecla Ctrl.


16. Aparecerá un nuevo botón: (Distribute Weights Evenly). Púlsalo y la altura de las vistas se ajustará para que ocupen la totalidad del layout. Realmente, lo que hace es dividir el espacio sin usar de forma proporcional entre las vistas. Es equivalente a poner layout_weight = 1 y layout_height = 0dp para todas las vistas de este layout. Esta propiedad se modificará en un siguiente punto.

17. Selecciona las cuatro vistas y pulsa el botón (Clear All Weight) para eliminar los pesos introducidos.

18. Selecciona la vista CheckBox. Asigna, en el marco Attributes, layout_height = 1 y layout_weight = 0dp en esta vista. Observa como toda la altura restante es asignada a la vista seleccionada.


19. Para asignar un peso diferente a cada vista, repite los pasos anteriores donde asignábamos peso 1 a todas las vistas (botón: ). Pulsa la lengüeta Text y modifica manualmente el atributo layout_weight para que el ToggleButton tenga valor 2; CheckBox tenga valor 0.5; SeekBar valor 4 y RatingBar valor 1. Pulsa la lengüeta Design. Como puedes observar, estos pesos permiten repartir la altura sobrante entre las vistas.

20. Utiliza los siguientes botones: para ajustar el zum.

21. Utiliza los botones de la barra superior para observar cómo se representará el layout en diferentes situaciones y tipos de dispositivos:


22. Selecciona la vista CheckBox y observa las diferentes propiedades que podemos definir en el marco Attributes. Algunas ya han sido definidas por medio de la barra de botones. En concreto, y siguiendo el mismo orden que en los botones, hemos modificado: Layout margin = 20dp, gravity = center y Layout weight = 0.5.

23. Busca la propiedad Text y sustituye el valor CheckBox por “Guardar automáticamente” y Text size por “9pt”.

24. Pulsa el botón para mostrar la visualización de diseño, la esquemática (Blueprnt) o ambas. A continuación, se muestra el resultado final obtenido:


25. Pulsa sobre la lengüeta Text. Pulsa las teclas Ctrl-Alt-L para que formatee adecuadamente el código XML. A continuación, se muestra este código:


26. Ejecuta el proyecto para ver el resultado en el dispositivo.

Ejercicio: Vistas de entrada de texto

1. Añade en la parte superior del layout anterior una vista de tipo entrada de texto EditText, de tipo normal (Plain Text). Lo encontrarás dentro del grupo Text. Debajo de esta, una de tipo correo electrónico (E-mail) seguida de una de tipo palabra secreta (Password). Continua así con otros tipos de entradas de texto.

2. Ejecuta la aplicación.

3. Observa como al introducir el texto de una entrada se muestra un tipo de teclado diferente.

2.2.2. Los atributos de las vistas

Vídeo[tutorial]: Atributos de la clase View en Android

Vídeo[tutorial]: Atributos de la clase TextView en Android

Recursos adicionales: Atributo de dimensión

En muchas ocasiones tenemos que indicar la anchura o altura de una vista, un margen, el tamaño de un texto o unas coordenadas. Este tipo de atributos se conocen como atributos de dimensión. Dado que nuestra aplicación podrá ejecutarse en una gran variedad de dispositivos con resoluciones muy diversas, Android nos permite indicar estas dimensiones de varias formas. En la siguiente tabla se muestran las diferentes posibilidades:


px (píxeles): Estas dimensiones representan los píxeles en la pantalla.
mm (milímetros): Distancia real medida sobre la pantalla.
in (pulgadas): Distancia real medida sobre la pantalla.
pt (puntos): Equivale a 1/72 pulgadas.
dp (píxeles independientes de la densidad): Presupone un dispositivo de 160 píxeles por pulgada. Si luego el dispositivo tiene otra densidad, se realizará el correspondiente ajuste. A diferencia de otras medidas como mm, in y pt este ajuste se hace de forma aproximada dado que no se utiliza la verdadera densidad gráfica, si no el grupo de densidad en que se ha clasificado el dispositivo (ldpi, mdpi, hdpi…). Esta medida presenta varias ventajas cuando se utilizan recursos gráficos en diferentes densidades. Por esta razón, Google insiste en que se utilice siempre esta medida. Desde un punto de vista práctico un dp equivale aproximadamente a 1/160 pulgadas. Y en dispositivos con densidad gráfica mdpi un dp es siempre un pixel.
sp (píxeles escalados): Similar a dp, pero también se escala en función del tamaño de fuente que el usuario ha escogido en las preferencias. Indicado cuando se trabaja con fuentes.

Recursos adicionales: Tipos de vista y sus atributos

Consulta el anexo D para conocer una lista con todos los descendientes de la clase View y sus atributos.

Preguntas de repaso: Las vistas y sus atributos

2.3. Layouts

Si queremos combinar varios elementos de tipo vista, tendremos que utilizar un objeto de tipo layout. Un layout es un contenedor de una o más vistas y controla su comportamiento y posición. Hay que destacar que un layout puede contener otro layout y que es un descendiente de la clase View.

La siguiente lista describe los layout más utilizados en Android:

LinearLayout: Dispone los elementos en una fila o en una columna.

TableLayout: Distribuye los elementos de forma tabular.

RelativeLayout: Dispone los elementos con relación a otro o al padre.

ConstraintLayout: Versión mejorada de RelativeLayout, que permite una edición visual desde el editor.

FrameLayout: Permite el cambio dinámico de los elementos que contiene.

AbsoluteLayout: Posiciona los elementos de forma absoluta.

Dado que un ejemplo vale más que mil palabras, pasemos a mostrar cada uno de estos layouts en acción:

LinearLayout es uno de los layout más utilizado en la práctica. Distribuye los elementos uno a continuación de otro, bien de forma horizontal o vertical.

<LinearLayout xmlns:android="http://...

android:layout_height="match_parent"

android:layout_width="match_parent"

android: orientation ="vertical">

<AnalogClock

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

<CheckBox

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un checkBox"/>

<Button

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un botón"/>

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un texto cualquiera"/>

</LinearLayout>


TableLayout distribuye los elementos de forma tabular. Se utiliza la etiqueta <TableRow> cada vez que queremos insertar una nueva línea.

<TableLayout xmlns:android=”http://...

android:layout_height="match_parent"

android:layout_width="match_parent">

<TableRow>

<AnalogClock

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

<CheckBox

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un checkBox"/>

</TableRow>

<TableRow>

<Button

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un botón"/>

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un texto cualquiera"/>

</TableRow>

</TableLayout>


RelativeLayout permite comenzar a situar los elementos en cualquiera de los cuatro lados del contenedor e ir añadiendo nuevos elementos pegados a estos.

<RelativeLayout

xmlns:android="http://schemas...

android:layout_height="match_parent"

android:layout_width="match_parent">

<AnalogClock

android:id="@+id/AnalogClock01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentTop="true"/>

<CheckBox

android:id="@+id/CheckBox01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_below = "@id/AnalogClock01"

android:text="Un checkBox"/>

<Button

android:id="@+id/Button01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un botón"

android:layout_below = "@id/CheckBox01"/>

<TextView

android:id="@+id/TextView01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentBottom = "true"

android:text="Un texto cualquiera"/>

</RelativeLayout>


ConstraintLayout versión más flexible y eficiente de RelativeLayout.

<androidx.constraintlayout.widget.ConstraintLayout

xmlns:android="http://schemas...

android:layout_height="match_parent"

android:layout_width="match_parent">

<AnalogClock

android:id="@+id/AnalogClock01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

app:layout_constraintLeft_toLeftOf= "parent"

app:layout_constraintTop_toTopOf= "parent"/>

<CheckBox

android:id="@+id/CheckBox01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un checkBox"

app:layout_constraintTop_toBottomOf=

"@+id/AnalogClock01"

app:layout_constraintTop_toTopOf= "parent"

<Button

android:id="@+id/Button01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un botón"

app:layout_constraintTop_toBottomOf=

"@+id/CheckBox01"

app:layout_constraintLeft_toLeftOf=

"@+id/CheckBox01"/>

<TextView

android:id="@+id/TextView01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un texto cualquiera"

app:layout_constraintBottom_toBottomOf= "parent"

app:layout_constraintLeft_toLeftOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>


FrameLayout posiciona las vistas usando todo el contenedor, sin distribuirlas espacialmente. Este layout suele utilizarse cuando queremos que varias vistas ocupen un mismo lugar. Podemos hacer que solo una sea visible, o superponerlas. Para modificar la visibilidad de un elemento utilizaremos la propiedad visibility.

<FrameLayout xmlns:android="http://schemas...

android:layout_height="match_paren"

android:layout_width="match_parent">

<AnalogClock

android:layout_width="wrap_content"

android:layout_height="wrap_conten"/>

<CheckBox

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un checkBox"/>

<Button

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un botón"

android:visibility="invisible"/>

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un texto cualquiera"

android:visibility="invisible"/>

</FrameLayout>


AbsoluteLayout permite indicar las coordenadas (x, y) donde queremos que se visualice cada elemento. No es recomendable utilizar este tipo de layout. La aplicación que estamos diseñando tiene que visualizarse correctamente en dispositivos con cualquier tamaño de pantalla. Para conseguirlo, no es una buena idea trabajar con coordenadas absolutas. De hecho, este tipo de layout ha sido marcado como obsoleto.

<AbsoluteLayout xmlns:android="http://schemas.

android:layout_height="match_parent"

android:layout_width="match_parent">

<AnalogClock

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_x= "50px"

android:layout_y="50px"/>

<CheckBox

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un checkBox"

android:layout_x= "150px"

android:layout_y="50px"/>

<Button

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un botón"

android:layout_x= "50px"

android:layout_y="250px"/>

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Un texto cualquiera"

android:layout_x= "150px"

android:layout_y="200px"/>

</AbsoluteLayout>


Si tienes dudas sobre cuándo emplear cada layout, usa la siguiente tabla:

LinearLayout: Diseños muy sencillos.

RelativeLayout: Nunca, hay una nueva alternativa.

ConstraintLayout: Usar por defecto.

FrameLayout: Varias vistas superpuestas.

AbsoluteLayout: Nunca. Aunque está bien conocerlo por si acaso.

Vídeo[tutorial]: Los layouts en Android

Preguntas de repaso: Tipos de layouts

Preguntas de repaso: Atributos de los layouts

También podemos utilizar otros layouts, que se describen a continuación:

ScrollView: Visualiza una vista en su interior; cuando esta no cabe en pantalla, se permite un deslizamiento vertical.

HorizontalScrollView: Visualiza una vista en su interior; cuando esta no cabe en pantalla, se permite un deslizamiento horizontal.


TabLayout, FragmentTabHost, TabLayout o TabHost: Proporciona una lista de pestañas que pueden ser pulsadas por el usuario para seleccionar el contenido a visualizar. Se estudia al final del capítulo.


ListView: Visualiza una lista deslizable verticalmente de varios elementos. Su utilización es algo compleja. Se verá un ejemplo en el capítulo siguiente.


GridView: Visualiza una cuadrícula deslizable de varias filas y varias columnas.


RecyclerView: Versión actualizada que realiza las mismas funciones que ListView o GridView. Se verá en el siguiente capítulo.

ViewPager: Permite visualizar una serie de páginas, donde el usuario puede navegar arrastrando a derecha o izquierda. Cada página ha de ser almacenada en un fragment.

2.3.1. Uso de ConstraitLayout

Este nuevo layout ha sido añadido en una librería de compatibilidad, por lo que se nos anima a usarlo de forma predeterminada. Nos permite crear complejos diseños sin la necesidad de usar layouts anidados. El hecho de realizar diseños donde un layout se introduce dentro de otro y así repetidas veces, ocasionaba problemas de memoria y eficiencia en dispositivos de pocas prestaciones.

Es muy parecido a RelativeLayout, pero más flexible y fácil de usar desde el editor visual de Android Studio (disponible desde la versión 2.3). De hecho, se recomienda crear tu layout con las herramientas drag-and-drop, en lugar de editar el fichero XML. El resto de layouts son más fáciles de crear desde XML.

Las posiciones de las diferentes vistas dentro de este layout se definen usando constraint (en castellano restricciones). Un constraint puede definirse en relación al contenedor (parent), a otra vista o respecto a una línea de guía (guideline). Es necesario definir para cada vista al menos un constraint horizontal y uno vertical. No obstante, también podemos definir más de un constraint en el mismo eje. Veamos un ejemplo:


Observa cómo la vista A está posicionada con respecto al contenedor. La vista B está posicionada verticalmente con respecto a la vista A, aunque se ha definido un segundo constraint con respecto al lado derecho del contenedor. Veremos más adelante cómo se maneja esta circunstancia.

También podemos posicionar las vistas usando alineamientos. Observa cómo el borde superior de B está alineado con el borde superior de A. La vista C define dos alineamientos horizontales simultáneos, pero ninguno vertical, lo que ocasionará un error de compilación. También podemos realizar alineamientos usando la línea base de texto y líneas de guía, como se muestra a continuación:


Ejercicio: Creación de un layout con ConstraintLayout

1. Abre el proyecto PrimerasVistas o crea uno nuevo.

2. En Gradle Scripts/Bulid.gradle (Module:app) ha de estar la dependencia:


3. Abre el layout activity_main.xml creado en el ejercicio anterior. Pulsa con el botón derecho en Component Tree y selecciona la opción Convert LinearLayout to ConstraintLayout. Esta herramienta nos permite convertir nuestros viejos diseños que se basaban en LinearLayout o RelativeLayout en este nuevo tipo de layouts. Por desgracia, no siempre funciona todo lo bien que desearíamos.

4. Crea un nuevo layout. Para ello, pulsa con el botón derecho sobre app/res/layout y selecciona New/Layout resource file. Como nombre introduce “constraint” y en Root element: androidx.constraintlayout.widget.ConstraintLayout.

5. Vamos a desactivar la opción de Autoconnect de la barra de acciones del ConstraintLayou. Es el segundo icono con forma de imán:


Tener activa esta opción es útil para diseñar más rápido los layouts. No obstante, a la hora de aprender a usar los constraint, es mejor ir haciéndolos de uno en uno.

6. Dentro del área Palette, selecciona Common y arrastra una vista de tipo ImageView al área de diseño. Se abrirá una ventana con diferentes recursos Drawable. Selecciona en Project, ic_launcher.

7. Para definir el primer constraint, pulsa sobre el punto de anclaje que aparece en la parte superior del ImageView y arrástralo hasta el borde superior del contenedor:


8. En la parte superior derecha nos aparece un editor visual para los constraint. Por defecto la distancia seleccionada ha sido 8dp. Pulsa sobre este número y cámbialo a 32dp:


NOTA: Según las recomendaciones de Material Design, los márgenes y tamaños han de ser un múltiplo de 8dp.

9. Realiza la misma operación con el punto de anclaje izquierdo, arrastrándolo al borde izquierdo. Ya tenemos la restricción horizontal y vertical, por lo que la vista está perfectamente ubicada en el layout.

10. Arrastra el punto de anclaje derecho al borde derecho, introduciendo una distancia de 32dp:


Observa como en este caso, al tener que cumplir simultáneamente dos constraint horizontales la imagen se centra horizontalmente. Esto se representa con la línea en zigzag, representando un muelle, que estira de la vista desde los dos lados. El pequeño botón con una cruz roja que aparece nos permite borrar todos los constraint de la vista.

11. Si en lugar de querer la imagen centrada la queremos en otra posición, podemos ir al editor de constraint y usar la barra deslizante (Horizontal Bias). Desplázarla a la posición 25.


Observa en el área de trabajo como la longitud del muelle de la izquierda es un 25 %, frente al 75 % del muelle de la derecha.

12. Seleccionando el ImageView en el área de trabajo, arrastra el cuadrado azul de la esquina inferior derecha hasta aumentar su tamaño a 96x96 dp (múltiplos de 8). Otra alternativa es modificar los valores layout_width y layout_height en el área Properties.

13. Desde el marco Palette / Common, añade un TextView a la derecha del ImageView. Arrastra el punto de anclaje de la izquierda hasta el punto de la derecha de la imagen y establece un margen de 64 dp. Arrastra el punto de anclaje superior del TextView hasta el punto superior de la imagen:


14. Añade un nuevo TextView bajo el anterior, con texto “hola”. Introduce tres constraint, usando los puntos de anclaje inferior, izquierdo y derecho, tal y como se muestra en la siguiente figura:


El margen inferior ha de ser 16dp y el izquierdo y derecho 0. De esta forma hemos centrado horizontalmente los dos TextView.

15. También podemos conseguir que el ancho del nuevo TextView coincida con el superior. Para ello selecciona la vista y en el campo layout_width e introduce match_constraint o 0dp. Con esto, hacemos que el ancho se calcule según las restricciones de los constraint. Quita los márgenes laterales para que los anchos de las dos vistas coincidan.


16. Haz que desde MainActivity se visualice este layout y ejecuta el proyecto en un dispositivo.

Una vez familiarizados con los conceptos básicos de los constraint vamos a ver con más detalle las herramientas disponibles. Veamos en editor de constraint:


(1) relación de tamaño: Puede establecer el tamaño de la vista en una proporción, por ejemplo a 16:9, si al menos una de las dimensiones de la vista está configurada como "ajustar a constraint" (0dp). Para activar la relación de tamaño, haz clic donde señala el número 1.

(2) eliminar constraint: Se elimina la restricción para este punto de anclaje.

(3) establecer alto/ancho: Para cambiar la forma en la que se calcula las dimensiones de la vista, pulsa en este elemento. Existen tres posibilidades:

ajustar a contenido: equivale al valor warp_content. (Ej. 1er TextView)

ajustar a constraint: equivale a poner 0dp. (Ej. 2º TextView)

tamaño fijo: equivale a poner un valor concreto de dp. (Ej. ImageView) Aunque se representan 4 segmentos, realmente podemos cambiar 2, los horizontales para el ancho y los verticales para el alto.

(4) establecer margen: Podemos cambiar los márgenes de la vista.

(5) sesgo del constraint: Ajustamos cómo se reparte la dimensión sobrante.

También es importante repasar las acciones disponibles cuando trabajamos con ConstraintLayout:


Ocultar constraint: Elimina las marcas que muestran las restricciones y los márgenes existentes.

Autoconectar: Al añadir una nueva vista se establecen unos constraint con elementos cercanos de forma automática.

Definir márgenes: Se configura los márgenes por defecto.

Borrar todos los constraint: Se eliminan todas las restricciones del layout.

Crear automáticamente constraint: Dada una vista seleccionada, se establecen unos constraint con elementos cercanos de forma automática.

Empaquetar / expandir: Se agrupan o se separan los elementos.

Alinear: Centra o justifica los elementos seleccionados.

Añadir línea de guía: Se crea una nueva línea de referencia.

Ejercicio: Líneas guía y cadenas en ConstraintLayout

1. Siguiendo con el layout del ejercicio anterior. Pulsa en la acción Guideline y selecciona Add Horizontal GuideLine. Aparecerá un círculo gris con un pequeño triángulo pegado al borde izquierdo, desde donde sale una línea guía horizontal. Arrástrala hacia abajo hasta separarla una distancia de 160dp.


2. Esta guía nos permite dividir el layout en dos áreas: la superior, donde ya hemos realizado una especie de cabecera, y la inferior. A partir de ahora los elementos de la parte inferior los colocaremos en relación a esta línea guía.

3. Selecciona el ImageView, cópialo (Ctrl+C) y pégalo tres veces (Ctrl+V). Acabamos de hacer tres copias de la imagen, pero no son visibles al estar en la misma posición. En el área Component Tree, selecciona imageView2 y arrástralo bajo la línea guía, pegado a la izquierda. Coloca imageView3 bajo la línea guía, en el centro, e imageView4, a la derecha de este.

4. Selecciona imageView2 con el botón derecho y borra todos sus constraint seleccionando Clear Constraint of Selección. Repite esta operación para imageView3 e imageView4.

5. Las tres imágenes han de tener un constraint desde el punto de anclaje superior a la línea guía con un margen de 32dp. Desde el punto de anclaje izquierdo de imageView2, establece un constraint con el borde izquierdo y en las otras dos imágenes, al punto de anclaje derecho de la vista de la derecha. El punto de anclaje derecho de la tercera vista únelo al borde derecho. El resultado ha de ser el siguiente:


6. Para conseguir que estas tres vistas formen una cadena, selecciónalas y utiliza la acción Align / Horizontaly o el botón derecho Chains / Create Horizontal Chain:


Observa cómo las vistas ahora están unidas por medio de un conector de cadena. Si abres la lengüeta Text para estudiar el XML, puedes comprobar que para establecer la cadena se han añadido dos constraint, desde el punto de anclaje derecho de las dos primeras vista hacia la vista de su izquierda. Es decir, una restricción mutua: de A -> B y de B -> A.

NOTA: En la versión actual del editor visual, parece que establecer la cadena indicando estos constraint individualmente no parece posible. Hay que usar la acción Align / Horizontaly o Chains / Create Horizontal Chain.

7. También es posible otras distribuciones de cadena. Podemos hacer que los márgenes se distribuyan solo entre las vistas o solo en los extremos izquierdo y derecho:


Si abres la lengüeta Text puedes comprobar que estas dos nuevas configuraciones de cadena se consiguen añadiendo en la primera vista el atributo:

app:layout_constraintHorizontal_chainStyle="spread_inside"

Para la primera distribución y para la segunda:

app:layout_constraintHorizontal_chainStyle="packed"

Para la distribución del punto anterior el valor es "spread" o no indicar nada.

8. Existe otra distribución en la que los márgenes desaparecen y se ajusta el ancho de las vistas hasta cubrir todo el espacio disponible. Selecciona la vista central y en el editor de constraint pulsa sobre el icono hasta que aparezca . Recuerda que esta acción es equivalente a poner 0 en layout_width. El resultado se muestra a la izquierda:


Para conseguir el resultado de la derecha, hemos repetido la operación con las otras dos imágenes.

Si en lugar de repartir los anchos por igual, quieres otra configuración, puedes usar el atributo layout_constraintHorizontal_weight (funciona igual que layout_weight en un LinearLayout).

9. Ejecuta el proyecto en un dispositivo.

Al crear constraint, recuerde las siguientes reglas:

• Cada vista debe tener al menos dos restricciones: una horizontal y otra vertical.

• Solo puede crear restricciones que compartan el mismo plano. Así, el plano vertical (los lados izquierdo y derecho) de una vista puede anclarse solo a otro plano vertical.

• Cada manejador de restricción puede utilizarse para una sola restricción, pero puede crear varias restricciones (desde vistas diferentes) al mismo punto de anclaje.

Práctica: Uso de layouts

1. Utiliza un ConstraintLayout para realizar un diseño similar al siguiente:


2. Utiliza un TableLayout para realizar un diseño similar al siguiente:


3. Utiliza un LinearLayout horizontal que contenga en su interior otros LinearLayout para realizar un diseño similar al siguiente. Ha de ocupar toda la pantalla:


4. Visualiza el resultado obtenido en diferentes tamaños de pantalla. ¿Se visualiza correctamente?

5. Realiza el ejercicio de la calculadora usando un ConstraintLayout.

Preguntas de repaso: ConstraintLayout

2.4. Una aplicación de ejemplo: Asteroides

A lo largo de este libro vamos a ir creando una aplicación de ejemplo que toque los aspectos más significativos de Android. Comenzamos en este capítulo creando una serie de vistas que nos permitirán diseñar una sencilla interfaz de usuario. Si quieres ver cómo quedará la aplicación una vez termines el libro, puedes ver el siguiente vídeo:

Vídeo[tutorial]: Asteroides

Enlaces de interés:

• Asteroides: Puedes descargarte la aplicación de Google Play:

https://play.google.com/store/apps/details?id=es.upv.mmoviles.asteroides&hl

Práctica: Creación de la aplicación Asteroides

1. Crea un nuevo proyecto con los siguientes datos:

Phone and Tablet / Empty Activity

Name: Asteroides

Package name: org.example.asteroides

Language: Java

Minimum API level: API 19 Android 4.4 (KitKat)

NOTA: Deja el resto de los parámetros con su valor por defecto.

2. Abre el fichero res/layout/ activity_main.xml y trata de crear una vista similar a la que ves a continuación. Ha de estar formada por un LinearLayout que contiene un TextView y cuatro Button. Trata de utilizar recursos para introducir los cinco textos que aparecen.


Solución:

1. El fichero activity_main.xml ha de ser similar al siguiente:


2. El fichero res/values/strings.xml ha de tener el siguiente contenido:


Práctica: Uso de ConstraintLayout en Asteroides

Repite la práctica anterior pero esta vez usando un ConstraintLayout:

2.5. La aplicación Mis Lugares

En este libro vamos a crear una segunda aplicación con características muy diferentes de Asteroides. Tendrá por nombre Mis Lugares y permitirá que los usuarios guarden información relevante sobre los sitios que suelen visitar (restaurantes, tiendas, etc.). En el capítulo 1 se implementaron algunas clases de esta aplicación y se presentó un vídeo que describía su funcionamiento. A diferencia de Asteroides, esta aplicación utilizará un diseño y varios elementos de Material Design. Una explicación más extensa de estos conceptos se abordará en El Gran Libro de Android Avanzado. Para más información sobre Material Design y el siguiente ejercicio te recomendamos un tutorial 17.

Vídeo[tutorial]: Mis Lugares

Ejercicio: Creación de la aplicación Mis Lugares

1. Crea un nuevo proyecto con los siguientes datos:

Phone and Tablet / Scrolling Activity

Name: Mis Lugares

Package name: com.example.mislugares

Language: Java ó Kotlin

Minimum API level: API 19 Android 4.4 (KitKat)

De esta forma, se creará una aplicación con una actividad basada en Material Design. Dispondrá de una barra de acciones y un botón flotante. El contenido principal podrá desplazarse, a la vez que la barra de acciones cambia de tamaño.

2. En el navegador de proyecto pulsa con el botón derecho sobre la clase ScrollingActivity y selecciona Refactor > Rename. Introduce como nuevo nombre MainActivity. En la carpeta res/layout renombra el fichero activity_scrolling.xml por activity_main.xml. En la misma carpeta renombra content_scrolling.xml por content_main.xml. Finalmente, en la carpeta res/menu renombra menu_scrolling.xml por menu_main.xml.

3. Ejecuta el proyecto y verifica su comportamiento:


NOTA: Además del tutorial indicado puedes hacer el siguiente 18.

Práctica: Creación de una primera actividad en Mis Lugares

En esta práctica crearemos una primera actividad que contendrá simplemente cuatro botones.

1. Edita el fichero res / layout / content_main.xml y trata de crear una vista similar a la que ves a continuación. Has de dejar el NestedScrollView que ya tenías y reemplazar el TextView por un ConstraintLayout o LinearLayout que contenga cuatro Button. Un NestedScrollView solo puede contener dentro un elemento, por lo que no puedes introducir directamente los cuatro botones. Usando un layout que los contenga se resuelve el problema.


Solución: http://www.androidcurso.com/index.php/115

Práctica: Un formulario para introducir nuevos lugares

El objetivo de esta práctica es crear un layout que permita introducir y editar lugares en la aplicación Mis Lugares.

1. Crea un nuevo layout con nombre edicion_lugar.xml.

2. Ha de parecerse al siguiente formulario. Puedes basarte en un LinearLayout o un ConstraintLayout para distribuir los elementos. Pero es importante que este layout, se encuentre dentro de un NestedScrollView para que cuando el formulario no quepa en pantalla se pueda desplazar verticalmente.


3. Introduce a la derecha del TextView con texto “Tipo:” un Spinner con id tipo. Más adelante configuraremos esta vista para que muestre un desplegable con los tipos de lugares.

4. Las vistas EditText han de definir el atributo id con los valores: nombre, direccion, telefono, url y comentario. Utiliza también el atributo hint para dar indicaciones sobre el valor a introducir. Utiliza el atributo inputType para indicar qué tipo de entrada esperamos. De esta manera se mostrará un teclado adecuado (por ejemplo, si introducimos un correo electrónico aparecerá la tecla @).

NOTA: El atributo inputType admite los siguientes valores (en negrita los que has de utilizar en este ejercicio): none, text, textCapCharacters, textCapWords, textCapSentences, textAutoCorrect, textAutoComplete, textMultiLine, textImeMultiLine, textNoSuggestions, textUri, textEmailAddress, textEmailSubject, textShortMessage, textLongMessage, textPersonName, textPostalAddress, textPassword, textVisiblePassword, textWebEditText, textFilter, textPhonetic, textWebEmailAddress, textWebPassword, number, numberSigned, numberDecimal, numberPassword, phone, datetime, date y time.

5. Abre la clase MainActivity y en el método onCreate() reemplaza el layout:

setContentView(R.layout<strike>.activity_main</strike>.edicion_lugar)

6. Comenta todas las líneas de este método que hay debajo usando /* ... */. Como ya no se crea el layout activity_main los id de vista a los que se accede ya no existen.

7. Ejecuta la aplicación y verifica cómo cambia el tipo de teclado en cada EditText.

8. Deshaz el cambio realizado en el punto 5 y 6.

Solución: http://www.androidcurso.com/index.php/115

2.6. Recursos alternativos

Una aplicación Android va a poder ser ejecutada en una gran variedad de dispositivos. El tamaño de pantalla, la resolución o el tipo de entradas puede variar mucho de un dispositivo a otro. Por otra parte, nuestra aplicación ha de estar preparada para diferentes modos de funcionamiento, como el modo “automóvil” o el modo “noche”, y para poder ejecutarse en diferentes idiomas.

A la hora de crear la interfaz de usuario, hemos de tener en cuenta todas estas circunstancias. Afortunadamente, la plataforma Android nos proporciona una herramienta de gran potencia para resolver este problema: el uso de los recursos alternativos.

NOTA: Las prácticas de este apartado se proponen para la aplicación Asteroides, pero también pueden realizarse con Mis Lugares.

Práctica: Recursos alternativos en Asteroides

1. Ejecuta la aplicación Asteroides (o Mis Lugares).

2. Los teléfonos móviles basados en Android permiten cambiar la configuración en apaisado y en vertical. Para conseguir este efecto con el emulador, pulsa el botón . Si usas un dispositivo de pantalla pequeña, observas como el resultado de la vista que acabas de diseñar en vertical no queda todo lo bien que desearíamos.


Para resolver este problema, Android te permite diseñar una vista diferente para la configuración horizontal y otra para la vertical.

3. Pulsa con el botón derecho sobre la carpeta res/layout y selecciona New > Layout resource file. Aparecerá una ventana donde has de rellenar en File name: activity_main, en Available qualifiers: selecciona Orientation y pulsa en el botón >>. En el desplegable Screen orientation: selecciona Landscape. Pulsa en OK. Observa como ahora hay dos recursos para el fichero activity_main.xml.

El primero es el recurso por defecto, mientras que el segundo es el que se usará cuando el dispositivo esté en orientación Landscape.


4. Crea en el nuevo layout (land) una vista similar a la que ves a continuación: formada por un TableLayout con dos Button por columna.


5. Ejecuta de nuevo la aplicación y observa como la vista se ve correctamente en las dos orientaciones.

Solución:

Has de obtener un código XML similar al siguiente:


NOTA: Para conseguir que en un TableLayout las columnas se ajusten a todo el ancho de la tabla, poner stretchColumns="*". stretchColumns="0" significa que se asigne la anchura sobrante a la primera columna. stretchColumns="1" significa que se asigne la anchura sobrante a la segunda columna. stretchColumns="*" significa que se asigne la anchura sobrante entre todas las columnas.

Android utiliza una lista de sufijos para expresar recursos alternativos. Estos sufijos pueden hacer referencia a la orientación del dispositivo, el lenguaje, la región, la densidad de píxeles, la resolución, el método de entrada, etc.

Por ejemplo, si queremos traducir nuestra aplicación al inglés, español y francés, siendo el primer idioma el usado por defecto, crearíamos tres versiones del fichero strings.xml y lo guardaríamos en los tres directorios siguientes:

res/values/strings.xml

res/values-es/strings.xml

res/values-fr/strings.xml

Aunque internamente el SDK de Android utiliza la estructura de carpetas anterior, en Android Studio el explorador del proyecto muestra los recursos alternativos de la siguiente manera:

res

values

strings.xml(3)

strings.xml

strings.xml(es)

strings.xml(fr)

Ejercicio: Traducción de Asteroides

1. Crea un nuevo recurso alternativo para strings.xml (en): Pulsa con el botón derecho en res/values, selecciona New > Values resource file e introduce strings como nombre de fichero. Mueve el cualificador Locale (o Language) desde el marco de la izquierda a la derecha, pulsando el botón >>. En Language selecciona English, en Specific Region Only deja el valor Any Region y pulsa OK.


NOTA: Observa cómo además del idioma también permite seleccionar la región. De esta forma podremos diferenciar entre inglés americano, británico, australiano, …

2. Copia el contenido del recurso por defecto, strings.xml, al recurso para inglés, strings.xml (en). Traduce los textos al inglés. No has de traducir los nombres de los identificadores de recursos (accion_mostrar, app_name, …) estos han de ser igual en todos los idiomas.

3. Ejecuta la aplicación.

4. Vamos a cambiar la configuración de idioma en un dispositivo Android. Para ello accede a Ajustes del dispositivo (Settings) y selecciona la opción Personal > Idioma y entrada. Dentro de esta opción selecciona como idioma Español o Inglés. NOTA: Observa que en otros idiomas permite seleccionar tanto el idioma como la región. Por desgracia, para el español solo permite dos regiones: España y Estados Unidos.

5. Observa como el texto aparece traducido al idioma seleccionado.

Otro ejemplo de utilización de recursos diferenciados lo podemos ver con el icono que se utiliza para lanzar la aplicación. Observa cómo, al crear una aplicación, este icono se crea en cinco carpetas mipmap diferentes, para utilizar un icono distinto según la densidad de píxeles del dispositivo:

res/mipmap-mdpi/ic_launcher.png

res/mipmap-hdpi/ic_launcher.png

res/mipmap-xhdpi/ic_launcher.png

res/mipmap-xxhdpi/ic_launcher.png

res/mipmap-xxxhdpi/ic_launcher.png

NOTA: En el siguiente capítulo se describe por qué se actúa de esta manera.

Resulta posible indicar varios sufijos concatenados; por ejemplo:

res/values-en-rUS/strings.xml

res/values-en-rUK/strings.xml

Pero cuidado, Android establece un orden a la hora de encadenar sufijos. Puedes encontrar una lista de estos sufijos en el apéndice C y en este enlace:

http://developer.android.com/guide/topics/resources/providing-resources.html

Para ver los sufijos disponibles, también puedes pulsar con el botón derecho sobre una carpeta de recursos y seleccionar New > Android resource file. Esta opción te permite crear un nuevo recurso y poner el sufijo deseado de forma y orden correctos.


Vídeo[tutorial]: Uso de recursos alternativos en Android

Ejercicio: Creando un layout para tabletas en Asteroides

Si ejecutas la aplicación Asteroides (o Mis Lugares) en una tableta, observarás que los botones son demasiado alargados (izquierda). Queremos que en este caso la apariencia sea similar a la mostrada a la derecha:


1. Crea un recurso alternativo a res/values/dimens.xml, que sea utilizado en pantallas de tamaño xlarge (7-10,5 pulgadas) en orientación land (apaisado). En este fichero define el siguiente valor:


2. Añade el mismo valor al recurso por defecto, pero esta vez con 30dp.

3. Modifica los ficheros res/layout/content_main.xml y content_main.xml (lan), reemplazando android:padding="30dp" por android:padding= "@dimen/margen_botones".

4. Verifica que la aplicación se visualiza correctamente en todos los tipos de pantalla, tanto en horizontal como en vertical.

Preguntas de repaso: Recursos alternativos

Enlaces de interés: Recursos alternativos

http://www.androidcurso.com/images/dcomg/ficheros/recursos_alternativos.pdf

2.7. Tipos de recursos y recursos del sistema

La definición de los recursos en Android es un aspecto muy importante en el diseño de una aplicación. Una de sus principales ventajas es que facilita a los diseñadores gráficos e introductores de contenido trabajar en paralelo con los programadores.

Añadir un recurso a nuestra aplicación es muy sencillo, no tenemos más que añadir un fichero dentro de una carpeta determinada de nuestro proyecto. Para cada uno de los recursos que añadamos el sistema crea, de forma automática, un id de recurso dentro de la clase R.

2.7.1. Tipos de recursos

Según la carpeta que utilicemos, el recurso creado será de un tipo específico. Pasamos a enumerar las carpetas y los tipos posibles:


Carpeta identificadorDescripción
res/drawable/R.drawableFicheros en bitmap (.png, .jpg o .gif). Ficheros PNG en formato Nine-patch (.9.png). Ficheros XML con descriptores gráficos (véase clase Drawable).
res/mipmap/R.mipmapFicheros en bitmap (.png, .jpg o .gif). Estos gráficos no son rescaldados para adaptarlos a la densidad gráfica del dispositivo, si no que se buscará en las subcarpetas el gráfico con la densidad más parecida y se utilizará directamente.
res/layout/R.layoutFicheros XML con los layouts usados en la aplicación.
res/menu/R.menuFicheros XML con la definición de menús, que podemos asignar a una actividad o a una vista.
res/anim/R.animFicheros XML que permiten definir animaciones Tween, también conocidas como animaciones de vista.
res/animatorR.animatorFicheros XML que permiten modificar las propiedades de un objeto a lo largo del tiempo (véase apartado “Animación de propiedades”). Solo desde la versión 3.0.
res/xml/R.xmlOtros ficheros XML, como los ficheros de preferencias.
res/raw/R.rawFicheros que se encuentran en formato binario. Por ejemplo, ficheros de audio o vídeo.
res/values/Ficheros XML que definen un determinado valor para definir un color, un estilo, una cadena de caracteres, etc. Se describen en la siguiente tabla.

Tabla 2: Tipos de recursos según carpeta en Android.

Veamos los tipos de recursos que encontramos dentro de la carpeta values:


Fichero por defecto identificadorDescripción
strings.xmlR.stringIdentifica cadenas de caracteres.<string name="saludo">¡Hola Mundo!</string>
colors.xmlR.colorUn color definido en formato ARGB (alfa, rojo, verde y azul). Los valores se indican en hexadecimal en uno de los formatos: #RGB, #ARGB, #RRGGBB ó #AARRGGBB.<color name="verde_opaco">#0f0</color><color name=" red_translucido">#80ff0000</color>
dimensions.xmlR.dimenUn número seguido de una unidad de medida.px – píxeles; mm – milímetros; in – pulgadas; pt – puntos (= 1/72 pulgadas); dp – píxeles independientes de la densidad (= 1/160 pulgadas); sp – igual que dp, pero cambia según las preferencias de tamaño de fuente.<dimen name="alto">2.2mm</dimen><dimen name="tamano_fuente">16sp</dimen>
styles.xmlR.styleDefinen una serie de atributos que pueden ser aplicados a una vista o a una actividad. Si se aplican a una actividad, se conocen como temas.<style name="TextoGrande" parent="@style/Text"><item name="android:textSize">20pt</item><item name="android:textColor">#000080</ítem></style>
R.intDefine un valor entero.<integer name="max_asteroides">5</integer>
R.boolDefine un valor booleano.<bool name="misiles_ilimitados">true</bool>
R.idDefine un recurso de id único. La forma habitual de asignar un id a los recursos es con el atributo id="@+id/nombre". Aunque en algunos casos puede ser interesante disponer de un id previamente creado, para que los elementos así nombrados tengan una determinada función. Este tipo de id se utiliza en las vistas TabHost y ListView.<item type="id" name="button_ok" /><item type="id" name="dialog_exit" />
R.arrayUna serie ordenada de elementos. Pueden ser de strings, de enteros o de recursos (TypedArray).<string-array name="dias_semana"><item>lunes</item><item>martes</item></string-array><integer-array name="primos"><item>2</item><item>3</item><item>5</item></integer-array><array name="asteroides"><item>@drawable/asteroide1</item><item>@drawable/asteroide2</item></array>

Tabla 3: Tipos de recursos en carpeta values.

Aunque el sistema crea ficheros que aparecen en la columna de la izquierda de la tabla anterior y se recomienda definir los recursos de cadena dentro de strings.xml, hay que resaltar que no es más que una sugerencia de organización. Sería posible mezclar cualquier tipo de recurso de esta tabla dentro de un mismo fichero y poner a este fichero cualquier nombre.

Vídeo[tutorial]: Tipos de recursos en Android

2.7.2. Acceso a los recursos

Una vez definido un recurso, este puede ser utilizado desde un fichero XML o desde Java. A continuación se muestra un ejemplo desde XML:

<ImageView

android:layout_height="@dimen/alto"

android:layout_width="match_parent"

android:background="@drawable/asteroide"

android:text="@string/saludo"

android:text_color="@color/verde_opaco"/>

Para acceder a un recurso definido en los ejemplos anteriores, usaremos el siguiente código:


2.7.3. Recursos del sistema

Además de los recursos que podamos añadir a nuestra aplicación, también podemos utilizar una serie de recursos que han sido incluidos en el sistema.

Vídeo[tutorial]: Recursos del sistema en Android

Usar recursos del sistema tiene muchas ventajas. No consumen memoria en nuestra aplicación, al estar ya incorporados al sistema. Además, los usuarios están familiarizados con ellos. Por ejemplo, si utilizamos el recurso android.R.drawable.ic_menu_edit, se mostrará al usuario el icono: . Muy posiblemente, el usuario ya está familiarizado con este icono y lo asocia a la acción de editar. Otra ventaja es que los recursos del sistema se adaptan a las diferentes versiones de Android. Si se utiliza el tema android.R.style. Theme_Panel, este es bastante diferente en cada una de las versiones, pero seguro que estará en consonancia con el resto de estilos para esta versión. Lo mismo ocurre con el icono anterior. Este icono es diferente en algunas versiones, pero al usar un recurso del sistema nos aseguramos de que se mostrará el adecuado a la versión del usuario. Finalmente, estos recursos se adaptan siempre a las configuraciones locales.

Si yo utilizo el recurso android.R.string.cancel, este será “Cancelar”, “Cancel”, “取 消”, etc., según el idioma escogido por el usuario.

Para acceder a los recursos del sistema desde código, usaremos la clase android.R. Se usa la misma estructura jerárquica de clases. Por ejemplo, android.R.drawable.ic_menu_edit. Para acceder desde XML, utilizamos la sintaxis habitual pero comenzando con @android:. Por ejemplo, @android:drawable/ic_menu_edit.

Para buscar recursos del sistema tienes varias alternativas:

• Usa la opción de autocompletar de Android Studio.

• Emplea el buscador de recursos que se incluye en el editor de layouts.

• Usa la aplicación android.R para explorar los recursos del sistema.


Ücretsiz ön izlemeyi tamamladınız.

Türler ve etiketler

Yaş sınırı:
0+
Hacim:
1123 s. 1022 illüstrasyon
ISBN:
9788426727374
Yayıncı:
Telif hakkı:
Bookwire
İndirme biçimi:

Benzer kitaplar