Cómo comenzar a usar Kotlin Multiplatform

1. Antes de comenzar

Requisitos previos

  • Saber cómo compilar apps con Jetpack Compose
  • Experiencia con Kotlin
  • Conocimientos básicos de la sintaxis de Swift

Requisitos

Qué aprenderás

  • Los conceptos básicos de Kotlin Multiplatform
  • Cómo compartir código entre plataformas
  • Cómo conectar el código compartido en iOS y Android

2. Prepárate

Para comenzar, sigue estos pasos:

  1. Clona el repositorio de GitHub:
$ git clone https://github.com/android/codelab-android-kmp.git

También tienes la opción de descargar el repositorio como archivo ZIP:

  1. En Android Studio, abre el proyecto get-started, que contiene las siguientes ramas:
  • main: Contiene el código de partida para este proyecto, en el que realizarás cambios para completar el codelab.
  • end: Contiene el código de la solución de este codelab.

Este codelab comienza con la rama main. Puedes seguir el codelab paso a paso a tu propio ritmo.

  1. Si quieres ver el código de la solución, ejecuta este comando:
$ git clone -b end https://github.com/android/codelab-android-kmp.git

También puedes descargar el código de la solución:

Instala Xcode

Para compilar y ejecutar la parte de iOS de este codelab, necesitas Xcode y un simulador de iOS:

  1. Instala Xcode desde App Store de Mac (para ello, necesitas una cuenta de Apple).
  2. Una vez que se instale, inicia Xcode.
  3. Aparecerá un diálogo que indicará qué componentes están integrados y cuáles debes descargar. c4aba94d795dabee.png
  4. Comprueba si tienes iOS 18.4 (o una versión posterior).
  5. Haz clic en Download & Install.
  6. Espera a que se instalen los componentes.

Este codelab se probó con Xcode 16.3. Si usas cualquier otra versión de Xcode y tienes problemas, te recomendamos que descargues la versión exacta que se menciona en este codelab.

La app de ejemplo

Esta base de código contiene una app para Android compilada con Jetpack Compose y una app para iOS compilada con SwiftUI. El proyecto de Android se encuentra en la carpeta androidApp/, mientras que el proyecto de iOS se encuentra en la carpeta iosApp/, que también contiene el KMPGetStartedCodelab.xcodeproj para ejecutar con Xcode.

3. Introducción a Kotlin Multiplatform

Kotlin Multiplatform (KMP) te permite escribir código una vez y compartirlo en varias plataformas de destino, como Android, iOS, la Web y computadoras de escritorio. Si aprovechas KMP, puedes minimizar la duplicación de código, mantener la coherencia y reducir significativamente el tiempo y el esfuerzo de desarrollo.

KMP no dicta cuánto ni qué partes de tu base de código debes compartir. Tú decides qué partes del código vale la pena compartir.

Decide qué compartir

El código compartido te permite mantener la coherencia y reducir la duplicación en todas las plataformas. Muchos equipos de desarrollo de apps para dispositivos móviles comienzan por compartir un conjunto discreto de lógica empresarial (p. ej., acceso a la base de datos, acceso a la red, etc.) y las pruebas asociadas, y, luego, comparten código adicional con el tiempo.

Muchas bibliotecas de Android Jetpack son compatibles con KMP. Las bibliotecas de Jetpack que se convirtieron en multiplataforma ofrecen varios niveles de compatibilidad según la plataforma de destino. Para obtener la lista completa de las bibliotecas y sus niveles de compatibilidad, consulta la documentación.

Por ejemplo, una de las bibliotecas compatibles, la biblioteca de bases de datos Room, es compatible con Android, iOS y computadoras de escritorio. Esto te permite portar la creación de la base de datos y su lógica relacionada a un módulo compartido de KMP común y, al mismo tiempo, conservar el otro código nativo en ambas plataformas.

Un posible paso después de migrar la base de datos sería compartir otra lógica de dominio. Luego, también puedes considerar usar la biblioteca multiplataforma ViewModel de Android Jetpack.

