With the emergence of mobile phone users, mobile application developers have constantly been struck by the choice of whether they should duplicate the effort for Android & iOS and go native with maximized performance and control or should they compromise on these and go cross-platform with a single effort for both applications.
In cross-platform, we have popular options like Flutter & React Native that provide you with development on both iOS & Android with a single codebase. But they have some major drawbacks, such as a lacking performance, since none of these can directly communicate with the system’s architecture; hence, they have to use wrappers, which get the job done, but at the cost of performance on both sides. Secondly, lack of flexibility: these platforms don’t give you much control over native components like cameras, storage, etc. Now, let’s talk about the man of this article.
KMM allows you to share a common business logic (e.g., fetching data from the backend, or local DB) between iOS & Android and write the presentation logic separately for both. It reduces the amount of code duplication by more than 70% as compared to going completely native, while keeping both the performance and control over native components, since UI is still being developed natively, for Android being in Jetpack Compose and for iOS in SwiftUI. Let’s start with KMM now.
In the new project window in Android Studio, select the KMM Mobile application.
Select the name, package name, and saving directory in the next window.
In the next window, you can keep the same name for both iOS and Android applications or have different ones if you want.
I have selected ‘iOS framework distribution’ to ‘Cocoapods dependency manager’ because it is a more accessible way to install and manage dependencies in your project.
Before doing this, make sure you have pods installed on your system (Only on MAC).
To check whether you have pods installed or not, run
pod --version in the terminal. If there are none, then run
$ sudo gem install cocoapods ; it will download and install the latest version of Cocoapods on your system.
Click finish and let Android Studio build the project.
Now, to open iOS-specific code, go to your project directory, follow the path as shown below, and open the .xcworkspace file in Xcode
Upon building the iOS app, you might get the error below.
It is nothing to worry about, iOS requires uniquely identifying your app, so it requires your identifier to be a unique one. Don’t worry, it will not affect your Application name. Just make it a unique one and you will be good to go.
Now, build the app on both sides.
Under the root project directory, you have 3 main folders.
That is where your iOS-specific code will go, such as UI or if you are using any native component.
That is where your Android-specific code will reside.
That is where you will write all of your business logic containing data and domain layers.
Now, you will also have two Gradle files apart from the project one.
And if you also get these error lines in Gradle files, don’t worry, there is nothing wrong with your project, it’s just the default SDK messing with you.
To fix this, go to Gradle settings and select and download Zulu SDK, restart Android Studio and you will be good to go.
Now, get back to the two Gradle files.
In Module: shared, you will have dependencies and configurations for the shared module; here you will add libraries or settings that both platforms will be able to access. For example, if you are using firebase, to share it among both, you will have to use Git Live SDK. You will add that SDK in a shared module, just like you add dependencies in Android.
By default, in the shared module you will get a simple class,
and it is accessed on both the iOS and Android side, e.g.;
And if you see this error of Xcode not being able to find the shared module’s code, just build your Xcode project and it will start working fine.
Another important thing to know about the shared module is ‘expect’ and ‘actual’. If you open Platform.kt, you will see something like this:
You use ‘expect’ and ‘actual’ when something in the shared module depends upon something native. For example, in our case, we are displaying the operating system version in default text view, which is something you can get from the native side only, so we created an ‘expect’ function whose ‘actual’ will be in directories called ‘androidMain’ & ‘iosMain’.
In the shared module, there are three directories.
Just like this:
Here, you can see that we are writing the implementation of an interface Platform and returning it via the ‘actual’ of getPlatform() function. If you are using dependency injection in your project, you will also have to write the ‘expect’ and ‘actual’ dependency modules. Because dependency injections work differently on both Android & iOS.
That’s it for getting started. We wish you luck with KMM.