I’m attempting to set up a Kotlin multiplatform project inside an existing Android project, and I’m having some issues getting my Gradle files configured properly. I’m in a state where my common module builds, but the original Android project can’t resolve the common module:
build.gradle: Unable to resolve dependency for ':app@preview/compileClasspath': Could not resolve project :common.
build.gradle: Unable to resolve dependency for ':app@previewUnitTest/compileClasspath': Could not resolve project :common.
build.gradle: Unable to resolve dependency for ':app@debug/compileClasspath': Could not resolve project :common.
build.gradle: Unable to resolve dependency for ':app@debugAndroidTest/compileClasspath': Could not resolve project :common.
build.gradle: Unable to resolve dependency for ':app@debugUnitTest/compileClasspath': Could not resolve project :common.
build.gradle: Unable to resolve dependency for ':app@release/compileClasspath': Could not resolve project :common.
build.gradle: Unable to resolve dependency for ':app@releaseUnitTest/compileClasspath': Could not resolve project :common.
I was originally following this tutorial here for guidance, and adapted it a bit so that the Android part could access core Android classes like Context.
Is there something I’m missing in my approach? Should I be configuring this so that the Android project in its entirety is compiled as part of the multiplatform project, instead of keeping the Android app code separate? My current understanding of the setup is that everything should be in their own project (common, android, and ios), and that common has modules inside for each of the platforms its intended to support (commonAndroid, commonIos) in addition to the platform-agnostic stuff (common).
common module build.gradle.kts:
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
id("com.android.application")
kotlin("multiplatform")
}
android {
compileSdkVersion(28)
defaultConfig {
minSdkVersion(21)
targetSdkVersion(28)
}
}
kotlin {
//select iOS target platform depending on the Xcode environment variables
val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
::iosArm64
else
::iosX64
iOSTarget("ios") {
binaries {
framework {
baseName = "life4common"
}
}
}
android()
sourceSets["commonMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
}
sourceSets["androidMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
}
}
val packForXcode by tasks.creating(Sync::class) {
group = "build"
//selecting the right configuration for the iOS framework depending on the Xcode environment variables
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets.getByName<KotlinNativeTarget>("ios").binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-frameworks")
from({ framework.outputDirectory })
into(targetDir)
doLast {
val gradlew = File(targetDir, "gradlew")
gradlew.writeText("#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n")
gradlew.setExecutable(true)
}
}
tasks.getByName("build").dependsOn(packForXcode)
Original Android build.gradle:
plugins {
id "com.android.application"
id "kotlin-android"
id "kotlin-android-extensions"
id "kotlin-kapt"
id "io.fabric"
id "com.google.gms.google-services"
id "io.objectbox"
}
android {
compileSdkVersion = 28
defaultConfig {
applicationId "com.perrigogames.life4trials"
minSdkVersion(18)
targetSdkVersion(28)
versionCode = 52
versionName = "3.1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
signingConfig signingConfigs.upload
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
signingConfig signingConfigs.upload
manifestPlaceholders = [providerName: "com.perrigogames.fileprovider"]
}
preview {
initWith(release)
}
debug {
applicationIdSuffix = ".debug"
signingConfig = signingConfigs.debug
manifestPlaceholders = [providerName: "com.perrigogames.fileprovider.debug"]
}
}
compileOptions {
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
}
packagingOptions {
exclude("META-INF/DEPENDENCIES")
exclude("META-INF/LICENSE")
exclude("META-INF/LICENSE.txt")
exclude("META-INF/license.txt")
exclude("META-INF/NOTICE")
exclude("META-INF/NOTICE.txt")
exclude("META-INF/notice.txt")
exclude("META-INF/ASL2.0")
}
lintOptions {
abortOnError = false
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
dependencies {
implementation(project(":common"))
implementation(fileTree(include: ["*.jar"], dir: "libs"))
implementation(dep.kotlin_stdlib_jre7)
implementation(dep.multidex)
implementation(dep.androidx)
implementation(dep.glide)
implementation(dep.eventbus)
implementation(dep.dexter)
implementation(dep.firebase)
implementation(dep.retrofit)
implementation(dep.coroutines_android)
implementation(dep.coroutines_jvm)
implementation(dep.lottie)
debugImplementation(dep.objectbox_debug)
releaseImplementation(dep.objectbox_release)
implementation("com.google.guava:guava:27.0.1-android")
kapt(dep.glide_compiler)
testImplementation(dep.junit)
testImplementation(dep.androidx_test)
testImplementation(dep.robolectric)
androidTestImplementation(dep.espresso)
}