Cómo escribir código específico de la plataforma

Kotlin Multiplatform presenta nuevas técnicas para implementar funciones específicas de la plataforma.

Declaraciones esperadas y reales

La función del lenguaje Kotlin expect actual está diseñada para admitir la base de código multiplataforma de Kotlin con compatibilidad total con IDE.

Este enfoque es ideal cuando el comportamiento específico de la plataforma se puede encapsular en una sola función o clase. Es un mecanismo flexible y potente. Por ejemplo, una clase expect común puede tener contrapartes actual específicas de la plataforma con modificadores de visibilidad más abiertos, supertipos adicionales o diferentes tipos o modificadores de parámetros. Estos tipos de variantes no serían posibles con una API de interfaz estricta. Además, expect actual se resuelve de forma estática, lo que significa que la implementación específica de la plataforma se aplica de manera forzosa en el tiempo de compilación.

Interfaz e implementaciones en Kotlin

Si ambas plataformas deben seguir APIs similares, pero con implementaciones diferentes, puedes definir una interfaz en el código compartido como alternativa a las declaraciones esperadas y reales. Este enfoque te permite usar diferentes implementaciones de pruebas o cambiar a una implementación diferente durante el tiempo de ejecución.

Además, las interfaces no requieren conocimientos específicos de Kotlin, lo que hace que esta opción sea accesible para los desarrolladores que estén familiarizados con las interfaces en otros lenguajes.

Interfaz en código compartido común, implementación en código nativo (Android o Swift)

En algunos casos, debes escribir código que no está disponible en el código de KMP. En esta situación, puedes definir una interfaz en código compartido, implementarla para Android en Kotlin y proporcionar una contraparte de iOS en Swift. Por lo general, las implementaciones nativas se insertan en el código compartido, ya sea usando la inserción de dependencias o directamente. Esta estrategia permite una experiencia personalizada en cada plataforma y, al mismo tiempo, mantiene una interfaz común para el código compartido.

4. Abre el proyecto de Xcode desde Android Studio

Una vez que se instale Xcode, debes asegurarte de poder ejecutar la app para iOS.

Puedes abrir el proyecto para iOS directamente desde Android Studio.

  1. Cambia el panel Project para usar la vista de proyecto.4f1a2c2ad988334c.png
  2. Busca el archivo KmpGetStartedCodelab.xcodeproj en la carpeta [root]/iosApp/. 1357ffb58fe05180.png
  3. Haz clic con el botón derecho en el archivo y selecciona Open In y Open in Associated Application. Se abrirá la app para iOS en Xcode. f93dee415dfd40e9.png
  4. Para ejecutar el proyecto en Xcode, haz clic en ⌘+R o navega al menú Product y selecciona Run.

fff7f322c13ccdc0.png

5. Agrega un módulo de KMP

Para agregar compatibilidad con KMP a tu proyecto, primero crea un módulo shared para el código que se reutilizará en todas las plataformas (iOS y Android).

Android Studio proporciona una forma de agregar un módulo de Kotlin Multiplatform con su plantilla de módulo compartido de KMP.

Para crear el módulo de KMP, haz lo siguiente en Android Studio:

  1. Navega a File > New > New Module > Kotlin Multiplatform Shared Module.
  2. Cambia el paquete por com.example.kmp.shared.
  3. Haz clic en Finish 4ef605dcc1fe6301.png.
  4. Una vez que se complete la creación del módulo y Gradle termine de sincronizarse, aparecerá un nuevo módulo shared en el proyecto. Para ver la vista que se muestra a continuación, es posible que debas cambiar de la vista de Android a la vista de proyecto.

eb58eea4e534dab2.png

El módulo compartido que genera la plantilla de módulo compartido de KMP incluye algunas funciones y pruebas básicas de marcadores de posición. Estos marcadores de posición garantizan que el módulo se compile y ejecute correctamente desde el principio.

