Kotlin Multiplatform Project vs. Swift for Android

Teresa Wu
5 min readAug 28, 2019

The Background

At Tide one of our goals is to reduce development time together with complexity and costs when developing our iOS and Android app. One of the issues we face is the duplication of code across platforms. Therefore we have recently conducted an interesting R&D at Tide of multi-platform solutions for our mobile apps.

Generally when someone mentions the word multi-platform, the immediate thought is React Native or Flutter. Actually multi-platform applies to anything with an operating system: ⌚️📱 📺 🖥 🚗 . Our goal for this project is to find a solution, which will shorten our development time, reduce the gap between devices and bring seamless user experience to our clients. Before we dive in, let me brief you on our app structure:

Our Android and iOS projects are composed of horizontal modules, providing core functions, together with vertical modules, which contain the business logic and can be platform independent. Hence we have chosen to focus our research on those platform independent modules. Overall we have looked into three frameworks: Flutter, Kotlin Multiplatform Project and Swift for Android.

Flutter

Flutter is the cross-platform tool used to build native iOS and Android apps. The platform is highly focused on UI and can be tailored for various screen sizes. It was officially released in late 2018 and, with the recent release of SwiftUI and Android Jetpack Compose, declarative UI has become the go-to theme, and will continue to take over the market.

Flutter is the first framework we researched with, so we didn’t spend a huge amount of time digging into it, based on the nature of our platform and UI free modules. Moreover if we twist UI appearance on iOS, we also need to test on Android, which result in double QA time. Wouldn’t it be nice if somehow there was a solution that could help us reduce the duplication of code but still allowed the two apps to be independent?

Kotlin Multiplatform Project

Building a Kotlin Multiplatform Project is not directly import Android on iOS, even though it is very similar to a standard Android module, but you need to forget about Android 😄 and it’s context. The setting up process is simple, first we need to enable the environment in build.gradle as below:

kotlin {
targets {
fromPreset(presets.iosArm64, 'ios')
fromPreset(presets.android, 'android')
}
sourceSets {
commonMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-common:1.3.10"}
androidMain.dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1"}
iosMain.dependencies {
implementation "io.ktor:ktor-client-serialization-iosx64:1.2.0-rc"}
}
}

Target allows you to enable a building environment; it can be an emulator or an actual device. Dependencies can be shared, or platform specific. The multi-platform package also provides a few special keywords: actual and expect. Expect function provides an abstract definition of a method, where we delegate the implementation to the actual method from common lib to platform specific lib.

For iOS, the Kotlin module builds into a framework where you can import to your project.

For Android, it is as simple as adding one line in gradle file:

implementation project(“:shared”)

Once the code is imported into your native project, we can use it in the same way as any native function. Here is the result after compiling and running the code:

class MainActivity : Activity(){
override fun onCreate(savedInstanceState: Bundle?) {
textView.text = providePlatform()
}
} // Android
class ViewController: UIViewController {
override func viewDidLoad() {
label.text = PlatformProvider().providePlatform()
}
} // iOS

Swift for Android

Of course our journey didn’t end here, we continued to look for solutions to use Swift on Android. Running Swift code on Android != writing the entire application using Swift especially with UI. It works in a similar way to how an NDK project would work, to execute Swift functions through JNI.

The setup is not difficult; you need to download iOS development tools: xCode, libicu-dev and icu-devtools, and make sure you have enabled NDK environment on Android Studio. The next step is to create an Android project, with the additional swift package under app/main for your swift functions.

To use the Swift function, you need to first download a few libraries on the fly (but only once!). The external keyword works the same as expect in Kotlin, where it defines a foreign function to be executed by native application.

class MainActivity: Activity(){
external fun returnHello():String

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
loadLibrary()
textInfo.text = returnHello()
}

private fun loadLibrary (){
System.loadLibrary ("c++_shared")
System.loadLibrary ("icudata")
System.loadLibrary ("icui18n")
System.loadLibrary ("icuuc")
//swift
System.loadLibrary ("swiftCore")
System.loadLibrary ("swiftGlibc")
//own lib
System.loadLibrary ("hello")
}
}

At the end…

Flutter “Add-to-App” feature is still under development, meaning we can build a 100% Flutter project but not use it as lib. Swift for Android is quite heavy and it does not officially support Android yet. Our preference is steered towards Kotlin, a true multi-platform within native project. Having said that, Kotlin Multiplatform Project is still in an experimental phase, so we will continue to monitor and test with its new releases.

This article is a summary of our recent Tide Android Meetup (11.07.19)

--

--

Teresa Wu

Enthusiastic about cloud technology, data, clean code, Flutter, and Agile