Kotlin Multiplatform Android 导入无法解析
Kotlin Multiplatform Android Imports won't resolve
我创建了一个非常简单的 KMP 项目,结构如下:
-Root
--app
--gradle
--SharedCode
--src\commonMain\kotlin\actual.kt
--src\iosMain\kotlin\actual.kt
--scr\androidMain\kotlin\actual.kt
--build.gradle.kts
--native
--KotlinIOS
--iOS project (xcodeproj, etc)
一切正常,基本项目可在 Android 和 iOS 平台上运行。
但是当我尝试在我的 android 主目录中使用 android-specific 导入语句时,导入语句不会解析:
import android.os.build // Android Studio can't find this
actual fun platformName(): String {
return "Android"
}
这很奇怪,因为 iOS 包正在使用 iOS-specific 成功导入:
import platform.UIKit.UIDevice // This import works
actual fun platformName(): String {
return UIDevice.currentDevice.systemName() +
" " + UIDevice.currentDevice.systemVersion
}
关于我可能需要配置什么才能让我的 Android 导入正常工作有什么建议吗?
为了完整性,这是我的 build.gradle.kts 文件:
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
}
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 = "SharedCode"
}
}
}
jvm("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) {
val targetDir = File(buildDir, "xcode-frameworks")
/// selecting the right configuration for the iOS
/// framework depending on the environment
/// variables set by Xcode build
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets
.getByName<KotlinNativeTarget>("ios")
.binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
from({ framework.outputDirectory })
into(targetDir)
/// generate a helpful ./gradlew wrapper with embedded Java path
doLast {
val gradlew = File(targetDir, "gradlew")
gradlew.writeText("#!/bin/bash\n"
+ "export 'JAVA_HOME=${System.getProperty("java.home")}'\n"
+ "cd '${rootProject.rootDir}'\n"
+ "./gradlew $@\n")
gradlew.setExecutable(true)
}
}
tasks.getByName("build").dependsOn(packForXcode)
您的 gradle 构建脚本中没有 android 必需的定义。这是适合我的基本 gradle 脚本:
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.tasks.FatFrameworkTask
buildscript {
repositories {
mavenLocal()
maven("https://kotlin.bintray.com/kotlinx")
maven("https://dl.bintray.com/jetbrains/kotlin-native-dependencies")
maven("https://dl.bintray.com/kotlin/kotlin-eap")
maven("https://plugins.gradle.org/m2/")
google()
jcenter()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.50")
classpath("com.android.tools.build:gradle:3.5.0")
classpath("co.touchlab:kotlinxcodesync:0.1.5")
}
}
plugins {
id ("com.android.library") version "1.3.50"
id ("org.jetbrains.kotlin.multiplatform") version "1.3.50"
}
allprojects {
repositories {
mavenLocal()
google()
jcenter()
mavenCentral()
maven("https://dl.bintray.com/kotlin/kotlin-eap")
maven("https://kotlin.bintray.com/ktor")
maven("https://kotlin.bintray.com/kotlinx")
}
}
group = "com.example.mykmp"
version = "0.0.1"
apply(plugin = "maven-publish")
apply(plugin = "com.android.library")
apply(plugin = "kotlin-android-extensions")
android {
compileSdkVersion(29)
defaultConfig {
minSdkVersion(21)
targetSdkVersion(29)
}
}
kotlin {
android()
val frameworkName = "mykmp"
val ios = iosX64("ios") {
binaries.framework {
baseName = frameworkName
}
}
sourceSets {
commonMain {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
commonTest {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting {
dependencies {
implementation(kotlin("stdlib-jdk8"))
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
}
}
val iosMain by getting {
dependencies {
implementation(kotlin("stdlib"))
}
}
val iosTest by getting {
dependencies {
implementation(kotlin("stdlib"))
}
}
}
tasks.create("framework", FatFrameworkTask::class) {
baseName = frameworkName
from(
ios.binaries.getFramework("DEBUG")
)
destinationDir = buildDir.resolve("xcode-frameworks")
group = "iOS frameworks"
description = "Builds a simulator only framework to build from xcode directly"
doLast {
val file = File(destinationDir, "gradlew")
file.writeText(text = "#!/bin/bash\nexport JAVA_HOME=${System.getProperty("java.home")}\ncd ${rootProject.rootDir}\n./gradlew $@\n")
file.setExecutable(true)
}
}
}
tasks.getByName("build").dependsOn(packForXcode)
此外,在 settings.gradle.kts
中,我有这个:
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == "kotlin-multiplatform") {
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
}
if (requested.id.id == "com.android.library") {
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
}
if (requested.id.id == "kotlinx-serialization") {
useModule("org.jetbrains.kotlin:kotlin-serialization:${requested.version}")
}
}
}
}
否则会提示找不到com.android.library
之后我还会在 Android Studio 或 IntelliJ 上推荐 Invalidate Cache/Restart
。
希望对您有所帮助。
我创建了一个非常简单的 KMP 项目,结构如下:
-Root
--app
--gradle
--SharedCode
--src\commonMain\kotlin\actual.kt
--src\iosMain\kotlin\actual.kt
--scr\androidMain\kotlin\actual.kt
--build.gradle.kts
--native
--KotlinIOS
--iOS project (xcodeproj, etc)
一切正常,基本项目可在 Android 和 iOS 平台上运行。
但是当我尝试在我的 android 主目录中使用 android-specific 导入语句时,导入语句不会解析:
import android.os.build // Android Studio can't find this
actual fun platformName(): String {
return "Android"
}
这很奇怪,因为 iOS 包正在使用 iOS-specific 成功导入:
import platform.UIKit.UIDevice // This import works
actual fun platformName(): String {
return UIDevice.currentDevice.systemName() +
" " + UIDevice.currentDevice.systemVersion
}
关于我可能需要配置什么才能让我的 Android 导入正常工作有什么建议吗?
为了完整性,这是我的 build.gradle.kts 文件:
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
}
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 = "SharedCode"
}
}
}
jvm("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) {
val targetDir = File(buildDir, "xcode-frameworks")
/// selecting the right configuration for the iOS
/// framework depending on the environment
/// variables set by Xcode build
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets
.getByName<KotlinNativeTarget>("ios")
.binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
from({ framework.outputDirectory })
into(targetDir)
/// generate a helpful ./gradlew wrapper with embedded Java path
doLast {
val gradlew = File(targetDir, "gradlew")
gradlew.writeText("#!/bin/bash\n"
+ "export 'JAVA_HOME=${System.getProperty("java.home")}'\n"
+ "cd '${rootProject.rootDir}'\n"
+ "./gradlew $@\n")
gradlew.setExecutable(true)
}
}
tasks.getByName("build").dependsOn(packForXcode)
您的 gradle 构建脚本中没有 android 必需的定义。这是适合我的基本 gradle 脚本:
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.tasks.FatFrameworkTask
buildscript {
repositories {
mavenLocal()
maven("https://kotlin.bintray.com/kotlinx")
maven("https://dl.bintray.com/jetbrains/kotlin-native-dependencies")
maven("https://dl.bintray.com/kotlin/kotlin-eap")
maven("https://plugins.gradle.org/m2/")
google()
jcenter()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.50")
classpath("com.android.tools.build:gradle:3.5.0")
classpath("co.touchlab:kotlinxcodesync:0.1.5")
}
}
plugins {
id ("com.android.library") version "1.3.50"
id ("org.jetbrains.kotlin.multiplatform") version "1.3.50"
}
allprojects {
repositories {
mavenLocal()
google()
jcenter()
mavenCentral()
maven("https://dl.bintray.com/kotlin/kotlin-eap")
maven("https://kotlin.bintray.com/ktor")
maven("https://kotlin.bintray.com/kotlinx")
}
}
group = "com.example.mykmp"
version = "0.0.1"
apply(plugin = "maven-publish")
apply(plugin = "com.android.library")
apply(plugin = "kotlin-android-extensions")
android {
compileSdkVersion(29)
defaultConfig {
minSdkVersion(21)
targetSdkVersion(29)
}
}
kotlin {
android()
val frameworkName = "mykmp"
val ios = iosX64("ios") {
binaries.framework {
baseName = frameworkName
}
}
sourceSets {
commonMain {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
commonTest {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting {
dependencies {
implementation(kotlin("stdlib-jdk8"))
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
}
}
val iosMain by getting {
dependencies {
implementation(kotlin("stdlib"))
}
}
val iosTest by getting {
dependencies {
implementation(kotlin("stdlib"))
}
}
}
tasks.create("framework", FatFrameworkTask::class) {
baseName = frameworkName
from(
ios.binaries.getFramework("DEBUG")
)
destinationDir = buildDir.resolve("xcode-frameworks")
group = "iOS frameworks"
description = "Builds a simulator only framework to build from xcode directly"
doLast {
val file = File(destinationDir, "gradlew")
file.writeText(text = "#!/bin/bash\nexport JAVA_HOME=${System.getProperty("java.home")}\ncd ${rootProject.rootDir}\n./gradlew $@\n")
file.setExecutable(true)
}
}
}
tasks.getByName("build").dependsOn(packForXcode)
此外,在 settings.gradle.kts
中,我有这个:
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == "kotlin-multiplatform") {
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
}
if (requested.id.id == "com.android.library") {
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
}
if (requested.id.id == "kotlinx-serialization") {
useModule("org.jetbrains.kotlin:kotlin-serialization:${requested.version}")
}
}
}
}
否则会提示找不到com.android.library
之后我还会在 Android Studio 或 IntelliJ 上推荐 Invalidate Cache/Restart
。
希望对您有所帮助。