Importante: Ten en cuenta la diferencia entre la carpeta iosApp y la carpeta iosMain. La carpeta iosApp contiene el código independiente de la app para iOS, mientras que iosMain forma parte del módulo compartido de KMP que acabas de agregar. iosApp contiene código Swift, mientras que iosMain contiene código KMP específico de la plataforma de iOS.

Primero, debes vincular el nuevo módulo compartido como una dependencia en el módulo de Gradle :androidApp para permitir que la app use el código compartido:

  1. Abre el archivo androidApp/build.gradle.kts.
  2. Agrega la dependencia del módulo shared en el bloque de dependencias de la siguiente manera:
dependencies {
    ...
    implementation(projects.shared)
}
  1. Sincroniza el proyecto con los archivos de Gradle c4a6ca72cf444e6e.png.

Verifica el acceso de código al módulo shared

Para verificar que la app para Android pueda acceder al código del módulo shared, realizaremos una actualización simple de la app.

  1. En el proyecto KMPGetStartedCodelab, abre el archivo MainActivity en androidApp/src/main/java/com/example/kmp/getstarted/android/MainActivity.kt.
  2. Modifica el elemento componible Text de contenido para incluir la información de platform() en la cadena que se muestra.
Text(
  "Hello ${platform()}",
)
  1. Haz clic en ⌥(option)+return en el teclado y selecciona Import function 'platform' da301d17884eaef9.png.
  2. Compila y ejecuta la app en un dispositivo Android o en un emulador.

Esta actualización verifica si la app puede llamar a la función platform() desde el módulo shared, que debería mostrar "Android" cuando se ejecuta en la plataforma de Android.

9828afe63d7cd9da.png

6. Configura el módulo compartido en la app para iOS

Swift no puede usar módulos de Kotlin directamente como lo hacen las apps para Android y requiere que se produzca un framework binario compilado (paquete XCFramework). Un paquete XCFramework es un paquete binario que incluye los frameworks y las bibliotecas necesarios para compilar para varias plataformas de Apple.

Cómo se distribuye la biblioteca compartida

La nueva plantilla de módulo en Android Studio ya configuró el módulo compartido para producir un framework para cada una de las arquitecturas de iOS. Puedes encontrar el siguiente código en el archivo build.gradle.kts del módulo shared.

val xcfName = "sharedKit"

iosX64 {
  binaries.framework {
    baseName = xcfName
  }
}

iosArm64 {
  binaries.framework {
    baseName = xcfName
  }
}

iosSimulatorArm64 {
  binaries.framework {
    baseName = xcfName
  }
}

Este paso implica configurar Xcode para ejecutar una secuencia de comandos que genere el framework de Kotlin y llamar a la función platform() en la app para iOS.

Para consumir la biblioteca compartida, debes conectar el framework de Kotlin al proyecto de iOS con los siguientes pasos:

  1. Abre el proyecto de iOS (el directorio iosApp mencionado anteriormente) en Xcode y haz doble clic en el nombre del proyecto en el navegador de proyectos para abrir la configuración del proyecto 94047b06db4a3b6f.png.
  2. En la pestaña Build Phases de la configuración del proyecto, haz clic en + y selecciona New Run Script Phase. De esta manera, se agrega una nueva fase "Run script" después de todas las demás. d4907a9cb0a5ac6e.png
  3. Haz doble clic en el título Run Script para cambiarle el nombre. Cambia el nombre predeterminado Run Script a Compile Kotlin Framework para que se comprenda lo que hace esta fase.
  4. Despliega la fase de compilación y, en el campo de texto debajo de Shell, ingresa el código de la secuencia de comandos:
cd "$SRCROOT/.."
./gradlew :shared:embedAndSignAppleFrameworkForXcode

7b6a393e44ddbe60.png

  1. Arrastra la fase Compile Kotlin Framework antes de la fase Compile Sources. 27dbe2cf958c986f.png
  2. Para compilar el proyecto en Xcode, haz clic en ⌘+B o navega al menú Product y selecciona Build. Ten en cuenta que el progreso de la compilación se muestra en la parte superior de Xcode. bb0f9cb0f96d1f89.png

