Kotlin Multiplatform Mobile : IOS and Android Apps with common native code

package com.kotlinnative.shared

expect fun getPlatformName(): String

class HelloWorld {
fun sayWelcome(): String = "Welcome, ${getPlatformName()}"
}
package com.kotlinnative.shared

import android.os.Build

actual fun getPlatformName(): String {
return "Android ${Build.VERSION.RELEASE}"
}
package com.kotlinnative.shared

import platform.UIKit.UIDevice

actual fun getPlatformName(): String {
return "${UIDevice.currentDevice.systemName()}
${
UIDevice.currentDevice.systemVersion()}"
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-multiplatform'

android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 15
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}

kotlin {
targets {
final def iOSTarget = System.getenv('SDK_NAME')?.startsWith('iphoneos') ? presets.iosArm64 : presets.iosX64

fromPreset(iOSTarget, 'ios'){
binaries {
framework('shared')
}
}

fromPreset(presets.android, 'android')
}

sourceSets {
// for common code
commonMain.dependencies {
api 'org.jetbrains.kotlin:kotlin-stdlib-common'

}

androidMain.dependencies {
api 'org.jetbrains.kotlin:kotlin-stdlib'
}

iosMain.dependencies {

}
}
}

configurations {
compileClasspath
}

task packForXCode(type: Sync) {
final File frameworkDir = new File(buildDir, "xcode-frameworks")
final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'
final def
framework = kotlin.targets.ios.binaries.getFramework("shared", mode)

inputs.property "mode", mode
dependsOn framework.linkTask

from { framework.outputFile.parentFile }
into frameworkDir

doLast {
new File(frameworkDir, 'gradlew').with {
text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n"
setExecutable(true)
}
}
}
tasks.build.dependsOn packForXCode
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.kotlinnative.shared"
/>
include ':app', ':shared'
rootProject.name='KotlinNativeExample'
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
... packagingOptions {
exclude 'META-INF/*.kotlin_module'
}

}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':shared')
...
}
package com.kotlinnative.example

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.kotlinnative.shared.HelloWorld
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
displayText.text = HelloWorld().sayWelcome()
}
}
./gradlew :shared:build
cd "$SRCROOT/../../shared/build/xcode-frameworks"
./gradlew :shared:build -PXCODE_CONFIGURATION=${CONFIGURATION}
$(SRCROOT)/../../shared/build/xcode-frameworks

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store