Kotlin Multiplatform Android Imports 无法解决

Posted

技术标签:

【中文标题】Kotlin Multiplatform Android Imports 无法解决【英文标题】:Kotlin Multiplatform Android Imports won't resolve 【发布时间】:2019-12-31 02:48:03 【问题描述】:

我创建了一个非常简单的 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 平台上运行。

但是当我尝试在我的 androidMain 目录中使用 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) 

【问题讨论】:

FWIW,我尝试将 android 插件添加到我的构建文件中,但我认为这是不正确的,并且构建无法查找 AndroidManifest.xml 文件,在 SharedCode 目录中不可用 plugins id("com.android.application") kotlin("multiplatform") android compileSdkVersion(28) 【参考方案1】:

您的 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

希望对您有所帮助。

【讨论】:

确实解决了我的问题!你是我的英雄!谢谢!

以上是关于Kotlin Multiplatform Android Imports 无法解决的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin-multiplatform:如何执行 iOS 单元测试

在 kotlin-multiplatform 上生成 UUID?

Kotlin Multiplatform 项目包含 cocoapod 依赖项

如何使用 Kotlin-Multiplatform 在 iOS 应用程序的后台线程中运行任务?

如何在 Kotlin Multiplatform(纯 kotlin)中进行延迟

Kotlin Multiplatform Android Imports 无法解决