Si todo está bien configurado, el proyecto se compilará de forma correcta.

bb9b12d5f6ad0bac.png

Configurar la fase de compilación de la secuencia de comandos de ejecución de esta manera te permite compilar tu proyecto de iOS desde Xcode sin necesidad de cambiar a una herramienta diferente para compilar el módulo compartido.

Verifica el acceso de código al módulo shared

Para verificar que la app para iOS pueda acceder correctamente al código del módulo shared, realizarás la misma actualización sencilla que hiciste para la app para Android.

  1. En el proyecto de iOS, en Xcode, abre el archivo ContentView.swift en Sources/View/ContentView.swift.
  2. Agrega import sharedKit en la parte superior del archivo.
  3. Modifica la vista Text para incluir la información de Platform_iosKt.platform() en la cadena que se muestra con \(Platform_iosKt.platform()).

Este es el resultado final del archivo:

import SwiftUI
import sharedKit 

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            
            Text("Hello, \(Platform_iosKt.platform())!")
        }
        .padding()
    }
}
  1. Para ejecutar la app, haz clic en ⌘ + R o navega al menú Product, y haz clic en Run.

Esta actualización verifica si la app para iOS puede llamar a la función platform() desde el módulo compartido, que debería mostrar "iOS" cuando se ejecuta en la plataforma de iOS.

8024b5cc4bcd3f84.png

7. Agrega la herramienta Swift/Kotlin Interface Enhancer (SKIE)

De forma predeterminada, la interfaz nativa que produce Kotlin es un encabezado de Objective-C. Swift es directamente compatible con Objective-C, pero este último no incluye todas las funciones modernas de Swift ni Kotlin.

Esta también es la razón por la que, en el ejemplo anterior, no podías usar la llamada a platform() directamente en el código Swift. KMP no puede generar una función global porque Objective-C no admite funciones globales, solo funciones estáticas encapsuladas en una clase, por lo que debes agregar Platform_iosKt.

Para que la interfaz sea más compatible con Swift, puedes usar la herramienta Swift/Kotlin Interface Enhancer (SKIE) para mejorar la interfaz de Swift del módulo :shared.

Las características comunes de SKIE son las siguientes:

  • Mayor compatibilidad con los argumentos predeterminados
  • Mayor compatibilidad con jerarquías selladas (sealed class y sealed interface)
  • Mayor compatibilidad con enum class con control exhaustivo en las sentencias switch
  • Interoperabilidad entre Flow y AsyncSequence
  • Interoperabilidad entre suspend fun y async func
  1. Agrega el complemento de Gradle co.touchlab.skie al archivo libs.versions.toml:
[versions]
skie = "0.10.1"

[plugins]
skie = { id = "co.touchlab.skie", version.ref = "skie" }
  1. Agrega el complemento al archivo build.gradle.kts raíz.
plugins {
   ...
   alias(libs.plugins.skie) apply false
}
  1. Agrega el complemento al archivo build.gradle.kts del módulo :shared:
plugins {
   ...
   alias(libs.plugins.skie)
}
  1. Sincroniza el proyecto con Gradle

Quita la llamada a la función estática

Ahora, cuando vuelvas a compilar la app para iOS, es posible que no notes nada de inmediato, pero puedes quitar el prefijo Platform_iosKt y permitir que la función platform() actúe como una función global.

Text("Hello, KMP! \(platform())")

Esto funciona porque SKIE (entre otras funciones) aprovecha las Notas de la API de Swift, que agregan información sobre las APIs para consumirlas mejor desde el código Swift.

8. Felicitaciones

Felicitaciones. Agregaste el primer código de Kotlin Multiplatform compartido a proyectos de iOS y Android. Si bien este es solo un punto de partida mínimo, ahora puedes comenzar a descubrir funciones y casos de uso más avanzados para compartir código con KMP.

¿Qué sigue?

Aprende a usar Jetpack Room para compartir una capa de datos entre iOS y Android en el siguiente codelab.

Más información