Cross-Platform Development with Kotlin Multiplatform

Lift off

Kotlin was created by JetBrains and later adopted by Google in 2011, but it wasn’t until 2016 that version 1.0 was released. Kotlin emerged to address the limitations of Java, specifically in the Android ecosystem, where developers were stuck with Java 8 due to legal constraints. Kotlin offered a modern alternative, retaining the JVM-based infrastructure while introducing new features to enhance productivity and safety.

Why Kotlin Multiplatform?

The desire to share logic across platforms is not new, but Kotlin Multiplatform addresses this need more effectively than previous approaches. Early attempts, such as using С++ modules compiled for specific platforms, had their limitations. However, Kotlin Multiplatform allows developers to write shared code, which can then be implemented for each target platform.

Key Benefits:

  • Efficiency: Share business logic across platforms and reduce code duplication.
  • Flexibility: Easily integrate with existing native codebases.
  • Scalability: Supports multiple platforms, including Android, iOS, and Web.

💡Read about other mobile development technologies: Navigating the Mobile Development Landscape

Core Concepts of Kotlin Multiplatform

At the heart of Kotlin Multiplatform is the ability to share code and manage platform-specific implementations seamlessly. Here’s a breakdown of its core concepts:

Shared Code

Write common code using Kotlin, which is shared across different platforms.

  • iOS: Framework (Static or Dynamic) or CocoaPods
  • Android: AAR (Android Archive)
  • JVM (Server/Desktop): JAR (Java Archive)
  • JavaScript: npm package or Plain JS files
  • Native Desktop: Static Library (.a, .lib) or Dynamic Library (.so, .dll, .dylib) or Exectutable Binary
Kotlin Multiplatform full hierarchy

Platform-Specific Code

Kotlin Multiplatform allows interaction with native APIs, which is crucial for accessing platform-specific functionalities.

  • expect and actual mechanism
  • androidMain & iosMain (Kotlin)

And platform-native code:

  • androidMain (Kotlin or Java) & iosApp (Swift or Obj-C).
Kotlin Multiplatform Project Structure

As you can see, the Kotlin version with Cinterop is rather a reflection of Objective-C API than Swift.

👉 Kotlin Multiplatform doesn’t force you to share everything. You can choose what to share and what to keep native.

Real-World Example: Building an Audio Player (with platform-specific code)

In my Kotlin Multiplatform talk, I talked about an example of building a simple audio player application with platform-specific code. In short, it looks like this:

  1. Define an interface in commonMain
  2. Create implementations in androidMain and iosMain
    1. Kotlin Native & cinterop – generated bindings. Potentially, if there’s a 3rd party library or you have a native implementation of an iOS app, you can generate bindings and use them in platform-specific module the same way.
    2. Handle pointers, memory allocation and memory scopes.
    3. ExperimentalForeignApi
  3. Provide exact class with dependency injection (DI)

Example #2: Image Converter (with platform-native code)

  1. Define an interface in commonMain
  2. Create implementations natively in each platform androidMain and iosApp
    1. might require custom data conversions, for instance between Kotlin’s ByteArray and Objective-C’s NSData
  3. Provide exact class with DI
    1. with a bit more cumbersome setup

Compose Multiplatform for shared UI

Compose Multiplatform, also by JetBrains, based on Jetpack Compose to offer a UI framework for Android similar to SwiftUI and React concept.

  • Supports the same targets as Kotlin Multiplatform.
  • Single codebase for Android and iOS apps.
  • On iOS and non-Android platforms, it doesn’t leverage native UI components but draws directly on the canvas (like Flutter), which is a sad part for me.

💡 Starting a new Android app? Consider Compose Multiplatform for easier future expansion to other platforms.

Challenges and Considerations

While powerful, Kotlin Multiplatform has its challenges:

  • Some components are still in alpha, beta, or experimental stages.
  • The project structure can feel overwhelming at first.
  • Gradle can be complicated at first (and sometimes “at second” too).
  • Compose Multiplatform still lacks some solutions available in React Native or Flutter (e.g., keyboard avoidance on iOS).

✅ The good news: Google officially supports Kotlin Multiplatform and many well-built libraries are being ported.

✅ If something is missing, implementing it can be easier than in React Native or Flutter.

Conclusion

Kotlin Multiplatform stands out because it doesn’t force you to share everything. Suppose you have two native applications and want to migrate to Kotlin Multiplatform. In that case, you can start by placing your Android and iOS apps in separate directories, tweak the build phase slightly, and it will assemble just fine without shared code.

From there, you can gradually move logic to shared modules. If shared code becomes problematic, you can reverse the process and use native components without getting stuck, unlike React Native or Flutter.

For cross-platform development with flexibility, reduced duplication, and modern tooling, Kotlin Multiplatform offers a solid approach. While there are challenges (as with any technology), the benefits are compelling.

Pavel Vashkel

Pavel Vashkel

Lead Mobile Developer

From our blog

Stay up to date

Check out our newsletter

© 2024 Red Panda Technology (dba datarockets). All Rights Reserved.