Kotlin Multiplatform for HarmonyOS App Development
Kotlin Multiplatform enables developers to share a single Kotlin codebase across Android, iOS and the new Harmony Next OS—avoiding costly full rewrites—by converting Harmony OS TypeScript definitions to Kotlin, compiling to JavaScript or native binaries, though challenges remain in debugging, library compatibility, bundle size and threading support.
In 2023 Huawei Developer Conference, Huawei announced Harmony Next, a version of HarmonyOS that no longer maintains compatibility with AOSP and only runs native Harmony apps. This forces developers to rewrite apps for the new platform.
Bilibili started native Harmony app development and found that adapting to Harmony Next would require a complete rewrite, leading to high cost. They explored cross‑platform solutions to reuse existing code.
Mobile cross‑platform development faces high coding cost and maintenance overhead because the same business logic must be implemented separately for iOS, Android and HarmonyOS, and UI and logic are often tightly coupled.
Kotlin Multiplatform (KMP) is a JetBrains solution that allows a single Kotlin codebase to target multiple platforms (mobile, frontend, backend, embedded). KMP uses the Kotlin K2 compiler with a front‑end that parses source code into an AST, performs semantic analysis, and generates an intermediate representation (IR). The back‑end then emits JVM bytecode, native binaries via LLVM, JavaScript, or WebAssembly.
KMP projects are organized into common modules (shared code declared with expect ) and platform‑specific modules (implementations with actual ). An optional intermediate module can contain mixed code.
expect val Platform: String actual val Platform: String get() = "Android" actual val Platform: String get() = "iOS"The dynamic type enables seamless inter‑operation with JavaScript. Example:
fun whatIsDynamic(dyn: dynamic) { dyn.doSomething() println(dyn.someProp) }Coroutines simplify asynchronous programming. Kotlin/JS can convert a JavaScript Promise to a suspend function and vice‑versa:
suspend fun fetchDataFromJS(): String { val promise = js("fetchSomeData()") as Promise return promise.await() }To call HarmonyOS APIs from Kotlin, .d.ts declaration files are transformed into Kotlin declarations using tools such as Dukat or karakum. The external keyword and @JsModule annotation map the API to the corresponding Harmony module.
The typical KMP workflow for a Harmony app is:
Convert required .d.ts files to Kotlin with karakum and import them.
Write Kotlin business logic and expose it with @JsExport .
Compile the KMP project with the Kotlin/JS IR compiler to produce .js and .d.ts artifacts.
Import the generated files into the Harmony project.
Use the exported Kotlin functions directly in the Harmony code.
During the practice several issues were encountered:
Debugging is harder because JS breakpoints cannot be mapped back to Kotlin source.
Many third‑party libraries assume a Node or browser environment (e.g., window , TextEncoder ) which are absent in Harmony.
The generated .js bundle can exceed 10 MB, affecting Ark runtime performance.
Kotlin code cannot directly use ArkTS multi‑threading primitives, leading to potential UI stalls.
A possible mitigation is to compile Kotlin code to native binaries (Kotlin/Native) for Harmony, which removes the Ark runtime overhead and enables native threading via libuv, ffrt or pthread.
In summary, the experiment demonstrates that Kotlin Multiplatform can successfully reuse business‑logic code across Android, iOS and HarmonyOS, reducing development cost and improving efficiency, while also highlighting areas that need further tooling and runtime support.
Bilibili Tech
Provides introductions and tutorials on Bilibili-related technologies.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.