We love trying out new technologies at Tooploox. That’s why we’ve recently been experimenting with the Kotlin multiplatform (KMM) to see if we can use it in production applications built for our clients to save development time and money.
First, we built a mobile application for one of our internal projects and then decided to give it a spin in one of our commercial projects.
There are a lot of challenges when using the Kotlin multiplatform as it’s an emerging technology and we’d like to share our solution with the community on how to handle multiple environments.
What this blog post will cover:
- Instructions on how to pass the chosen environment as an argument when building a shared KMM module from the iOS app.
What you won’t find in this blog post:
- Detailed instructions on how to configure and set up build types and environments on the iOS side using build configurations and `.xcconfig` files. There are plenty of existing tutorials adequately covering this topic. If you want to dive deep into this topic I really recommend this tutorial: Building Your App Using Build Configurations and .xcconfig
- Detailed instructions on how to configure and set up build types and environments on the Android side. We used BuildKonfig to set up Dev and Prod configurations. It’s pretty straightforward, feel free to check out this commit to see implementation details. Then if you need to use `baseUrl` somewhere in the shared module then you just need to place `import com.yuki.shared.BuildConfigData` at the top of your file and simply use `BuildConfigData.baseUrl`.
So let’s run Xcode and see how we can configure our project to support Development (referred to as `dev` in code) and Production (referred to as `prod` in code) environments in a Kotlin Multiplatform project. For the purpose of this tutorial, I used a kmm-basic-sample as an example project so I didn’t have to set up a new KMM project from scratch.
- First, we need to create configs for each of the build types and environments we want to support.
- Build types
I created `Debug` and `Release` configs to handle different build types. All you have to do is add `KOTLIN_FRAMEWORK_BUILD_TYPE = Debug` and `KOTLIN_FRAMEWORK_BUILD_TYPE = Release` respectively in the Debug.xcconfig and Release.xcconfig files (please refer to the tutorial linked in the paragraph above to see how to add .xcconfig files to your project).
I created `Development` and `Production` .xcconfig files to handle different environments. All you have to do is to add `KMM_FLAVOR = dev` and `KMM_FLAVOR = prod` respectively in the Development.xcconfig and Production.xcconfig files. Make sure that `dev` and `prod` are the names of the configs provided on the Android side. We’ll pass them later on as arguments when building our shared module.
- Build types
- When you have those config files created you need to use them to set up configurations for your project in Xcode. Take a look at the screenshot below to see how I configured them.
- Optionally you can create separate schemes for every environment so you can easily switch between the two versions of your app, one pointing to the Development environment and the second to Production. Take a look at the screenshot below to see how I configured the Debug-Dev scheme using configs created in Step 2.
- The final step is to pass the selected environment when building a shared KMM module, in order to do so we have to replace the default run script:
cd "$SRCROOT/.." ./gradlew :shared:embedAndSignAppleFrameworkForXcode
cd "$SRCROOT/.." ./gradlew -i :shared:embedAndSignAppleFrameworkForXcode -P buildkonfig.flavor=$KMM_FLAVOR
I prepared a repository with a sample project as complementary material for this blog post. Feel free to check it out.
It took us some time to research this topic and come up with this solution so hopefully, this tutorial will save you some time. I’d like to give credit to my colleague Przemysław Stasiak for helping me out with research and this blog post. Feel free to send us any questions if you have any.