====== Programación de dispositivos móviles con Android ====== ===== Android ===== Android es un sistema operativo basado en Linux, diseñado principalmente para dispositivos móviles como teléfonos y tabletas, aunque también se utiliza en relojes, televisores, automóviles y otros dispositivos. Para desarrollar aplicaciones Android se utiliza el **Android SDK** (Software Development Kit), un conjunto de herramientas, bibliotecas y APIs que permiten crear, compilar, probar y depurar aplicaciones. {{ :bloque1:android_logo.png?200 |}} De forma simplificada podemos distinguir: * Android: el sistema operativo que se ejecuta en el dispositivo * Android SDK: las herramientas y APIs utilizadas para desarrollar aplicaciones * Android Studio: el entorno de desarrollo utilizado para escribir y gestionar nuestros proyectos Las aplicaciones Android se ejecutan sobre ART (Android Runtime), el entorno de ejecución utilizado actualmente por Android. ==== Android Studio ==== **Android Studio** es el entorno de desarrollo integrado (IDE) oficial para crear aplicaciones Android. Está basado en //IntelliJ IDEA// e incorpora las herramientas necesarias para facilitar el desarrollo. {{ :bloque1:android-studio.png?300|}} Entre sus principales características se encuentran: * Editor de código para Kotlin y Java * Integración con Gradle para compilar los proyectos * Gestión del Android SDK * Emulador de dispositivos Android * Herramientas de depuración * Diseño y previsualización de interfaces * Integración con sistemas de control de versiones como Git Durante el módulo utilizaremos Android Studio, Kotlin y el Android SDK para desarrollar nuestras aplicaciones. Android Studio es el IDE, pero por sí solo no contiene todas las APIs necesarias para desarrollar aplicaciones. Para ello necesita utilizar el **Android SDK**. ==== Android SDK ==== El **Android SDK (Software Development Kit)** es el conjunto de herramientas, bibliotecas y APIs necesarias para desarrollar aplicaciones para Android. El SDK incluye, entre otros elementos: * Las APIs correspondientes a las diferentes versiones de Android * Herramientas de compilación * Herramientas para comunicarse con dispositivos Android * Herramientas de depuración * Gestión de dispositivos virtuales * Utilidades utilizadas internamente por Android Studio Android Studio permite instalar y gestionar estos componentes mediante el **SDK Manager**. Por ejemplo, un equipo puede tener instaladas diferentes versiones del SDK: Android SDK | +-- Android API 35 +-- Android API 36 +-- Android API 37 | +-- Build Tools | +-- Platform Tools | +-- adb No es necesario instalar todas las versiones disponibles. Normalmente se instalan únicamente aquellas que van a utilizarse para desarrollar y probar las aplicaciones. ==== Versiones de Android y niveles de API ==== Android ha tenido numerosas versiones desde su aparición. Cada versión incorpora nuevas funcionalidades y modificaciones en el sistema operativo. Para identificar las capacidades disponibles en cada versión, Android utiliza un número denominado **API Level**. Por ejemplo: ^ Versión de Android ^ API Level ^ | Android 14 | 34 | | Android 15 | 35 | | Android 16 | 36 | | Android 17 | 37 | El nivel de API resulta especialmente importante durante el desarrollo, ya que determina qué funcionalidades de Android podemos utilizar. En los proyectos encontraremos principalmente tres valores dentro del fichero ''app/build.gradle.kts'' minSdk = 24 targetSdk = 36 compileSdk = 37 ^ Propiedad ^ Significado ^ | **minSdk** | Versión mínima de Android en la que puede instalarse la aplicación | | **targetSdk** | Versión de Android para la que se ha preparado y probado principalmente la aplicación | | **compileSdk** | Versión de las APIs que utiliza el compilador para construir la aplicación | Por ejemplo: minSdk = 24 targetSdk = 36 compileSdk = 37 significa que la aplicación: * puede instalarse desde API 24 * está preparada principalmente para el comportamiento de API 36 * puede utilizar las APIs disponibles durante la compilación con API 37 Que una aplicación utilice ''compileSdk = 37'' no significa que solamente pueda ejecutarse en dispositivos con API 37. La versión mínima en la que puede instalarse viene determinada por ''minSdk''. ==== Estructura básica de un proyecto Android ==== Cuando creamos un proyecto nuevo en Android Studio se genera automáticamente una estructura de directorios y archivos. Una versión simplificada podría ser: MiAplicacion | +-- app | | | +-- manifests | | | | | +-- AndroidManifest.xml | | | +-- kotlin | | | | | +-- MainActivity.kt | | | +-- res | | | +-- drawable | +-- layout | +-- mipmap | +-- values | +-- Gradle Scripts Algunos de sus elementos más importantes son: ^ Elemento ^ Función ^ | ''MainActivity.kt'' | Contiene inicialmente el código de la actividad principal | | ''AndroidManifest.xml'' | Define características y componentes importantes de la aplicación | | ''res'' | Contiene recursos como textos, imágenes, iconos o colores | | ''build.gradle.kts'' | Configuración de compilación del proyecto | | ''libs.versions.toml'' | Puede utilizarse para gestionar versiones de librerías y plugins | {{ :bloque1:android-project.png?400 |}} >Vista Android en el IDE ==== Gradle ==== {{ :bloque1:gradle-logo.png?200|}} Los proyectos Android utilizan **Gradle** como sistema de compilación. Gradle se encarga, entre otras tareas, de: * Compilar el código * Gestionar las dependencias * Procesar los recursos de la aplicación * Ejecutar pruebas * Generar los archivos instalables de la aplicación Por ejemplo, si nuestra aplicación necesita utilizar una determinada librería, Gradle puede descargarla automáticamente. En proyectos actuales es habitual encontrar dependencias definidas mediante un catálogo de versiones: implementation(libs.androidx.core.ktx) implementation(libs.androidx.activity.compose) Las versiones correspondientes pueden encontrarse en: gradle/libs.versions.toml ==== Ejecución de una aplicación ==== {{ :bloque1:android-emulator.png?300|}} Una aplicación Android necesita ejecutarse sobre un dispositivo Android. Tenemos principalmente dos posibilidades: * Emulador * Dispositivo físico Ambas serán configuradas desde el **Device Manager** de Android Studio. El **emulador** es capaz de simular diferentes dispositivos Android. Permite seleccionar características como: * Tamaño de pantalla * Resolución * Versión de Android * Cantidad de memoria * Tipo de dispositivo Su principal ventaja es que permite probar rápidamente una aplicación utilizando diferentes configuraciones. Sin embargo, el emulador **puede consumir una cantidad considerable de memoria y recursos del ordenador.** Por otro lado, si tenemos un **dispositivo físico Android** también podemos ejecutar directamente la aplicación. Para hacerlo será necesario activar las **Opciones de desarrollador** y la **Depuración USB** o **Depuración Wifi** en nuestro dispositivo. Después podremos conectar el dispositivo al ordenador ejecutar directamente la aplicación desde Android Studio. En equipos con recursos limitados puede ser recomendable utilizar dispositivos Android físicos en lugar del emulador. ===== Fundamentos de una aplicación Android ===== Una aplicación Android está formada por diferentes componentes que trabajan conjuntamente. Algunos se encargan de mostrar la interfaz, otros de gestionar datos, ejecutar tareas en segundo plano o comunicarse con otras aplicaciones. En las primeras aplicaciones nos centraremos principalmente en las Activities, los recursos y el archivo ''AndroidManifest.xml''. ==== Activity ==== Una Activity representa normalmente una pantalla de una aplicación Android. Por ejemplo, una aplicación podría tener: Pantalla de inicio -> MainActivity Pantalla de ajustes -> SettingsActivity Pantalla de detalle -> DetailActivity En un proyecto básico creado con Android Studio suele existir inicialmente una clase: MainActivity.kt En un proyecto con Jetpack Compose podemos encontrar algo similar a: class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // JetPackCompose setContent { MiAplicacion() } //XML Views setContentView(R.layout.activity_main) } } El método ''onCreate()'' se ejecuta cuando se crea la Activity. Mediante **setContent** indicamos la interfaz que se mostrará. ==== Ciclo de vida de una Activity ==== Una Activity pasa por diferentes estados durante su ejecución: [[https://developer.android.com/guide/components/activities/activity-lifecycle?hl=es-419|https:// developer.android.com]] Android dispone de diferentes métodos asociados a estos cambios: ^ Método ^ Momento aproximado ^ | ''onCreate()'' | Cuando se crea la Activity | | ''onStart()'' | Cuando comienza a ser visible | | ''onResume()'' | Cuando el usuario puede interactuar con ella | | ''onPause()'' | Cuando pierde el foco | | ''onStop()'' | Cuando deja de ser visible | | ''onDestroy()'' | Antes de ser destruida | No siempre será necesario utilizar todos estos métodos, pero es importante comprender que Android controla el ciclo de vida de las pantallas. {{ :bloque1:activity_lifecycle.png?600 |}} ==== AndroidManifest.xml ==== El archivo **AndroidManifest.xml** contiene información importante sobre la aplicación. Entre otras cosas puede indicar: * Las Activities disponibles * La Activity que se inicia al abrir la aplicación * Los permisos necesarios * Características generales de la aplicación Por ejemplo: En el **AndroidManifest.xml**, se declara cuál es la actividad principal mediante un filtro de intención ('''') con la acción **MAIN** y la categoría **LAUNCHER**. ==== Recursos ==== Android permite separar determinados elementos del código fuente mediante el sistema de recursos. Estos recursos se almacenan dentro del directorio **app/src/main/res** (res -> resources) Algunos directorios habituales son: ^ Directorio ^ Contenido ^ | ''drawable'' | Imágenes y recursos gráficos | | ''mipmap'' | Iconos de la aplicación | | ''values'' | Textos, colores, temas y otros valores | | ''layout'' | ficheros XML Views en casa de app basadas en ellas| Por ejemplo, los textos pueden almacenarse en: res/values/strings.xml Mi aplicación Hola Android Separar los textos del código facilita, entre otras cosas, la traducción de las aplicaciones a distintos idiomas. ==== Context ==== En Android, **Context** es un objeto que permite acceder a recursos y servicios de la aplicación y del sistema. Por ejemplo, para mostrar un mensaje, leer un texto de los recursos o abrir otra pantalla, Android necesita saber desde qué entorno se realiza la operación. Ese entorno se proporciona mediante un //Context//. Por ejemplo, puede utilizarse para: * Acceder a recursos * Iniciar otras Activities * Acceder a servicios del sistema * Mostrar determinados mensajes ^ Operación ^ Ejemplo ^ | Acceder a textos de recursos | ''context.getString(R.string.app_name)'' | | Mostrar un mensaje breve | ''Toast.makeText(context, ...)'' | | Acceder a archivos internos | ''context.filesDir'' | | Obtener servicios del sistema | Acceder al servicio de notificaciones, por ejemplo. | | Iniciar otra actividad | ''context.startActivity(intent)'' | El contexto se suele dividir en dos tipos: - Activity Context (Contexto de Actividad): * Está ligado al ciclo de vida de una pantalla o Activity específica. * Se utiliza para operaciones visuales, mostrar cuadros de diálogo (dialogs), inflar vistas o iniciar otra actividad. * Se suele referenciar mediante ''this'' o ''MyActivity.this''. - Application Context (Contexto de Aplicación): * Está ligado al ciclo de vida de toda la aplicación, desde que se abre hasta que se cierra. * Sobrevive a los cambios de configuración (como girar la pantalla). * Se obtiene llamando a ''getApplicationContext()''. * Se debe usar para operaciones globales que no dependen de una pantalla visual específica (por ejemplo, inicializar librerías, bases de datos o gestores de red. ==== Depuración y Logcat ==== Android Studio incluye **Logcat**, una herramienta que permite visualizar mensajes generados por la aplicación y por el sistema Android. Podemos escribir nuestros propios mensajes utilizando: Log.d("MI_APP", "Aplicación iniciada") Esto resulta muy útil para comprobar qué está ocurriendo durante la ejecución y localizar errores. import android.util.Log . . . Log.d("Alumnos", "Alumno guardado") // Depuración Log.i("Alumnos", "Aplicación iniciada") // Información Log.w("Alumnos", "Nombre vacío") // Advertencia Log.e("Alumnos", "Error al guardar") // Error En Android no debemos depender de ''println()'' como hacíamos en las aplicaciones de consola. Debemos utilizar Logcat. ===== Desarrollo de interfaces ===== Existen dos grandes formas de construir interfaces en Android: * **Views y XML**, sistema tradicional de interfaces Android * **Jetpack Compose**, sistema moderno de interfaces declarativas En Android Studio tenemos diferentes plantillas para crear un proyecto: {{ :bloque1:project-selection.png?600 |}} * **No Activity**: Crea la estructura del proyecto sin una pantalla inicial. Tú añades las actividades y la interfaz. Útil si quieres configurarlo todo manualmente. * **Empty Activity**: Crea una pantalla mínima con **Jetpack Compose**. Es la opción para empezar una interfaz escrita en Kotlin con funciones ''@Composable''. * **Gemini API Starter**: Crea una base para integrar IA de Gemini dentro de la aplicación. * **Navigation UI Activity**: Crea una aplicación con Compose y una estructura de navegación preparada para varias pantallas o secciones. * **Basic Views Activity**: Crea una base con Views y XML, con componentes como barra superior, botón flotante y navegación entre pantallas mediante fragments. * **Empty Views Activity**: Crea una actividad sencilla con diseño XML. Es la opción más clara para empezar con botones, campos de texto y eventos. * **Responsive Views Activity**: Crea una interfaz con Views y XML preparada para adaptar su distribución y navegación a distintos tamaños de pantalla. * **Game Activity (C++)**: Prepara una base para desarrollar juegos con C/C++, con soporte para gestionar aspectos como la entrada del usuario y el ciclo de vida. * **Native C++**: Prepara un proyecto Android con código C/C++. Útil para bibliotecas nativas, procesamiento intensivo o reutilización de código C++. * **Kotlin Multiplatform**: Prepara un proyecto para compartir código Kotlin entre plataformas, por ejemplo Android e iOS. Vamos a simplificar el proceso, y en nuestro caso usaremos: * **Empty Activity**: Para construir una app usando el kit **JetPack Compose** * **Empty Views Activity**: Para construir una app cuando queramos usar el **sistema de vistas XML** ==== Funciones Composable ==== Las funciones que forman parte del diseño de la interfaz se marcan con la anotación: @Composable Por ejemplo: @Composable fun Saludo() { Text("Hola Android") } Una función ''@Composable'' puede llamar a otras funciones ''@Composable'' para construir interfaces más complejas. Por ejemplo: @Composable fun PantallaPrincipal() { Column { Text("Bienvenido") Text("Mi primera aplicación") } } === Mostrar la interfaz === Desde la Activity podemos indicar qué interfaz queremos mostrar utilizando: setContent { PantallaPrincipal() } Un ejemplo completo sería: class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { PantallaPrincipal() } } } ==== XML Views==== **XML Views** es el sistema tradicional de desarrollo de interfaces. En este sistema se separa la definición de la interfaz (XML) del código Kotlin que controla su funcionamiento: * **XML**: define los componentes visuales, su posición y apariencia * **Kotlin**: gestiona los eventos, modifica los componentes y ejecuta la lógica de la aplicación Los archivos XML que definen las interfaces se encuentran normalmente en: ''app/src/main/res/layout/'' Por ejemplo, el archivo ''activity_main.xml'' puede contener: