简体   繁体   中英

How to make Kotlin Multiplatform work with Android Studio's project view?

I am trying to build a template of a Multiplatform library module in Android studio that can interoperate seamlessly with other normal Android library and application modules. I've found it's easy enough to make a Multiplatform Android project technically work in terms of compiling, running and publishing artefacts, but one problem I can't seem to solve is getting the source sets to show correctly in the Android project files pane view.

So you can see in the Project view here, the sources are divided into android, native and common directories and their respective test directories, for a total of six source directories:

项目文件视图

In the Android Project view this is rendered by build targets instead of source file directories, so that this 'typing-sdk' module example has total of 10 different sub-modules. And you'll notice androidMain and androidTest are not among them: instead of being rendered as submodules, their sources fall under an inline kotlin directory instead; you can see the main and test com.demo.typing packages respectively.

Android 项目视图

It is a little annoying that every single build target gets its own submodule, when in practice, one will virtually never actually need to use some of these, like 'iosArm64Test' for example. Nevertheless, I can live with redundant submodules. The central problem here is that each of these submodules are populated with the wrong source files.

So whereas in the file structure, both the common and native sets have their own source files, as you can seen here:

扩展的项目文件视图

In the Android Project View, every single submodule contains the Android sources??

扩展的 Android 项目视图

Either this is a bug in how Android Studio interoperates with the Kotlin Multiplatform Gradle Plugin, or there's something wrong with the Gradle build file I have written, which is this (using Gradle 7.1):

plugins {
    id 'org.jetbrains.kotlin.multiplatform' version '1.6.10'
    id 'com.android.library' version '7.0.4'
}

allprojects {
    group = 'typing'
    version = '1.0'
    sourceCompatibility = '1.8'

    repositories {
        mavenCentral()
        google()
    }
}

kotlin {
    android()
    ios()

    sourceSets {
        commonMain
        commonTest
        androidMain {
            dependsOn(commonMain)
        }
        androidAndroidTestRelease
        androidTest {
            dependsOn(commonTest)
            dependsOn(androidAndroidTestRelease)
        }
        nativeMain {
            dependsOn(commonMain)
        }
        nativeTest {
            dependsOn(commonTest)
        }
        iosMain {
            dependsOn(nativeMain)
            iosX64Main.dependsOn(it)
            iosArm64Main.dependsOn(it)
        }
        iosTest {
            dependsOn(nativeTest)
            iosX64Test.dependsOn(it)
            iosArm64Test.dependsOn(it)
        }
    }
}

android {
    compileSdk 31
    defaultConfig {
        minSdk 23
        targetSdk 30
    }
}

I have noticed most of the source examples already out there are using Kotlin DSL, which is preferable, but circumstances are forcing me to use Groovy here. On another project I have that is Kotlin DSL, using earlier versions of the Gradle (7.0.2) Android Gradle Plugin (7.0.2) and Kotlin (1.5.20), the Android project view is rendered differently, and though still quite defective, it's not so disastrously wrong as to have Android sources listed under every single build target module. In the Android block on that project you have a second definition of the sourcesets to the com.android.library plugin:

android {
    compileSdk = 31
    defaultConfig {
        minSdk = 23
        targetSdk = 30

        consumerProguardFiles("proguard-rules.pro")
    }
    sourceSets.all {
        java.srcDirs(file("src/android${name.capitalize()}/kotlin"))
        res.srcDirs(file("src/android${name.capitalize()}/res"))
        resources.srcDirs(file("src/android${name.capitalize()}/resources"))
        manifest.srcFile(file("src/android${name.capitalize()}/AndroidManifest.xml"))
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

I don't know how to directly translate this into Groovy, but following the Android documentation, one can put something like this:

android {
    compileSdk 31
    defaultConfig {
        minSdk 23
        targetSdk 30
    }
    sourceSets {
        main {
            java.srcDirs = ['src/androidMain/kotlin']
            manifest.srcFile 'src/androidMain/AndroidManifest.xml'
        }
        test {
            java.srcDirs = ['src/androidTest/kotlin']
        }
        androidTest {
            setRoot 'src/androidTest/kotlin'
        }
    }
}

Unfortunately this doesn't solve the problem. If nobody can show me workable Gradle scripts that don't create hideous and broken source file views in Android Studio, I will submit this as a bug to JetBrains.

IntellIJ is the recommended IDE to use when it comes to Multiplatform development.

Android Studio is for more Android Specific things, I don't think Android project view is something JetBrains wants to support, maybe there will be a Kotlin Multiplatform Project View at some point, but not at the moment.

(If you open a Spring, NodeJS, iOS or any other type of project the Android Project View will similarly seem broken)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM