Search code examples
androidkotlinkotlin-multiplatform

Android context in multiplatform project


I wonder if is possible to access the Android context application in androidMain sourceSets with the kotlin-multiplatform plugin.

Here is the build.gradle file

apply plugin: 'kotlin-multiplatform'

kotlin {
    targets {
        final def iOSTarget = System.getenv('SDK_NAME')?.startsWith("iphoneos")   \
                                ? presets.iosArm64 : presets.iosX64

        fromPreset(iOSTarget, 'iOS') {
            compilations.main.outputKinds('FRAMEWORK')
        }

        fromPreset(presets.jvm, 'android')
    }

    sourceSets {

        commonMain {
            kotlin.srcDir('src')
            dependencies {
                implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
                // coroutine
                implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.1.0"
            }
        }

        androidMain {
            dependencies {
                implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
                // Timber
                implementation "com.jakewharton.timber:timber:$timber_version"
                // coroutine
                implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.0"
            }
        }
    }
}

I have tried add the 'com.android.application' plugin into androidMain source, but the sync fails.

Thanks in advance


Solution

  • Yes, you can.

    In your build.gradle file you are not targeting android as such (presets.android) but the jvm (presets.jvm) and calling it android.

    As it is now, what your build will generated is a JAR file not an aar file.

    If you want to target android you have also to use the android gradle plugin. To be able to use the android framework from the androidMain folder, update your build.gradle file. Below an example:

    apply plugin: 'org.jetbrains.kotlin.multiplatform'
    apply plugin: 'com.android.library'
    
    android {
        compileSdkVersion 28
        defaultConfig {
            minSdkVersion 21
            targetSdkVersion 28
            versionCode 1
            versionName '1.0'
        }
        buildTypes {
            release {
                minifyEnabled false
            }
        }
    
            // By default the android gradle plugin expects to find the kotlin source files in 
            // the folder `main` and the test in the folder `test`. This is to be able place 
            // the source code files inside androidMain and androidTest folders
        sourceSets {
            main {
                manifest.srcFile 'src/androidMain/AndroidManifest.xml'
                java.srcDirs = ['src/androidMain/kotlin']
                res.srcDirs = ['src/androidMain/res']
            }
            test {
                java.srcDirs = ['src/androidTest/kotlin']
                res.srcDirs = ['src/androidTest/res']
            }
        }
    }
    
    dependencies {
        implementation "com.jakewharton.timber:timber:$timber_version
    }
    
    kotlin {
        targets {
            final def iOSTarget = System.getenv('SDK_NAME')?.startsWith("iphoneos")   \
                                    ? presets.iosArm64 : presets.iosX64
    
            fromPreset(iOSTarget, 'iOS') {
                compilations.main.outputKinds('FRAMEWORK')
            }
    
            fromPreset(presets.android, 'android')
        }
        sourceSets {
            commonMain {
                dependencies {
                    implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
                    // coroutine
                    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.1.0"
                }
            }
            androidMain {
                dependencies {
                    api "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
                }
            }
        }
    }
    
    task buildiOSFramework(type: Sync) {
    
        final File frameworkDir = new File(buildDir, "xcode-frameworks")
        final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'
    
        inputs.property "mode", mode
        dependsOn kotlin.targets.iOS.compilations.main.linkTaskName("FRAMEWORK", mode)
    
        from { kotlin.targets.iOS.compilations.main.getBinary("FRAMEWORK", mode).parentFile }
        into frameworkDir
    
        doLast {
            new File(frameworkDir, 'gradlew').with {
                text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n"
                setExecutable(true)
            }
        }
    }