Kotlin code sharing among platforms

When you try to deal with the across platform codes, you need to solve 2 things, one is what to share, the other is the architecture of how to share the code.

Different languages have different techniques to the second problem, but in Kotlin, you can use multiplatform projects to share the code.  With kotlin native, you can even expand the support to natively to iOS and Android.

1. Goals

  • share code among JVM, JS, iOS, and Android.
  • enable the use of XCode and Android Studio to edit the native app, while using another IDE to edit the sharing code part. (But you can use Android studio for editing the KN code as well because they use the same language and the setup will be ready.)
    • I saw some setups. They use root folder as a whole gradle project which will affect the Android project structure been displayed in the android studio because it will add some noise there.
  • share more code between iOS and Android.
    • The main hurdle is the platform-specific API. We can make them as `interface` and still shared the logic around them. But here we will use `kotlin multi-platform` approach to make the code more elegant.
    • Think of an API like this `UserService.getAllorNull()`, then your native side just need to bind the result to the UI. Even though the `HTTP` call is different across platform. But all the exception handling and data processing around the http call are the same and could be shared.
  • a clean structure where everything related should reside together.
    • I mean for the gradle phase as well. Such that, `android` folder is only for Android, `ios` folder is only for iOS. The root folder is for all projects. And the gradle settings for `KN-android` should be in the `android` folder as well as the `iOS` side.
  • enable testing the Kotlin native code as well.
    • It’s native project so anything native can be tested via the strategy on that platform. But what about kotlin native part, what about the `common` code? What about the kotlin native platform specific code for `android` and `ios`? Yes, we have that part covered as well here in the example.

1.1 What if there is no need to care about the platform-specific implementation?

If all you need is the API from kotlin-stdlib, and no platform specific code, then you don’t need to use this setup. You can simply remove the platform folder. And let the common just output an iOS framework for the XCode project to consume. For Android, embed the source code in Android studio to make it as dependency, then it’s fine. Same case for JVM and JS as well. And the setup for JVM and JS is as easy as following the official document.

2. Folder structure

  • ios: XCode project
  • android: Android Studio project
  • common: Common code that is about to share across platforms without any change.
  • platforms:
    • ios: platform specific API for iOS
    • js: platform specific API for js
    • jvm: a dependency for both `android app` and `jvmApp`

Very easy to understand. One interesting thing here is in the platforms folder, besides the common folder. What’s the platforms/android and platforms/ios folder for? Well, they are for platform-specific API.

