To see our repository with a sample app written with the help of KMM, go to https://github.com/itmaginationdemos/KMM-Sample-App
Before we get to the main part of the article, we would like to explain our starting position first. We went into this completely blind with minimal earlier knowledge on KMM (Kotlin Multiplatform Mobile) and some of the issues we got is due to this lack of experience with the framework, as it’s still fresh. With just some time, you quickly become familiar with the tool.
As a sidenote, big companies already realized the benefits of the new framework – including Philipps, Netflix, and VMWare. Even though there are some hiccups along the way, KMM is a phenomenal tool for cross-platform mobile development in large organizations.
Google search results when you enter the phrase “KMM tutorial” were official docs, and they are immensely helpful. It would have been helpful to tell the reader which Gradle file should we place the necessary code, as it is not obvious (every one of the files is called the same). It kind of feels like when you are starting learning Android programming and Android Studio for the first time.
An awesome tool mentioned in the tutorial on the official site is KDoctor, which proved a tremendous help with finding any issues that arose. For example, there was a lot of head scratching when KMM plugin got removed (seemingly for no reason) which was diagnosed by KDoctor in a few seconds (it did take us a few hours to ask the good doctor for help, though).
Basic Koin set up was awesome. It was clear and concise. Everything fell right into place in minutes within opening the docs. If you needed any further explanation, there was some sample code for Android and iOS. There was a slight issue, but more on that in the next section.
Starting a new project is overwhelming. You must grasp a lot of new concepts. We are also bombarded with loads of unnecessary folders/subsets. Arguably, the first minutes can put newcomers off.
Let’s get back to Koin. Like we mentioned already, basic set up was a dream, but with one slight issue - shared code between Android and iOS in case of constructors having differed for whatever reason. To be more precise, when instantiating SQLDelight database we had to manually create each of the instances (not a big issue but could be added to the docs).
To create an iOS app, you need XCode. For whatever reason, in the year 2022 we have limited bandwidth on Apple’s side which made the download take 5 hours (for reference Android Studio download takes 1 to 2 minutes). Anyway, just like in the 90s, start the download before you go to sleep.
We talked to some people who also tried KMM, and some did have these issues, some had different ones, and some had none. Our experiences described below may not be the same as yours.
Sadly, we had quite a few problems with Gradle, Android Studio, Kotlin and the KMM plugin itself, and it is hard to precisely pinpoint what was the issue. From the first start of the tutorial to the time of writing of this article, we had changed versions of all of them (they change regularly).
We even tried Android Studio Chipmunk, Dolphin and Electric Eel, of which the latter proved to be the most stable (which is odd).
Also, as we already mentioned, the KMM plugin just got removed at some point, which we didn’t even notice at first until we called KDoctor. In retrospect, this could have been the biggest issue here. Without it, a lot of strange errors and false alarms popped up. For example, we had a bunch of errors around shared iOS and Android code, but the code compiled correctly.
There were some frustrating issues with empty source sets as well, where they were interpreted as modules. This caused issues when using the expect keyword (more on that here), when the IDE (Integrated Development Editors) was sure we had missing implementations.
Not sure if this is related to KMM as such, but Compose navigation also had some issues. Even though we followed the instructions correctly, we weren’t able to import NavHostController. After some searching around, we found some advice to clear Gradle caches and reset Java class paths. With the help of Invalidating caches and a restart, 40 minutes later, the import worked. It was not fun.
We wanted to add something a bit more complicated to the project, so we went with recording voice notes, as the name of the app suggests.
We started with making a newcomer mistake in trusting Google documentation. The issue we experienced was writing to external storage. Doing this got really complicated in the last few Android versions, and the documentation was not too helpful. Authors of docs targeted Android API 28 which omits most of those issues.
Furthermore, we needed to get users permission to record voice messages, and we started doing that the old way (before Compose). The solution could have been improved a lot, but it was messy, and we didn’t like it. So, we Googled a bit for something better. Enter Accompanist, a set of tools to be used with Compose. Here, Google does help us out a big deal. There are a bunch of useful features there, but we just used the permission part – which deals with the voice permission in three lines of code.
Maybe when you read this you get the sense that everything is bad, and it is not worth it. That cannot be further from the truth. Think of this more as a map to avoid pitfalls (some of them, at least). There are a few more potential issues you will encounter that we did not cover here that mostly relates to multi-threading on iOS – but that is a topic for another time.
When you set everything up, you can pretty much think of this as a multimodule Android application, with an emphasis on sharing as much code as possible with primary modules (Android and iOS). With a hypothetical app that has a relatively simple UI but a lot of logic (mapping or being offline-first) you could really limit the amount of repeated code and as such limit the time spent on writing it and having inevitable bugs that come with it.
We may have had a more biased view towards smaller teams or even individuals, as some of the problems listed are non-issues on larger teams. When you have a team of 10 or more developers, spending a few days setting everything up is not that much in the grand scheme of things. Also, the main benefit of code reuse scales well with larger teams and larger codebases (more code in a shared module means less code is doubled across platforms).
We wrote recently on the topic of code reusability in the large applications, which you can check out here. The gist of it is that if you have a complex product, you probably have a lot of complex code and domain rules. Those things must be written two times (Android and iOS) which means two times the bugs, two times the cost and probably not a 100% overlap in functionality.
Finally, as opposed to other multiplatform solutions, with KMM, by design, you are not in any way touching the UI part of your application. The UI is 100% on a per-platform basis and as such it will have the authentic feel of a native app. On the other hand, you will need to hire additional developers, experiences in writing native iOS interfaces.
We encourage you to try it, you never know, maybe this is exactly what you were looking for. If you need a hand implementing the new app in your company, feel free to contact our experts.