Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Going Multiplatform with Your Android App (Andr...

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

Going Multiplatform with Your Android App (Android Makers 2026)

Existing Android apps are in a great position to expand into Kotlin Multiplatform: you might already be using patterns, libraries, and APIs that work on more platforms than just Android. With Compose Multiplatform, you can build an app with a fully shared Kotlin codebase, targeting iOS, desktop, and even the web!

In this talk, we’ll look at how you can migrate an existing Android app to multiplatform. As this can be a significant engineering effort for an existing, well-established app, we’ll also discuss how to plan and organize the required changes, and how to adopt KMP incrementally across your codebase without disrupting day-to-day development.

Avatar for Márton Braun

Márton Braun

April 10, 2026

More Decks by Márton Braun

Other Decks in Programming

Transcript

  1. 9

  2. Quick start • Ship almost immediately • Nontrivial moves •

    Fragmentation Retrofit RxJava Glide Dagger kapt Ktor Coroutines Coil Koin KSP 28
  3. Quick start • Ship almost immediately • Nontrivial moves •

    Fragmentation • Structural changes ? 29
  4. Migrate from Java to Kotlin • Docs on kotlinlang.org •

    J2K converter in Intell" IDEA • AI tools kotl.in/java-to-kotlin kotl.in/agent-skills 51
  5. kapt to KSP // Android dependencies { ksp("androidx.room3:room3-compiler:3.0.0-alpha01") } //

    Kotlin Multiplatform dependencies { add("kspAndroid","androidx.room3:room3-compiler:3.0.0-alpha01") add("kspIosArm64","androidx.room3:room3-compiler:3.0.0-alpha01") add("kspJvm","androidx.room3:room3-compiler:3.0.0-alpha01") add("kspJs","androidx.room3:room3-compiler:3.0.0-alpha01") add("kspWasmJs","androidx.room3:room3-compiler:3.0.0-alpha01") } 57
  6. Update ALL the dependencies • Gradle • Android Gradle Plugin

    • Kotlin • Jetpack Compose • … kotl.in/kmp-compat kotl.in/cmp-compat kotl.in/gradle/agp9 58
  7. A few common replacements JDK, Android APIs Kotlin standard library

    Moshi, Jackson, Gson kotlinx.serialization java.time kotlinx-datetime OkHttp Ktor Retrofit Ktorfit kotlinx-rpc (Preview) gRPC JUnit kotlin.test, kotest SQLite SQLDelight Dagger, Anvil Metro Glide Coil 66
  8. Already good to go Kotlin standard library kotlinx.serialization kotlinx-datetime Ktor

    Ktorfit kotlinx-rpc (Preview) kotlin.test, kotest SQLDelight Metro Coil Room Compose DataStore Koin Apollo GraphQL Arrow 67
  9. Handling the rest commonMain androidMain iosMain expect fun getPlatformId(): String

    actual fun getPlatformId(): String = !!... actual fun getPlatformId(): String = !!... 72
  10. Handling the rest commonMain androidMain iosMain interface Platform { !!...

    } fun init(platform: Platform) class AndroidPlatform Platform { !!... } class IosPlatform : Platform { !!... } : 73
  11. Handling the rest commonMain androidMain iosMain interface Platform { !!...

    } fun init(platform: Platform) class AndroidPlatform( context: Context ) Platform { !!... } class IosPlatform : Platform { !!... } : 74
  12. Setting up the KMP plugin (for Android) Change plugins Move

    dependencies Move sources Add AGP 9 opt-ins 86
  13. Setting up the KMP plugin (for Android) Set up Compose

    Multiplatform Configure previews Use multiplatform resources Change plugins Move dependencies Move sources Add AGP 9 opt-ins 87
  14. Setting up the KMP plugin android { namespace = "com.example.mylibrary"

    compileSdk = 36 defaultConfig { minSdk = 24 } compileOptions { sourceCompatibility = VERSION_11 targetCompatibility = VERSION_11 } buildFeatures { compose = true } } 89
  15. Setting up the KMP plugin kotlin { android { namespace

    = "com.example.mylibrary" compileSdk = 36 defaultConfig { minSdk = 24 } compileOptions { sourceCompatibility = VERSION_11 targetCompatibility = VERSION_11 } buildFeatures { compose = true } } } 90
  16. Setting up the KMP plugin kotlin { androidLibrary { namespace

    = "com.example.mylibrary" compileSdk = 36 defaultConfig { minSdk = 24 } compileOptions { sourceCompatibility = VERSION_11 targetCompatibility = VERSION_11 } buildFeatures { compose = true } } } 91
  17. Setting up the KMP plugin kotlin { android { namespace

    = "com.example.mylibrary" compileSdk = 36 defaultConfig { minSdk = 24 } compileOptions { sourceCompatibility = VERSION_11 targetCompatibility = VERSION_11 } buildFeatures { compose = true } } } 92
  18. Setting up the KMP plugin kotlin { android { namespace

    = "com.example.mylibrary" compileSdk = 36 defaultConfig { minSdk = 24 } compileOptions { sourceCompatibility = VERSION_11 targetCompatibility = VERSION_11 } buildFeatures { compose = true } } } 93
  19. Setting up the KMP plugin kotlin { android { namespace

    = "com.example.mylibrary" compileSdk = 36 minSdk = 24 compileOptions { sourceCompatibility = VERSION_11 targetCompatibility = VERSION_11 } buildFeatures { compose = true } } } 94
  20. Setting up the KMP plugin kotlin { android { namespace

    = "com.example.mylibrary" compileSdk = 36 minSdk = 24 compilerOptions { jvmTarget = JvmTarget.JVM_11 } buildFeatures { compose = true } } } 95
  21. Setting up the KMP plugin kotlin { android { namespace

    = "com.example.mylibrary" compileSdk = 36 minSdk = 24 compilerOptions { jvmTarget = JvmTarget.JVM_11 } } } 96
  22. Setting up the KMP plugin dependencies { implementation(libs.androidx.preference) } kotlin

    { sourceSets { androidMain.dependencies { } commonMain.dependencies { } } } implementation(libs.kotlinx.datetime) implementation(libs.ktor.client.core) implementation(libs.ktor.client.content.negotiation) 98
  23. Setting up the KMP plugin dependencies { implementation(libs.androidx.preference) } kotlin

    { sourceSets { androidMain.dependencies { } commonMain.dependencies { } } } implementation(libs.kotlinx.datetime) implementation(libs.ktor.client.core) implementation(libs.ktor.client.content.negotiation) 99
  24. Setting up the KMP plugin kotlin { sourceSets { androidMain.dependencies

    { implementation(libs.androidx.preference) } commonMain.dependencies { } } } implementation(libs.kotlinx.datetime) implementation(libs.ktor.client.core) implementation(libs.ktor.client.content.negotiation) 100
  25. Add AGP 9 opt-ins kotlin { android { androidResources.enable =

    true withHostTest { isIncludeAndroidResources = true } withDeviceTest { instrumentationRunner = "androidx.test.runner.AndroidJUnit } } } 102
  26. Setting up the CMP plugin - + + androidx-compose-foundation =

    { module = "androidx.compose.foundation:foundation" module = "org.jetbrains.compose.foundation:foundation", version.ref = "composeMultiplatform" } 105
  27. Setting up previews kotlin { sourceSets { commonMain.dependencies { implementation(libs.compose.ui.tooling.preview)

    } } } dependencies { androidRuntimeClasspath(libs.compose.ui.tooling) } 107
  28. Migrate to CMP resources 109 kotlin { android { androidResources.enable

    = true } sourceSets { commonMain.dependencies { implementation(libs.compose.components.resources) } } } // Optional customization compose.resources { nameOfResClass = "Res" packageOfResClass = "org.example.resources" }
  29. Add more platforms kotlin { android { ...} iosArm64() iosSimulatorArm64()

    jvm() wasmJs { browser() } js { browser() } } 112
  30. Add more platforms kotlin { android { ...} iosArm64() iosSimulatorArm64()

    jvm() wasmJs { browser() } js { browser() } } 113
  31. Add more platforms kotlin { android { ...} iosArm64() iosSimulatorArm64()

    jvm() wasmJs { browser() } js { browser() } } 114
  32. What’s next? kotl.in/kmp-team-intro • Project configurations • Introducing your team

    to KMP • Try Swift Export • Compose Hot Reload kotl.in/swift-export kotl.in/kmp-project-config kotl.in/compose-hot-reload 129