2.1 How to consume the lib

  • JVM and JS just as easy as including the lib as the dependencies in build.gradle.
  • Android related code will be shared via simply including the according module in the android project.
  • iOS related code will be shared as an iOS framework because Kotlin native will generate that. We will then add it to the XCode building phase. You can see more details on my another [blog](http://www.albertgao.xyz/2018/01/14/how-to-create-kotlin-native-ios-project/).

2.2 Background knowledge for Kotlin multi-platform project

Let’s say you want to have an HTTP kotlin class where you can do the normal GET, POST thing, but the HTTP implementation is different across platforms. If you use the old school interface way, you need to declare an IHTTP interface, then implement it twice in android and ios. Then inject it at runtime to make it work.

But via using the Kotlin multi-platform project, you don’t need to inject, the compiler will only pick up the piece of codes depends on your building target. If you build for Android, it will only grab the Android implementation.

It currently works for jvm, js and kotlin native, oh, that’s a nearly-all-platform code sharing tech right? 😀

And it’s very simple.

You need to expect an implementation of your common code.

expect class Platform {
    fun get():String

Then implement the actual code in somewhere else, like android.

actual class Platform {
    actual fun get():String {

Or in ios:

actual class Platform {
    actual fun get():String {

Then with some proper setup in gradle, it will work flawlessly.

2.3 How to code the `platforms-ios`

Oh well, you may think that old school interface may better in terms of iOS because you need to implement the iOS API specific thing in swift or obj-c then pass it back to kotlin native. But that is not true. Because there is a 1-to-1 API match in kotlin native such that you can implement the iOS specific API in kotlin as well. And it has the same signature which means you can reuse all the existing knowledge. And kotlin and swift are very similar. And from v6, the building phase will link some of the iOS API (you need to build the others) for you if you are on a Mac.
Which means in an ideal world, your swift side just needs to care about the UI part while all other logic will be handled in the Kotlin native side, shared across platform and tested well.

3. About the example

All the code for setup can be found in this repo.

  • `Sample` class is for code that is sharing across platforms (Which means you have to use API from `kotlin-stdlib-common`).
  • `Platform` class is a class which has been implemented twice for different platforms for showing the platform API case.
  • Open `android` folder from the root in Android Studio, run the app, it will show a string from the `:shared-android` project.
  • Open `ios` folder from the root in XCode, run the app, it will show a string from the `:platforms-ios` project.

In fact, all the apps (jvmApp, jsApp, android and iOS) retrieve the string by invoking the method from the Sample class. And the Sample class invokes the method from Platform class to get the string. When you build an iOS framework, the KN compiler will use :platforms-ios to build along with :common. And when you consume it in android project, the setup will use :platforms-android along with :common. No injection, no affection on the code structure, just that simple. Thanks to the Multi-platform project setup from kotlin.
It is a perfect example of showing how to share the code when you have to deal with the platform API.

Hope it helps. Thanks.


Waterfall or Agile?

This page describes both Waterfall and Agile software development philosophies. In reality developments are not 100% waterfall or agile, but a blend of the two.

This is a ‘back to basics’ look at the two philosophies. Separate pages will consider the implications, and necessary modifications, when each is applied to different bespoke software or product software projects.


  • Why yet another page?
  • waterfall: modelled on construction projects
    • We have an agreed design and the process to build this is well known.
  • agile: modelled on engineering design projects
    • no one has ever done this before
  • hybrids?
  • Budgeting
  • The Team

Why yet another page?

In short, to try to separate the ‘religion’ from this topic, and to step back from the ‘bespoke only’ or ‘product software only’ perspective in almost every other page on this topic I have found.

An example of the ‘religion’ attitude is an article here which suggests Apple computer has poor software quality because they use ‘waterfall’ rather than ‘agile’.  It is almost certain that Apple would use a methodology encapsulating some of both ‘agile’ and ‘waterfall’,  but the implication is that label ‘waterfall’ is itself sacrilege.  While a company (and even perhaps Apple) may not embrace sound software methodology, evaluation is more complex than simply a label.

The other issue is to take each concept, and envisage only a chosen adaptation for the authors field of software.  Not only are bespoke and product software almost polar opposites, but even within each category there are factors that affect ideal methodology.  So most pages compare only for a specific environment, which is great if all your projects match that description, but less helpful for those with different or varied projects.

Waterfall:  Modelled on constructions projects.

waterfallsThe process of building something (i.e. a building) has been practiced and refined over centuries.  The waterfall approach is simply taking this construction model, and applying the model to the building of software.  Using a gantt chart,  the steps look more like a cascade of waterfalls.  But if you view a cascade from the front (see pic) then you have the appearance of water falling from step to step.  The waterfall is from step to step, not all at once.

From xbsoftware.com

The principle of waterfall is that each step is completed before the next begins. A complete understanding of requirements should be in place before design starts.  ‘Building” or development, should not commence without a completed design. Once built, tests verify the building meets the design.  These are the same steps that have been proven to work for construction projects over centuries.

Agile: Modelled on engineering design.

While waterfall considers a software project as similar to a construction project, agile effectively considers the entire software project, as being an engineering design phase.

With engineering design, you have a problem, and the challenge is to find a solution.

If it is know that some existing design can be modified to provide a solution, then there is no engineering design required.

An example from the tangible world is the design phase for mass produced products. You have a team of designers who engineer a design, but although you may have a fixed budget and time frame, it is only at the end of the design phase that you know what the final product will look like.

The principles of agile can be considered be:

  • what is being created is new and innovative
  • new ideas will need prototyping and revision
  • the best solution is not always clear at the outset
  • actual product requirements may not even be clear until the product is trialled

The process of agile software development can be considered as:

  • define initial set of requirements
  • build an as simple as possible prototype as quickly as possible
  • now repeat the following steps until satisfied:
    • analyse what how the prototype could be improved, and add those improvements to requirements
    • analyse steps that can be made within 1-2 weeks to meet more requirements and perform those steps

Note: this is representing the agile philosophy itself. Any actual implementation of agile will also depend on some other choices as to how agile will be implemented.

Consider a car manufacturer who produces a new model of a certain car every year.  The design team, with an allocated number of people and resources, is given a fixed time to come up with next years design.  Agile development is similar to this process.

Hybrids? Solutions using a combination.

Waterfall: We have a specification and the process to build this is well known.

With construction projects, you could be building an exact replica in an effectively identical site, but surely there will be something new?  In fact, the more daring the building, the more often that some part of the project will actually encompass an engineering design project, even with prototypes!  The fact that almost every waterfall project encounters some steps which better fit the agile pattern, is the reason so many waterfall projects suffer time and cost blowouts.

Agile: No one has ever done this before.

But Surely someone has done part of it before?  Won’t there are least be construction projects to build the prototypes?

The reality is that both agile and waterfall can start to approach a series of short waterfalls placed back to back. Each just approaches from the opposite side.

A very short waterfall stage loses many of the characteristics of waterfall, and a long build of a single prototype becomes more waterfall.  In the end no project is ‘pure’ and all have elements of both.  Software is always doing something new, but just how new?

The more new, the more no one has genuinely done anything like this before, the greater the need for an agile mindset.  The more ‘just like a previous one but with these straight forward but time consuming changes‘, the more a waterfall mindset may work.


No one can predict the exact cost of an exactly specified system containing elements that no one has ever done before.

As waterfall is based on the construction model, the budgeting process it quite like getting quotes having a house built to match the plans you have had drawn up.  You can have faith you will get something that matches the plans, even if it may be a little late and the real problems only occur if you realise during construction that result will not match what you actually need.

Agile is more like working with the architect.  You may have a fixed quote but you have to commit blindly without knowing in advance if you will like the result.  With agile you can control the budget, but at the expense of accepting what is produced within that budget.

The result is that  many projects are forced into a waterfall mindset from the budgeting phase, and  can only live with an agile mindset for the limited spend of the design phase.

The Team

Just as waterfall breaks a project into steps, it separates the roles needed for those steps.  Design people are expensive, but during ‘construction’ you may only need labourers who cost less.  Similarly a waterfall methodology separates project managers, annalists, and programmers. Programmers who just program become lowest cost resource, and can be more easily outsourced and managed by project managers.

Agile requires the whole team act like engineers.  As the work is always different even the construction has less guidance and more decisions on the fly by the ‘engineer’.  The result is more costly resources and a much flatter team structure.  The team project manages themselves using scrum or other methodology, but this requires additional skills.

Evaluation of Kotlin Native for mobile: January 2018

We have been looking at Kotlin Native (KN) as a viable solution for mobile development, and as a competitive solution to those like Xamarin – or to completely separate developments for iOS and Android. To be a viable mobile solution in general requires Kotlin Native(KN)  to be workable for iOS as first announced

On my inspection, I believe that KN makes sense, and very good sense in the longer term for mobile development, but Kotlin Native is still far from production ready for the following reasons:

  1. This is the most important reason, all the platform specific API hasn’t been published as maven artifacts, which mean you can’t add them as project dependencies in gradle which leads to many other problems like:
    1. syntax highlight
    2. autosuggestions
    3. your code related to KN is fragile as they said:
      • `warning: IMPORTANT: the library format is unstable now. It can change with any new git commit without warning!`
  2. No documentation for API. And without any support from IDE. It will greatly slow down the job.
  3. Multiplatform project needs to support KN in order to get benefits in terms of architecture. You can still just use the old school way (by declaring `interface`). But this should be ready in 0.6 (My feeling according to slack, still not sure.)
  4. In response to a question on the Kotlin Native slack channel “Any ETA on beta/1.0 version?Nikolay Igotti replied( 25/December/2017) :Not yet, however, being v0.x is mostly an internal thing, in general both compiler and runtime are pretty well tested and known to work on rather complex codebases, such as Video Player: https://github.com/JetBrains/kotlin-native/tree/master/samples/videoplayer

  5. CLion: The benefit of using CLion seems more for the KN dev team, and for projects integrating with the C family, which is not the case for iOS projects.  When the developers deal with the cross-platform setup, they need to dig into the LLVM layer in order to build the bridge. CLion is the only IDE in JB family which supports Kotlin Native at this time, which is problematic for projects looking to go multiplatform with JVM or JS, and for iOS projects which combine with Swift and Xcode.  There is no announced plan for supporting the other JB IDEs. Further, from the project leader’s talk in slack in late January 2018 on support for IDEA: `this is not yet completely decided, but CLion is currently the only option`. And you know, CLion doesn’t support gradle, and they use gradle to build…..    The other possibility is Koltin support in AppCode, which there are suggestions may be coming and could be the best solution.
    • So we have some difficult situation here, which is:
      • CLion doesn’t support gradle. And the issue is there since 2014.
      • The multiplatform project hasn’t support KN yet. But this one is easy and difficult.
        • It’s easy because once the maven dependencies is there, the support will be nearly there. Or we could build the whole thing by `gradle` ourseleves.
        • It’s hard because as I said… The KN libs hasn’t been published as maven dependencies yet.
      • And from the talk of slack, it seems that the team holds the releasing mainly because the KN lib has a completely different format, even for the file extention, it’s called `.klib` now. So, uploading it to maven or JCenter seems not ideal. I assume JB might end up with building a new repository just KN libs.

And when there are some problems on both IDEA and CLion, a potential answer from JetBrains might be a new IDE just for Kotlin native. The following video maybe a provenance for this:

https://www.youtube.com/watch?v=QOIn8Uh3lkE at 6:20 Andrey Breslav said (in Russian) they started development of new commercial product for cross-mobile development, Android and iOS.

But it seems that Appcode with KN support should land first according to the slack chat.

The team leader has said in the slack channel that they will ask for dogfooding once it’s ready. 🙂

If app developers wish to only build using the kotlin-std-lib, and inject the platform-specific API at runtime, it’s doable. But then your codebase will be a mess because you need to build the bridge by yourself  as the kotlin type has been converted to some special interface type, which you need to implement in the swift side as well…. all to cope with an interim solution which will be deprecated in a future version release…

So, 3 things are crucial for using KN in production:

  1. Decent IDE support such that we could inspect the APIs signature(No matter CLion or IDEA or AppCode, this is essential)
  2. Multiplatform project support KN
  3. Able to create an KN project without depending on the KN repo…. Which means they need to publish their platform lib in order to enable us to add them as the project dependencies in gradle. Otherwise, a single build on KN repo takes 2 hours…..on my 2017 i7 15″ retina MacBook pro.

All of the 3 are all needed for writing KN related app.

But I will keep an eye on KN, because I think as I dig into more, I think KN starts to make more sense.

  1. You can really share your logic. The most awesome part is that you can invoke platform-specific API from kotlin side which means you don’t need to deal with the communication between languages. Which means you can really embed heaps of logic in the KN base.
  2. The multiplatform project is a really great way to share code across platforms. It just makes sense. You abstract your code in `common`, `js`, `jvm`, `ios` or `android`. And the gradle will grab the related pieces to compile according to the platform you wanna build against.
  3. This sort of embrace-the-platform-differences-rather-than-write-everything-once-and-run-anywhere concept has granted KN a very promising future compare to Xamarin’s replacing-them-all.

Starting with gradle, creating a simple build.gradle

(note: proof edits pending)

Gradle a very well known building tool, originating in JVM world, but spreading to wider and wider use. A building tool is designed to automate workflows, particularly for building programs but in fact can automate any workflow iincluding building, linting, testing, pushing and much more to make your life easier. Sometimes it could be hard to grasp the concept even after reading the official documentation. This guide focuses on the basics and can enable having gradle up and running within a few minutes.

1. Gradle Introduction
2. A practical workflow for working with gradle
3. Add plugins
4. Configure the plugin
5. Add the dependencies of your project
6. Configure the project information
7. End

Continue reading “Starting with gradle, creating a simple build.gradle”

How to publish artifacts to Maven Central via Gradle

Publishing artifacts on Maven Central is a close equivalent to publishing Python packages on PyPI (aka the cheese shop). If you have published packages on PyPI before, you will find these steps a bit more advanced than those you tackled in Python.

0. First things first
1. Sign up
2. Apply for your namespace
3. Get the GPG key
4. Save your secrets
5. Set up your project to upload
6. Upload
7. Publish on Maven Central
8. Use it

0. First things first

No one can publish to Maven Central directly. You have to publish your artifacts to an approved repository, then release them to Maven Central.
Sonatype OSS Nexus​ is an approved repository hosting service run by Sonatype (the company that runs Maven Central) which provides hosting free of charge specifically for open-source projects.


1. Sign up

Hopefully, you know about namespaces, packages and groupIds, right? To upload an artifact into a Sonatype repo, your artifact should be created using a specific namespace in order to prevent naming collisions. The package and groupId are also required. You must apply for a namespace from Sonatype. To apply for a namespace, you will need to raise an issue (see below) on the Sonatype Jira instance. In order to do that, you will first need to sign up for a Sonatype Jira account.


  • Sign up with your company email if you are going to apply for a groupId which will be the domain name of your company.
  • Remember your user name and password. It is not only used for raising issues. It is used for uploading your artifacts as well.


2. Apply for your namespace

Create an issue here to apply for your namespace (it should be a reversed domain name). Your issue will be manually reviewed by a Sonatype employee. It should be fast, within 2 hours.


After your application is approved, you will gain permission to the following URLs:


3. Get the GPG key

If you use Mac, you should download and install GPG Suite. Then open the app. The generate new key pair dialogue box should automatically open, otherwise press New on the tope menu in the app to create your key pair.

  • Name is the user name that you used when you registered on Sonatype.
  • Email is the email address that you used when you registered on Sonatype.
  • Enter a unique password twice to confirm it. Remember this password too, you are going need it.
  • Advanced options can be left as they are.

Needs confirmation: I don’t know whether the user name and email need to match, but I matched them both just in case.

After successfully creating your key, either accept the option to Upload Public Key in the dialogue box displayed or right-click your key in the key list in the app and select Send Public Key to Key Server to publish your public key.
To find your Key ID double-click your key in the key list in the app, select the Key tab if not already selected, note it down.
In Terminal on your Mac, use this command to get the secret key ring file:
gpg --export-secret-keys YOUR-KEY-ID > secret-keys.gpg

Enter the passphrase you used when you created the key in the Pinentry Mac dialogue box when it is displayed. The secret-keys.gpg file will be located in the folder where you ran GPG export command above. Take note of the path to this file, it will be needed later.
If you use Windows or other systems, you just need to get the following 3 things in order to push any further:

  • Key ID of your newly generated key pair.
  • The key password for this key pair.
  • The secret key ring file called secret-keys.gpg.

4. Save your secrets

Create your ​gradle.properties file or open it if you already have one and add the following code:




  • Add the gradle.properties to your project root folder rather than in the .gradle  or gradle folders. Why? I am using Intellij IDEA and my IDEA gradle settings file could not be found if I put it either of those two folders. I had to put it in the project root.
  • ADD THE gradle.properties FILE TO YOUR PROJECT’S .gitignore. You never want to release this to the repo (it has your key password).


5. Set up your project to upload

There is an official guide here using the Maven gradle plugin, but I choose to use ​com.bmuschko.nexus because I found it easier to understand and use.
Below is the full code listing of the build.gradle ​com.bmuschko.nexus plugin. Add it to your current gradle code:

buildscript {
  repositories {
  dependencies {
     classpath 'com.bmuschko:gradle-nexus-plugin:2.3.1'

apply plugin: 'com.bmuschko.nexus'

archivesBaseName = 'teachUpload-jvm'
group = "com.yourCompany.package"
version = "0.1"

modifyPom {
 project {
   name 'teachUpload'
   description 'Teaching how to use gradle.'
   url 'https://bitbucket.org/objdict/objjson'
   inceptionYear '2018'

   scm {
     url 'https://bitbucket.org/objdict/objjson'
     connection 'scm:https://bitbucket.org/objdict/objjson.git'
     developerConnection 'scm:git://bitbucket.org/objdict/objjson.git'

   licenses {
     license {
       name 'The Apache Software License, Version 2.0'
       url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
       distribution 'repo'

   developers {
     developer {
       id 'albertgao'
       name 'Albert Gao'
       email 'albert.gao@salect.co.nz'

extraArchive {
 sources = true
 tests = true
 javadoc = true

nexus {
 sign = true
 repositoryUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
 snapshotRepositoryUrl = 'https://oss.sonatype.org/content/repositories/snapshots/'


  • You don’t need to create the sourceJar in the build.gradle settings file above. The ​com.bmuschko.nexus plugin will add it for you.

6. Upload

The above code should add an uploadArchives task to your gradle (it might reside in the upload category (if you can’t find it in your IntelliJ IDEA gradle side-panel)).

Double click it to execute the uploadArchives task.
You might see the following error when you first upload:
Could not find metadata com.yourCompany.package:teachUpload-jvm/maven-metadata.xml in remote (https://oss.sonatype.org/service/local/staging/deploy/maven2/)

  • This is not an error, just information – this is your first time, so no meta file previously existed on the server.
  • Your package will have already been uploaded if this is the only information displayed.

Congratulations! After completing all of these steps, your package should finally have been uploaded onto Sonatype OSS Nexus.


7. Publish on Maven Central

There are two ways to get your artifacts onto Maven Central:

  1. Auto-publish via gradle
  2. Manually publish via Nexus website

7.1 Auto-publish via gradle

We are going to need to use another gradle plugin called Gradle Nexus Staging plugin.

Just add the following gradle code:

plugins {
    id 'io.codearte.nexus-staging' version '0.11.0'
nexusStaging {
    // optional if packageGroup == project.getGroup()
    packageGroup = "org.mycompany" 

    // when not defined will be got from server using "packageGroup"
    stagingProfileId = "yourStagingProfileId"

Now several gradle tasks will exist:

  • closeRepository – closes an open repository with the uploaded artifacts. There should be just one open repository available in the staging profile (possible old/broken repositories can be dropped with Nexus GUI)
  • releaseRepository – releases a closed repository (required to put artifacts to Maven Central aka The Central Repository)
  • closeAndReleaseRepository – closes and releases a repository (an equivalent to closeRepository and then releaseRepository)
  • getStagingProfile – gets and displays a staging profile id for a given package group. This is a diagnostic task to get the value and put it into the configuration closure as stagingProfileId.

Now you should already have uploaded your artifacts to the Nexus repo. All you need to do now is to run the closeAndReleaseRepository, and your artifacts will be added to Maven Central (within 10 min ~ 2 hours).


  • If you have a multiple project gradle setup. You just need to add this plugin at the root level.

7.2 Manually publish via Nexus website

The reason we still need this publishing option is that sometimes there are some errors during the auto-publishing phase. After publishing, check the status on the website. Follow the steps below to publish manually if the auto option is unsuccessful.

  1. Open the Nexus Repository Manager.
  2. Click the Log In button in the upper right corner of the screen.
  3. On the right-hand side, click Staging Repositories.
  4. Search your project by following this search pattern: if for example, your groupId is com.google, then enter comgoogle.
  5. Select the correct item and click the Close button to close it – this action finalizes the upload.
  6. Click the Refresh button to get the latest updates (remember this trick, no ajax yet).
  7. If see any errors:
    • You can inspect them at the Activity panel.
    • You will need to:
      •  Drop this upload
      • Find and fix the errors in your local folder
      • Run the uploadArchives task again
      • Then finalize the upload by pressing the Close button again and then continue
  8. If you see NO errors:
    • Click the Release button to publish

Congratulations! Your artifact should have finally been uploaded to Maven Central.

8. Use it

In the build.gradle file in your project, add the following if you want to use this package:

repositories {

dependencies {
    compile "com.yourCompany.package:teachUpload-jvm:0.1"

The pattern in our example is: groupId:archiveBaseName:versionNumber

          groupId = com.yourCompany.package
          archiveBaseName = teachUpload-jvm
          versionNumber = 0.1



Hopefully now you get it and everything is set up! Enjoy. 🙂