This project serves as a practical demonstration of implementing flavors in a Kotlin Multiplatform (KMP) project. Flavors in the context of KMP are used to differentiate between various build environments, configurations, or feature sets across the shared codebase. Specifically, this example showcases how to manage and utilize different build environments — namely, development and production — within a KMP project.
The use of flavors allows for the customization of the application's behavior, dependencies, and configurations without the need to duplicate code. This approach is particularly beneficial in a multiplatform scenario where consistency across platforms is crucial, yet the need for environment-specific variations exists.
In this example, you'll find how to:
build.gradle.kts
files for targeting different environments.gradle.properties
file to define default build configurations and how to override them via command-line options for flexible build processes.By the end of this project, you'll have a clear understanding of how to effectively implement and work with flavors in a Kotlin Multiplatform project, enhancing your ability to manage complex build configurations and environment-specific logic in a multiplatform context.
This section guides you through setting up your project for development and production environments.
Add the following modules to your project:
config/development
config/production
Include these modules in your project by editing settings.gradle.kts
:
include(":config:development", ":config:production")
In your gradle.properties
file, define the default flavor:
flavor=development
In composeApp/build.gradle.kts
, access the flavor
property:
val flavor: String by project
val suffix = when (flavor) {
"development" -> ".dev"
else -> ""
}
kotlin {
commonMain.dependencies {
implementation(project(":config:$flavor"))
}
}
Create a strings.xml
file for each flavor. E.g.:
config/development/androidMain/values/res/strings.xml
config/production/androidMain/values/res/strings.xml
Add a string with the name app_name
like you normally would.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">KMP Flavor Dev</string>
</resources>
This string can now be used in AndroidManifest.xml like you normally would
android {
namespace = "com.rakangsoftware.flavors"
defaultConfig {
when (flavor) {
"development" -> resValue("string", "app_name", "KMP Flavor Dev")
else -> resValue("string", "app_name", "KMP Flavor")
}
}
}
android {
defaultConfig {
applicationIdSuffix = suffix
}
}
To create a new task for running the debug build, define the following in your build script:
tasks.register("runDebug", Exec::class) {
dependsOn("clean", "uninstallDebug", "installDebug")
commandLine(
"adb", "shell", "am", "start", "-n",
"com.rakangsoftware.flavors$suffix/com.rakangsoftware.flavors.MainActivity"
)
}
Note: Update the MainActivity
path if your starting activity is different.
To build, install, and run your application, use the following commands:
For development:
./gradlew runDebug -Pflavor=development
For production:
./gradlew runDebug -Pflavor=production
Configure run configurations for easy execution within Android Studio:
Below is a refined and detailed iOS setup guide for your README.md, designed to assist in configuring development and production environments for a Kotlin Multiplatform project:
This section outlines the steps required to configure your iOS application for different environments: Development and Production. These configurations enable you to build and run your iOS app with environment-specific settings and resources.
iosApp
root in the project navigator. Then, choose the iosApp
target on the target list to the right.To set up your project for the Development environment, follow these steps:
Rename Info.plist: Rename the iosApp/Info.plist
file to iosApp/Info-Development.plist
. This allows you to maintain separate property lists for different environments.
Update Build Phases: Navigate to the Build Phases
tab and locate the Compile Kotlin Framework
section. Modify the script to include the -Pflavor=development
flag:
./gradlew :composeApp:embedAndSignAppleFrameworkForXcode -Pflavor=development
Adjust Info.plist File Setting: Under the Build Settings
tab, find the Info.plist File
setting within the Packaging
section. Update its value to point to the new development plist file: iosApp/Info-Development.plist
.
Rename the Target: Change the name of the iosApp
target to Development
to clearly identify the build configuration.
Rename Scheme: Update the scheme name to iOS Dev
for easy identification.
For the Production environment, duplicate the Development setup with slight modifications:
Duplicate and Rename Target: Duplicate the Development
target and rename the new target to Production
.
Create and Move Info.plist: Rename the duplicated .plist
file to Info-Production.plist
and ensure it is located within iosApp
.
Update Build Phases for Production: In the Build Phases
of the Production
target, adjust the Compile Kotlin Framework
script to use the production flavor:
./gradlew :composeApp:embedAndSignAppleFrameworkForXcode -Pflavor=production
Update Info.plist File Setting for Production: Within the Build Settings
of the Production
target, change the Info.plist File
under Packaging
to: iosApp/Info-Production.plist
.
Rename Scheme: Rename the newly created scheme to iOS Prod
for clarity.
Invalidate Android Studio Caches: To ensure that your changes are fully applied and to avoid potential issues, invalidate the caches in Android Studio by navigating to File
-> Invalidate Caches
-> Check all boxes -> Click Invalidate and Restart
.
Setup iOS Run Configurations: Adjust your iOS run configurations to reflect the Development and Production setups. This ensures that you can easily switch between environments when running your app.