Last Updated: 2020-30-11
En los últimos años, y con un entorno móvil en constante crecimiento, Android se ha posicionado como el sistema operativo dominante para dispositivos móviles, manteniendo aproximadamente el 70% de la cuota de mercado en los últimos 5 años. Android es un sistema basado en el kernel de Linux que está diseñado para smartphones, pero cuenta con variaciones para dispositivos wearables, tablets e incluso televisores.
Una de las principales características de Android es su código abierto y el control que brinda al dueño del dispositivo por medio de numerosas herramientas de desarrollador. Estos elementos potencian el alcance del desarrollo de aplicaciones móviles, ya que hacen posible que cualquiera pueda desarrollar. Además, existen varias herramientas y lenguajes que pueden utilizarse para crear aplicaciones de Android, entre los cuales principalmente se encuentran Java y Kotlin como lenguajes oficiales, y una variedad de herramientas para crear aplicaciones cross-platform o híbridas.
Kotlin es un lenguaje de programación de alto nivel y código abierto, el cual es estática y fuertemente tipado y se ejecuta sobre la Java Virtual Machine. Su sintaxis es distinta a la de Java, pero es bastante expresiva y fácil de comprender, ya que es un lenguaje funcional (con soporte a Programación Orientada a Objetos (POO)).
Kotlin es el primer lenguaje oficial para desarrollar aplicaciones en Android, las cuales inicialmente eran desarrolladas con Java únicamente. Por este motivo es muy común referenciar librerías core de Java (además de las APIs de Android) durante el desarrollo de aplicaciones para Android con Kotlin.
Al final de este tutorial usted tendrá:
Al desarrollar este tutorial aprenderá:
Para este tutorial, primero debe entender algunas características básicas del lenguaje Kotlin y luego, aplicar unos cambios en el código del proyecto.
Kotlin es el lenguaje de programación que oficialmente soporta el desarrollo de aplicaciones en Android. Como se mencionó anteriormente, este lenguaje puede compilar a un bytecode aceptado por la Java Virtual Machine (JVM), lo cual permite una interoperabilidad con el lenguaje Java. Si usted está familiarizado con el lenguaje Java, notará que existen varias similitudes.
En primer lugar, Kotlin es un lenguaje fuertemente tipado que soporta los tipos básicos de datos como Int, Double, Float, Long, Int, Byte, Char, Boolean
y otros tipos compuestos como String
, Array
, List
, MutableList
, entre otros; también soporta el uso de rangos. Kotlin además soporta estructuras de control básicas: condicionales if-else, ciclos While y Do-While
, pero también soporta estructuras no presentes en Java como When (alternativa del Switch-case
) y los ciclos For
a partir de rangos.
En segundo lugar, Kotlin no soporta conversiones internas entre tipos de datos. Esto hace que las variables no puedan tomar valores nulos a menos que se especifique de forma explícita que la variable puede aceptarlos. Paralelamente, Kotlin no maneja el concepto de "estático", sino que utiliza vals como constantes y companion objects como elementos estáticos de una clase. Kotlin soporta programación orientada a objetos con objetos y clases, los cuales funcionan como en cualquier otro lenguaje de programación, incluyendo clases internas, de datos, selladas, anidadas y anónimas.
En tercer lugar, Kotlin maneja modificadores de visibilidad como los de Java, incluyendo Private
, Protected
, Internal
y Public
para sus clases. En cuanto a encapsulación y organización de código, también funciona en paquetes al igual que Java, con la diferencia de que permite importar tanto clases como funciones entre diferentes archivos.
Existen muchas más particularidades y funcionalidades interesantes del lenguaje que usted irá descubriendo y que va a requerir para construir programas complejos y de alta calidad. Esta exploración, como en cualquier lenguaje de programación, se dará a medida que practique con él. Si desea consultar más recursos relacionados, puede comenzar por la guía ofrecida en Android Developers, disponible en el siguiente enlace: https://developer.android.com/kotlin/get-started?hl=es.
Para el caso de este tutorial, usted modificará una aplicación generada a partir de una plantilla vacía para incluir funcionalidad básica a partir de un botón, y en el proceso explorará la estructura de archivos de un proyecto típico de Android.
Abra Android Studio para crear un nuevo proyecto vacío en su sistema de archivos. Si no tiene un proyecto abierto, verá un menú como el de la imagen 1; en este caso, presione la opción "Start a new Android Studio project". En caso de tener un proyecto abierto, debe buscar la opción "New Project..." del menú de la parte superior del IDE en la pestaña "File", la cual se muestra en la imagen 2 a continuación:
Imagen 1. Menú de inicio de Android Studio
Imagen 2. Menú superior de Android Studio
En ambos casos, verá un panel como el de la imagen 3 a continuación para seleccionar una plantilla para su proyecto. Seleccione la plantilla denominada "Empty Activity", luego presione el botón next para llenar un formulario con el nombre de la aplicación, el nombre del package, la ubicación en el sistema local de archivos, el lenguaje de programación y los Software Development Kit (SDK) soportados.
Imagen 3. Panel de selección de plantillas para el nuevo proyecto
Note que Android Studio genera una estructura de archivos con archivos de Gradle para las dependencias, con los recursos XML para agregar multimedia y plantillas de componentes (en el directorio res
); el AndroidManifest para declarar la estructura de la aplicación y sus componentes; y cualquier otro archivo de código fuente relacionado a las activities elegidas como plantilla (en el directorio src/java
).
Para comprender el código fuente que construye la aplicación sencilla que creó, abra el archivo MainActivity.kt
. Las activities son clases fundamentales del desarrollo con Android que se asemejan a una ventana y que se reflejan como la interfaz gráfica que se renderiza en el dispositivo Android y permite la interacción con el usuario. Una aplicación puede contener múltiples activities y establecer una comunicación entre ellas por medio de envío de mensajes llamados Intents. No obstante, los Intents funcionan a nivel de sistema operativo y no de aplicación, por lo cual se puede establecer comunicaciones con Activities de cualquier paquete instalado en Android.
Una de las comunicaciones fundamentales por medio de Intents se establece desde la acción de lanzar una aplicación. Las aplicaciones de Android típicamente cuentan con un ícono launcher en el menú, el cual sirve para lanzar la aplicación en un menú principal. Este proceso ocurre gracias a la declaración establecida en el archivo AndroidManifest.xml
. Abra dicho archivo en el editor y note que la aplicación contiene su Activity, y que dicha Activity contiene un Intent Filter que funciona con la acción principal de la categoría Launcher.
La interfaz que se renderiza al momento de lanzar una Activity se define en el archivo respectivo del directorio de layout
entre los recursos (res
). Abra el archivo activity_main.xml
y note que Android Studio presenta su contenido de forma gráfica y no en código a pesar de que este también es un archivo con formato .xml. Los elementos gráficos que se definan en este archivo serán luego presentados en la interfaz gráfica de su dispositivo por medio del proceso de layout inflation, donde al ejecutarse la aplicación se crean objetos de tipo View en memoria de Kotlin y posteriormente son dibujados dinámicamente por el Activity. Android Studio también le permite ver el contenido "crudo" de este archivo en formato XML si hace clic en la opción Code. Note que existe un elemento TextView envuelto por un ConstraintLayout que permite definir las dimensiones y separación entre elementos por medio de sus atributos de etiqueta.
Las modificaciones dinámicas de la interfaz se hacen por medio del código fuente que se encuentra en el archivo MainActivity.kt
. Note que dicha clase se extiende de la clase AppCompatActivity, la cual se extiende a su vez de Activity y ofrece soporte para múltiples versiones del sistema operativo de Android. Las Activities funcionan con un ciclo de vida complejo que permite definir los comportamientos que la aplicación debería tomar en respuesta a ciertos eventos para ofrecer una experiencia adecuada con el sistema operativo. Este ciclo de vida se explica en detalle en el siguiente enlace de Android Developers y vale la pena que lo lea para tener claridad del funcionamiento de sus aplicaciones: https://developer.android.com/guide/components/activities/activity-lifecycle. En particular, su proyecto tiene una implementación sobreescrita del método OnCreate
, donde se establece el vínculo formal con el layout que se debe inflar en tiempo de ejecución.
Como se ha mencionado, la interfaz no cuenta con elementos que permitan una interacción con las acciones del usuario en la pantalla. Usted va a modificar la aplicación para que tenga una distribución de Layout más fácil de manejar, un botón para simular el lanzamiento de un dado y un elemento gráfico para mostrar el resultado del lanzamiento.
En este caso, se optará por utilizar una organización a partir de LinearLayout, dado que este funciona mejor que el ConstraintLayout incluido por defecto en el proyecto, pues no requiere definir medidas relativas que pueden afectar el resultado de la interfaz según el tipo de pantalla en que se renderice.
En primer lugar, elimine el código que se encuentra en el archivo activity_main.xml
y reemplácelo con las siguientes líneas:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".MainActivity" >
...
</LinearLayout>
El espacio con los tres puntos suspensivos será donde ubique los elementos gráficos posteriormente. Para tener una referencia, la aplicación que se desea desarrollar se debe ver como en la siguiente imagen:
Imagen 4. Vista en ejecución de la aplicación a desarrollar en este paso
En el proyecto inicial había un elemento TextView con el texto "Hello World!" escrito directamente en el código. Es importante que en sus aplicaciones de Android separe las cadenas de texto en el archivo strings.xml
del directorio values
en los recursos res
por motivos de mantenibilidad del código. Abra dicho archivo e ingrese los textos que utilizará la aplicación en el botón y el espacio superior. Su archivo debe contener el siguiente código:
<resources>
<string name="app_name">DiceRoller</string>
<string name="roll_label">Roll</string>
</resources>
Estos recursos de texto pueden ser luego referidos desde la aplicación con el manejador de recursos R.
Ahora, modifique nuevamente el archivo activity_main.xml
para incluir los elementos gráficos correspondientes haciendo uso de las cadenas de texto que acaba de definir. Los elementos gráficos mostrados en la imagen 4 son un TextView, como el que venía por defecto, y un botón, los cuales en código se ven de la siguiente forma:
<TextView
android:id="@+id/result_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="30sp"
android:text="Hello World!" />
<Button
android:id="@+id/roll_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/roll_label" />
Ubique este mismo código en el espacio de los tres puntos suspensivos que debe haber en su archivo. Con esto verá que se modificó visualmente el layout que está definiendo para MainActivity. Si detalla los atributos de cada etiqueta, verá que se define un identificador para cada una, que servirá para referirse al elemento desde el código, y además, se define un tamaño y un posicionamiento, junto con el texto que define al elemento.
Ahora, para agregar el comportamiento dinámico usted debe modificar el archivo MainActivity.kt
, cambiando el método OnCreate de su actividad para definir el listener del evento de clic sobre su botón. El comportamiento que debe tener la aplicación consiste en la generación de un número aleatorio entre 1 y 6, y en la renderización del número generado en el texto para que el usuario esté consciente del resultado. Para lograr esto, agregue las siguientes líneas de código al final del método OnCreate
de su Activity:
val rollButton: Button = findViewById(R.id.roll_button)
val resultText: TextView = findViewById(R.id.result_text)
rollButton.setOnClickListener {
val randomInt = (1..6).random()
resultText.text = randomInt.toString()
}
Este código define un par de variables no cambiantes que corresponden a los elementos gráficos del botón y el TextView, los cuales obtiene por medio del método findViewById()
. Este método recorre el árbol de recursos gráficos o Views buscando un elemento con el identificador dado por parámetro y retorna el elemento correspondiente. Este proceso puede requerir recursos computacionales, los cuales son limitados en un dispositivo móvil, por lo cual se recomienda reducir el uso de dicho método lo máximo que sea posible. Luego de esto, el código define un listener para el botón, donde se define que cada vez que se haga clic, se calcule un número aleatorio y se muestre en el texto del elemento TextView.
Verifique que la aplicación se comporta de la forma esperada ejecutando su aplicación nuevamente en el dispositivo que utilizó en un paso anterior. Al hacer clic en el botón debería ver el texto cambiar de "Roll" a un número entre 1 y 6.
Para seguir explorando las funcionalidades de Kotlin y los elementos de Android, ahora usted extenderá la aplicación modificando la forma en que se presenta el resultado a los usuarios. La aplicación desarrollada en esta parte del tutorial está basada en el tutorial de Android Developers disponible en el siguiente enlace: https://developer.android.com/codelabs/kotlin-android-training-images-compat/#0.
En vez del campo de texto, la aplicación tendrá un ImageView para mostrar un dado con el número correspondiente, de forma que utilizar la aplicación sea más agradable para el usuario. De esta forma, lo primero que debe hacer es incluir las imágenes en los assets del proyecto; para esto descargue el archivo .zip
con las imágenes desde el siguiente enlace: https://github.com/google-developer-training/android-kotlin-fundamentals-starter-apps/blob/master/DiceImages.zip. Una vez lo haya descargado, descomprima el archivo y copie su contenido en el directorio res/drawable
de su proyecto. Esto debe incluir 7 archivos en formato .xml
: una imagen para cada valor posible del dado y una imagen por defecto para cuando no se ha generado un número aleatorio. Si lo desea, abra alguno de estos archivos en el editor y verá que las imágenes se forman por medio de etiquetas XML y no directamente de un archivo multimedia.
Para agregar el View que va a mostrar las imágenes, abra nuevamente el archivo activity_main.xml
y reemplace la etiqueta relativa al TextView por el siguiente código:
<ImageView
android:id="@+id/dice_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/empty_dice" />
Note que los atributos de la etiqueta no varían más allá del identificador y el atributo src
, que determina de donde se va a tomar la imagen.
Ahora modifique el código que incluyó en el listener de su botón dentro del método OnCreate
del MainActivity para modificar el atributo src
del ImageView según el resultado obtenido. Para esto, primero elimine la variable que tenía relacionada al TextView y la línea de código donde modificaba su texto. Debe declarar una variable ahora relacionada al nuevo elemento gráfico y elegir la imagen a mostrar para cada uno de los posibles valores. Finalmente, el código de su clase MainActivity debe verse de la siguiente forma:
lateinit var diceImage: ImageView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rollButton: Button = findViewById(R.id.roll_button)
rollButton.setOnClickListener {
val randomInt = (1..6).random()
val drawableResource = when (randomInt) {
1 -> R.drawable.dice_1
2 -> R.drawable.dice_2
3 -> R.drawable.dice_3
4 -> R.drawable.dice_4
5 -> R.drawable.dice_5
else -> R.drawable.dice_6
}
diceImage.setImageResource(drawableResource)
}
diceImage = findViewById(R.id.dice_image)
}
En este caso se utilizó la estructura de control when, que es particular del lenguaje Kotlin. Note que esta funciona de la misma forma que un switch-case o un if-else, pero permite retornar un valor directamente hacia una variable, en este caso para elegir el recurso a renderizar como imagen. Así mismo, se utilizó una variable del tipo lateinit var
para optimizar las consultas con el método findViewById
, el cual debe elegir una imagen para mostrar en el ImageView.
Nuevamente, vuelva a ejecutar la aplicación en su dispositivo y compruebe el funcionamiento de la misma. Debería ver una pantalla como la siguiente:
Imagen 5. Vista en ejecución de la aplicación final desarrollada
¡Felicidades!
Al finalizar este tutorial, pudo familiarizarse con el entorno del desarrollo de aplicaciones en Android haciendo uso de las herramientas de Android Studio y el lenguaje de programación Kotlin.
Ahora podrá crear sus propios proyectos de Android, compilar y ejecutar aplicaciones y ahondar en las particularidades del desarrollo con Kotlin para crear aplicaciones modernas y cada vez más complejas.
Juan Sebastián Espitia Acero | Autor |
Norma Rocio Héndez Puerto | Revisora |
Mario Linares Vásquez | Revisor |