· 4 min read Posted by Gustavo Fão Valvassori

Jetpack Compose to Compose Multiplatform: Transition Guide

As an Android developer, you probably already use Jetpack Compose to build UI. But did you know that with a few changes you can also build your application for other platforms, such as iOS, macOS, and the Web?
Sigmund - https://unsplash.com/photos/text-_dJCBtdUu74
Credit: Sigmund - https://unsplash.com/photos/text-_dJCBtdUu74

Jetpack Compose is the current standard tool for building UI in Android applications. It’s a declarative UI toolkit that allows you to build your UI using Kotlin code. Like many other Android libraries, it is open-source and maintained by Google.

Just a couple of days after the first stable release of Jetpack Compose, JetBrains announced that they are working on a fork of Compose that is compatible with Kotlin Multiplatform. This means that you can use the same codebase to build your UI for Android, iOS, JVM, and the Web.

As you can imagine, this compilation change is not automatic, as the JetBrains version is a fork of the original Compose library. But in two steps, you can make your project compatible with multiple platforms.

Step 1: Migrating your module to KMP

The first step to use Compose Multiplatform, is to make your module compatible with Kotlin Multiplatform. This means that you need to include the kotlin-multiplatform plugin in your build.gradle.kts file and configure the targets. You can start with the Android target and add the other platforms later.

plugins {
    id("com.android.application")
    // or
    id("com.android.library")

    // Replace `kotlin("android")` with:
    kotlin("multiplatform")
}

// Declare android target
kotlin {
    androidTarget()
}

android {
    // Your android app configuration
}

Now you need to create the commonMain and the androidMain source sets, and move your code to them. The code that does not depend on Java or Android APIs can be directly moved to commonMain. The code that depends on Android APIs should be moved to androidMain.

Last but not least, if your android configuration has a compileOptions block to define the Java version, you should also update the androidTarget declaration to use the same Java version.

kotlin {
    androidTarget {
        compilations.all {
            kotlinOptions {
                jvmTarget = "1.8"
            }
        }
    }
}

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

Without it, you will get a compilation error similar to the one below:

Inconsistent JVM-target compatibility detected for tasks ‘compileDebugJavaWithJavac’ (1.8) and ‘compileDebugKotlinAndroid’ (17).

Step 2: Migration to Compose Multiplatform

Jetpack Compose is enabled by a “build feature” in your project. If you already have it set up, you probably already have these few lines in your project build.gradle.kts file:

android {
    // Enabling Compose
    buildFeatures {
        compose = true
    }

    // Defining Compose version
    composeOptions {
        kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get()
    }
}

Unlike Jetpack, the Compose Multiplatform is enabled through a plugin. So the first step to use it, is declaring the plugin on you project root build.gradle.kts file and removing Jetpack Compose configuration:

plugins {
    kotlin("multiplatform") version "1.9.23" apply false 
    id("org.jetbrains.compose") version "1.6.1" apply false
}

And in your module build.gradle.kts:

plugins {
    kotlin("multiplatform")
    id("org.jetbrains.compose")
}

After that, all you need to do is include the Compose libraries in the common main source sets. To help you with this challenge, the plugin provides a helper compose variable with core Compose Multiplatform modules.

kotlin {
    androidTarget {
        compilations.all {
            kotlinOptions {
                jvmTarget = "1.8"
            }
        }
    }

    sourceSets {
        commonMain.dependencies {
            implementation(compose.runtime)
            implementation(compose.foundation)
            implementation(compose.ui)
            implementation(compose.animation)
        }
    }
}

Now your project is Multiplatform Ready and using Compose Multiplatform. If you want to build for other targets, all you need to do is add them to your build.gradle.kts file.

Bonus: Compose Resources

The 1.6.0 release of Compose Multiplatform has included support for resources. This means that you can now configure and use strings, images and other resources types in your common code.

To enable it, you must include the resources library to you common module, and create a new resource dir called composeResources.

kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation(compose.components.resources)
        }
    }
}

The current implementation is very similar to Android Resources, so it should be easy to migrate your current resources to the new format. Some of them can just be copied and paste to the common resource dir and it will work. Here is a list of supported resource types:

  • Strings/String Array
  • Drawable/Vector Images
  • Fonts
  • Files (similar to Android Raw resources)

Some types are not supported yet, but they may be added in future releases. Here is a list of unsupported resource types:

  • Integers
  • Booleans
  • Colors
  • Plurals
  • Dimensions

To access it on your Kotlin code, all you need to do is Replace the R class with the new Res class. If you don’t see the Res class in your code, can trigger the generateComposeResClass task.

Conclusion

Migrating projects from Jetpack Compose to Compose Multiplatform is a simple process that can be done in a few steps. The process will be even easier if your code has fewer couplings with Android-only APIs or platform libraries. And with the new resources support, most Android resources can be migrated to Compose Multiplatform without any changes.

If you need some examples on how this migration can be done, you can check the last commits from the Compose Animations project that was recently migrated to Compose Multiplatform.