Kevin van Mierlo
Kevin van Mierlo

Reputation: 9814

MacOS specific code with Compose Multiplatform

I'm using Compose Multiplatform to write an app for MacOS. But I want to check if I have an internet connection. Preferably unmetered (so no hotspot). I have found some code for MacOS to check that. But when I create an expect class it complains about the actual class for jvmMain. But I want to put that part in macOSMain. If I try to add an empty class in jvmMain it takes that class instead of macOSMain. So I'm not sure how to implement this?

Here is a part of my build.gradle.kts:

kotlin {
    jvm {
        compilations.all {
            kotlinOptions.jvmTarget = "11"
        }
        withJava()
    }
    macosArm64("macOS")
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
            }
        }
        val jvmMain by getting {
            dependsOn(commonMain)
            dependencies {
                implementation(compose.desktop.currentOs)
            }
        }
        val macOSMain by getting {
            dependsOn(commonMain)
        }
    }
}

In commonMain I put this for testing:

expect class Test {
    fun test(): String
}

In macOSMain I put this:

actual class Test {
    actual fun test(): String {
        return "MacOS"
    }
}

And in jvmMain I put this:

actual class Test {
    actual fun test(): String {
        return "JVM"
    }
}

And to call the function in jvmMain:

fun main() = application {
    println("test: ${Test().test()}")

    Window(onCloseRequest = ::exitApplication) {
        App()
    }
}

Which unfortunately prints "JVM". What do I need to do to make it print "MacOS"? Preferably without implementing the class in jvmMain. I also tried expect class in jvmMain, but it then complained about the function not being there in jvmMain.

Upvotes: 1

Views: 1446

Answers (1)

Hicham
Hicham

Reputation: 770

Although this is an old question, I am answering it in case there is still a need for it or someone else comes across it.

You are getting "JVM" in the output because the Compose Multiplatform app you are running runs in the JVM, so it uses the jvm target you defined in the kotlin block, while the macosArm64 target is not used for your case, as it corresponds to the native support for MacOS.

To have a specific code running for MacOS, you need to check the running OS from Java, and you can do so by checking the property os.name by calling:

System.getProperty("os.name")

Or you can also use a third library that does the check for you like Apache's commons-lang one.

Note 1: with the above in mind, you won't be able to access MacOS native APIs directly, you'll need some sort of interface to get to them, which can either be JNI or something simpler like JNA.

Note 2: there is an experimental support for native MacOS apps using Compose Multiplatform, but I never tested it, if you want to give it a try, you can do so by adding the line org.jetbrains.compose.experimental.macos.enabled=true to the gradle properties, then adding the main function to your macosArm64 target.

Upvotes: 4

Related Questions