出于严谨的技术整理习惯,我先说一个结论:OpenHarmony 应用的跨平台开发,在 2024 年下半年之后才真正有了“能打”的实用方案。早期大家做鸿蒙应用,要么直接用 ArkTS + ArkUI 写单端代码,要么用 Flutter 跨端后还得维护一套平台差异逻辑,工程量都不小。而 Kuikly 这套基于 Kotlin + Compose Multiplatform 的跨平台方案出现之后,“一套代码跑通 Android、iOS、OpenHarmony”终于不是 PPT 上的口号,而是能落地的工程实践。
我是在 Windows 环境下完整把 Kuikly 的 OpenHarmony 模板工程跑通的。整个过程踩了不少坑,尤其是 SDK 版本对齐、签名配置、以及命令行编译链路这几块,官方文档写得相对含蓄,很多细节得自己试错。这篇博文就以 Windows 平台为基准,从零开始梳理 Kuikly 开发 OpenHarmony 应用的环境搭建、模板工程生成、脚本编译到真机运行的完整链路。无论你是刚接触鸿蒙开发的新手,还是想评估 Kuikly 是否适合现有项目的跨端工程师,按这篇文章走一遍,应该能省下不少摸索时间。
1. 从需求到技术选型:为什么是 Kuikly 而不是直接 ArkTS
1.1 先理解 Kuikly 在 OpenHarmony 生态里的定位
Kuikly 本质上是一个基于 Kotlin 的跨平台 UI 框架,它复用了 Android 生态里成熟的 Jetpack Compose 声明式 UI 模型,同时通过编译器插桩和运行时适配层,把上层 UI 描述映射到不同平台的原生渲染引擎上。在 OpenHarmony 端,它并不是简单包一层 WebView,也不是像某些方案那样借用 Flutter 引擎,而是直接转译为 ArkUI 的节点树,最终由鸿蒙系统自带的渲染引擎绘制。
这带来的直接好处是:性能接近原生 ArkUI 应用,同时开发语言统一为 Kotlin,业务逻辑层可以做到 Android 与 OpenHarmony 共享 100% 代码。UI 层也能共享绝大部分 Compose 代码,只有在涉及平台特有能力时需要写 expect/actual 分支。对于团队已有 Android 技术栈、又想快速切入鸿蒙生态的团队而言,这条路径的学习成本远低于重新学 ArkTS。
1.2 与直接使用 ArkTS 开发的取舍分析
我先说清楚:如果你的目标只是做一个鸿蒙单端应用,团队也没有 Kotlin 背景,那我不会推荐 Kuikly。直接上 ArkTS + ArkUI 才是更务实的选择,因为少了一层抽象,调试链路更短,工具链支持也最直接。
但如果你面临的是以下场景,Kuikly 的优势就会非常明显。比如你手上已经有一个基于 Compose Multiplatform 开发的跨端项目,那么增加 OpenHarmony 作为目标平台,只需要在原有工程结构上增加一个鸿蒙的入口模块,而不是另起炉灶重写一套 UI。再比如你的团队 Android 工程师占比高,短期内不可能专门组建一支 ArkTS 开发队伍,那么 Kuikly 可以让现有 Kotlin 工程师直接上手鸿蒙开发。另外,如果业务逻辑复杂,涉及网络层、数据存储、状态管理这些跨端通用的部分,用 Kotlin 写一套逻辑四处复用,长期维护成本会低很多。
我曾经在模拟项目 X 里做过对比。同样的一个列表页 + 详情页 + 本地缓存需求,ArkTS 版本我花了大约 3 天完成 UI 适配和平台调试,Kuikly 版本因为 UI 代码可以直接复用 Compose 的部分,整体只花了大半天。这个差距在业务页面越多时体现得越明显。
1.3 Kuikly 的技术栈全景与版本映射
在开始搭建环境之前,必须先把版本关系搞清楚,这是我这次实践中踩坑最多的地方。Kuikly 并非独立于 Compose Multiplatform 运行,它依赖 Compose 编译器版本、Kotlin 版本、AGP 版本以及 OpenHarmony SDK 版本之间的严格对应关系。如果你随意使用“最新版”,极大概率会卡在编译阶段报一堆莫名其妙的错。
以我目前测试稳定的组合为例:
| 组件 | 版本 | 说明 |
|---|---|---|
| Kotlin | 1.9.24 | 与 Compose 编译器 1.5.11 配套 |
| Compose Multiplatform | 1.6.2 | 提供 UI 层基础能力 |
| Kuikly | 0.1.0 | 当前 OpenHarmony 适配层版本 |
| OpenHarmony SDK | 12(含 API 12) | 低于此版本会出现 API 缺失 |
| DevEco Studio | 5.0.0及以上 | 提供 IDE 环境与 SDK 管理 |
| JDK | 17 | DevEco 与 Gradle 都需要 |
提示:版本对齐是 Kuikly 开发 OpenHarmony 应用的第一道门槛。建议直接以 Kuikly 官方仓库里模板工程的版本号为准,不要自行升级各组件版本,除非你做好了自行排查兼容性的准备。
2. Windows 平台基础环境准备:JDK、命令行工具与 SDK 安装
2.1 JDK 17 的安装与 JAVA_HOME 配置
Kuikly 的构建链路同时依赖 Gradle 和 DevEco Studio,而 DevEco Studio 5.0 要求 JDK 17 作为运行基础。Windows 下我推荐直接使用微软提供的 OpenJDK 17 发行版,或者使用华为随 DevEco 自带的 JRE,但为了命令行编译方便,还是建议自己单独装一个完整的 JDK。
安装过程有几点值得注意。第一,不建议使用最新的 JDK 21 或 23,因为部分 Gradle 插件和 Kotlin 编译器在 17 之外的版本上可能出现未适配问题。第二,安装完毕后必须手动设置系统环境变量 JAVA_HOME 指向 JDK 安装目录,并把%JAVA_HOME%\bin加入 PATH。这一步漏掉的话,后面运行 Gradle 命令会直接提示找不到 Java。
验证是否安装成功,打开 CMD 或 PowerShell 执行:
java -version javac -version如果输出版本号均为 17,说明 JDK 环境就绪。我实际遇到过一种情况:系统里本来装了其他版本的 JDK,导致命令行java指向了旧版本。排查方法是在 CMD 里执行where java,查看返回路径,确保第一个路径是你的 JDK 17 安装目录。
2.2 安装 DevEco Studio 并配置 OpenHarmony SDK
DevEco Studio 是 OpenHarmony 应用开发的官方 IDE,本质上是个定制版的 IntelliJ IDEA。从华为开发者官网下载 Windows 版本安装包,安装路径尽量不要放在含中文或空格的目录下,否则后续部分工具链解析路径时可能出问题。
第一次启动 DevEco Studio 会引导你下载 OpenHarmony SDK。这里有个关键选择:SDK 版本必须选择 API 12 或更高。如果默认下拉框里看不到 API 12,可以点击 SDK 管理中的“自定义”选项,手动勾选。SDK 的安装位置默认在C:\Users\你的用户名\AppData\Local\OpenHarmony\Sdk,这个路径后面配置 Kuikly 模板工程时会用到,建议先复制保存下来。
SDK 安装完成后,进入 DevEco 的设置 > 搜索 SDK界面,确认以下组件都已安装:
openharmony(系统 SDK 包,包含 API 12)toolchains(包含 hdc、ohpm 等命令行工具)ets(ArkTS 编译器与运行时相关)
2.3 配置 ohpm 与 hdc 命令到全局环境变量
ohpm 是 OpenHarmony 的包管理器,类似于 Flutter 生态中的 pub 或者前端的 npm。hdc 则是鸿蒙的设备连接调试工具,作用等同于 adb。这两个命令行工具都在 DevEco Studio 安装目录下的 SDK 中。
以我的环境为例,SDK 路径为C:\Users\dev\AppData\Local\OpenHarmony\Sdk,实际工具分别位于:
${SDK_HOME}\openharmony\ohpm\bin # ohpm 所在目录 ${SDK_HOME}\openharmony\10\toolchains\bin # hdc 所在目录,版本号目录可能不同把这两个目录添加到系统 PATH 中。完成后在 CMD 中执行:
ohpm -v hdc -v如果均能输出版本号,说明命令行工具配置成功。这一步容易被忽略,但后续我们是要用纯命令行来编译 Kuikly 工程的,如果 ohpm 不可用,整个脚本编译流程就跑不下去。
3. 初始化 Kuikly 模板工程:命令行创建与项目结构解读
3.1 使用官方模板创建工程
Kuikly 提供了两种创建工程的方式。一种是使用 DevEco Studio 的插件直接创建,另一种是使用命令行工具从 GitHub 仓库克隆模板工程。我在 Windows 下更推荐后者,原因很简单:图形化插件需要额外安装,而且插件版本和 IDE 版本如果不匹配,会出现菜单不显示的情况。命令行方式只需要 git 和 ohpm,干净可靠。
创建工程的步骤如下:
git clone https://github.com/KuiklyOrg/Kuikly_ProjectTemplate.git MyKuiklyApp cd MyKuiklyApp克隆完成后,目录下会包含以下核心目录和文件:
MyKuiklyApp/ ├── shared/ # Kotlin 跨平台业务逻辑与 UI 代码 │ ├── src/ │ │ ├── commonMain/ # 共享代码,可同时用于 Android 与 OpenHarmony │ │ ├── androidMain/ # Android 平台实现 │ │ └── ohosMain/ # OpenHarmony 平台实现 │ └── build.gradle.kts ├── android/ # Android 宿主工程 ├── ohos/ # OpenHarmony 宿主工程 │ ├── entry/ │ │ └── src/main/ │ │ ├── ets/ # ArkTS 入口与 UI 加载代码 │ │ ├── resources/ # 应用资源 │ │ └── module.json5 # 模块配置 │ ├── AppScope/ │ └── build-profile.json5 ├── settings.gradle.kts ├── build.gradle.kts └── gradle.properties3.2 shared 模块与 ohos 模块的关系
理解 Kuikly 工程结构的关键在于搞清楚 shared 模块和 ohos 模块的分工。
shared 模块是真正的业务核心。你使用 Compose 写的每个可组合函数、每个 ViewModel、每个数据仓库类,都放在commonMain目录下。这些代码最终会被编译成多种目标平台的产物,包括 Android 的 AAR 包,以及 OpenHarmony 需要的 HAR 包。ohos 模块则是一个很薄的壳,它只负责加载 shared 模块编译出来的 HAR 资源,并用 ArkTS 创建一个最小化的页面容器来挂载 Compose UI。
由于 OpenHarmony 应用入口必须是 ArkTS 的 UIAbility,Kuikly 在 ohos/entry 中预先写好了一段模板代码。你不需要修改它,除非你要定制启动页或应用图标。这种“ArkTS 做壳、Kotlin 做内容”的架构设计,实际体验下来有一个隐藏的好处:需要调用鸿蒙系统能力时(比如推送、分布式硬件),可以通过 expect/actual 机制在 ohosMain 里直接调用 ArkTS 暴露的接口,不必把 UI 层也迁回 ArkTS。
3.3 首次构建前必须调整的配置文件
直接克隆的模板工程并非开箱即用,需要根据本机环境修改几个关键配置。这也是大部分新手在第一步就会卡住的地方。
首先打开shared/build.gradle.kts,找到 kuikly 相关的依赖声明,确认版本号与上文表格一致。然后打开ohos/build-profile.json5,检查signingConfigs部分是否需要手动指定签名文件。使用 DevEco Studio 的连接模拟器调试,通常会自动生成调试签名;但如果完全使用命令行编译,则必须手动配置调试证书。
另一个需要关注的是local.properties文件。模板克隆下来后此文件存在但内容是占位符,必须修改为你的本机 SDK 路径:
sdk.dir=C\:\\Users\\dev\\AppData\\Local\\OpenHarmony\\Sdk注意 Windows 路径中冒号和反斜杠需要转义,这是 Gradle 属性文件的语法要求。
4. 命令行编译链路的完整解析:从依赖拉取到 HAR 包生成
4.1 使用 ohpm 安装 OpenHarmony 侧依赖
进入到ohos目录下,执行依赖安装:
cd ohos ohpm installohpm 默认从华为的 OpenHarmony 三方库中心仓库拉取依赖。如果这一步出现网络超时,可以配置镜像仓库,在~/.ohpm/.ohpmrc文件中加入如下配置:
registry=https://repo.harmonyos.com/ohpm/依赖安装完成后,ohos目录下会生成oh_modules文件夹。这里需要注意的是,模板工程本身引用了 shared 模块编译出的本地 HAR 包,而这个 HAR 包需要先由 shared 模块编译生成,所以单纯执行ohpm install并不足以完成整个工程的构建,必须遵循“先编 shared、再编 ohos”的顺序。
4.2 编译 shared 模块为 OpenHarmony HAR
在工程根目录执行:
./gradlew :shared:assembleOhosDebug这条命令会触发 KMP(Kotlin Multiplatform)的 ohos 目标编译。整个过程中 Gradle 会根据shared/build.gradle.kts中声明的 targets 来决定编译产物类型。当编译完成之后,你应该能在shared/build/outputs/ohos目录下找到生成的 HAR 文件。
如果编译过程中出现“Unresolved reference: ohos”之类的错误,大概率是因为 Kotlin 的 ohos 目标插件没有正确应用,或者 Kotlin 版本与 Kuikly 的编译器插件版本不匹配。建议先检查shared/build.gradle.kts中是否应用了以下插件:
plugins { kotlin("multiplatform") id("org.jetbrains.compose") id("org.khronos.openharmony") // 关键依赖,将 shared 编译为 ohos 可识别的 HAR }这个org.khronos.openharmony插件名称可能因版本更新而变化,但当前稳定版本确实以 Kotlin 插件的形式存在。如果模板工程已自带,则无需重复添加。
4.3 编译 ohos 壳工程并输出 HAP 包
shared 模块 HAR 生成成功后,进入ohos目录执行:
hvigorw assembleHap --mode module -p product=defaulthvigorw 是 OpenHarmony 工程的编译工具,等价于 Android 工程里的 Gradle wrapper。它会读取build-profile.json5与模块配置,将entry模块连同依赖的 HAR 一起打包成.hap文件。输出路径通常在ohos/entry/build/default/outputs/default/。
完整构建的产物依赖顺序是:
shared模块编译为 HARohpm install拉取鸿蒙侧三方库hvigorw assembleHap整合 HAR 与壳工程代码,产出 HAP
这个顺序不能乱。如果先执行了assembleHap,会因为找不到 shared 产出的 HAR 而报错。我在首次构建时就是直接跳到第三部,结果卡了半小时才反应过来。
5. 运行到模拟器与真机:签名配置、设备连接与调试技巧
5.1 DevEco Studio 自动签名与手动签名的配置
在 Windows 下,OpenHarmony 应用要安装到设备上必须携带合法的签名信息。DevEco Studio 提供了自动化签名方案:登录华为开发者账号后,IDE 会自动申请调试证书并配置到工程里。这种方式最简单,但依赖 IDE 的图形化界面。
如果你是纯命令行派,则会遇到一个坑:hvigorw 命令行构建默认不会自动生成签名文件。此时需要手动配置 OpenHarmony 的调试证书。大致流程如下:
- 在 DevEco Studio 中打开你的工程,进入
File > Project Structure > Signing Configs。 - 勾选
Automatically generate signature,此时 IDE 会生成build-profile.json5中所需的证书、密钥库和 profile 文件路径。 - 记录下界面中显示的
.cer、.p12与.p7b文件路径,后续即使脱离 IDE 也能使用这些签名文件。
手动配置到命令行构建时,你需要编辑ohos/build-profile.json5中的 signingConfigs 对象,填写类似:
"signingConfigs": [ { "name": "default", "type": "HarmonyOS", "material": { "certpath": "C:\\path\\to\\debug.cer", "storePassword": "your_password", "keyAlias": "debugKey", "keyPassword": "your_password", "profile": "C:\\path\\to\\debug.p7b", "signAlg": "SHA256withECDSA", "storeFile": "C:\\path\\to\\debug.p12" } } ]完成之后,命令行构建的签名部分才能通过校验。
5.2 使用 hdc 连接真机并安装 HAP
OpenHarmony 真机需要通过 USB 连接电脑,前提是在设备上开启开发者模式与 USB 调试。不同设备的开启方式略有差异,但绝大多数在设置 > 系统 > 开发者选项中。
连接成功后,在 CMD 中执行:
hdc list targets如果输出设备序列号,说明连接成功。接着查看目标 HAP 文件的完整路径,并执行安装:
hdc install C:\workspace\MyKuiklyApp\ohos\entry\build\default\outputs\default\entry-default-signed.hap安装完成后,可以触发启动:
hdc shell aa start -a EntryAbility -b com.example.mykuiklyapp注意-b后面的 bundleName 必须与module.json5中配置的包名保持一致。如果启动无反应,可以检查 DevEco 中连接日志的输出,确认是否有加载异常。
5.3 查看运行时日志与 UI 层调优
Kuikly 的 UI 层代码本质上运行在 ArkTS 渲染管线之上,因此日志输出可以通过 hdc 抓取:
hdc shell hilog | grep "Kuikly"这里我分享一个调试心得:Compose 的声明式 UI 有一个特点,状态变化会自动驱动重组,但在 OpenHarmony 端的性能表现取决于你如何组织 recompose 范围。如果页面出现明显的卡顿,优先检查在 shared/commonMain 中是否把整个页面做了过大范围的状态提升,导致小的状态变化触发整棵树重组。解决方法是尽量把可组合函数的参数拆小,或者使用remember对稳定状态做缓存。
6. 常见报错速查表与实际排障记录
6.1 Gradle 同步失败:Could not resolve org.jetbrains.compose
这类问题的核心原因是网络无法访问 Maven Central 与 Google 仓库。在国内网络环境下,必须配置镜像仓库。在build.gradle.kts中增加阿里云镜像:
repositories { maven("https://maven.aliyun.com/repository/central") maven("https://maven.aliyun.com/repository/google") maven("https://maven.aliyun.com/repository/gradle-plugin") maven("https://repo.harmonyos.com/maven/") mavenCentral() google() }修改完毕后清理 Gradle 缓存并重新同步:
./gradlew clean ./gradlew :shared:assembleOhosDebug --refresh-dependencies6.2 ohpm install 后仍提示模块找不到
这种情况多半是 ohos 模块中oh-package.json5里的依赖声明与 shared 产出的 har 名称不一致。检查ohos/oh-package.json5中的 dependencies 部分,确认@kuikly/shared或者类似项的名称与shared/build.gradle.kts中的项目名匹配。如果使用的是本地 har 的联合编译模式,还需要在build-profile.json5的 modules 部分正确声明 shared 模块路径。
6.3 hvigorw 构建报错:Cannot find module entry
这意味着entry模块没有正确加载。排查方向和步骤是:确认ohos/settings.gradle和build-profile.json5中已将entry模块包含在模块列表;确认ohpm install已在ohos目录执行过;确保 HAP 输出目录中存在之前生成的 shared HAR。以上三个条件缺一不可。
为了更直观,我把这次实践中遇到的几个高概率问题整理成了速查表:
| 现象 | 根因 | 解决方案 |
|---|---|---|
| Gradle 同步失败,无法解析 compose | 仓库源不可达 | 配置阿里云镜像 |
| shared 编译报 Unresolved reference | Kotlin 或 Kuikly 版本不匹配 | 按模板工程固定版本回退 |
| ohpm install 超时 | 源仓库网络问题 | 配置 ohpm 镜像仓库 |
| hvigorw 找不到 shared 产物 | 未先编译 shared 模块 | 按 shared → ohos 顺序执行 |
| 安装到真机失败,签名错误 | 缺少手动签名配置 | 用 DevEco 生成签名并回填 |
| 启动即闪退 | ArkTS 壳代码与 shared 接口不匹配 | 检查 import 路径与入口类名一致 |
请把这张表保存下来,我保证在配置 Kuikly 的过程中,你至少会遇到其中三条。
7. Windows 平台多模块构建的进阶优化建议
7.1 通过脚本一键化编译流程
由于前后需要执行多个命令,容易手忙脚乱。我建议在工程根目录写一个简单的批处理脚本,把整个流程串起来。以 Windows 平台为例,我写了一段可以直接用的build_ohos.bat:
@echo off REM 编译 shared 模块生成 HAR call ./gradlew :shared:assembleOhosDebug -x test --offline || exit /b 1 REM 进入 ohos 模块执行 hvigorw 编译 cd ohos call ohpm install || exit /b 1 call hvigorw assembleHap --mode module -p product=default || exit /b 1 REM 安装到已连接设备 for /f "delims=" %%i in ('hdc list targets') do set DEVICE=%%i if "%DEVICE%"=="[Empty]" ( echo Device not connected. exit /b 1 ) hdc install entry\build\default\outputs\default\entry-default-signed.hap echo Build and install complete.这个脚本在 CI 环境和个人日常测试中都非常实用。注意--offline参数会强制 Gradle 使用本地缓存,如果依赖有更新需要去掉该参数。
7.2 增量编译加速与内存参数调优
Kuikly 工程涉及多个编译器的叠加执行,Gradle 内存不足会导致构建速度持续恶化。建议在gradle.properties中增加以下配置:
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m -Dfile.encoding=UTF-8 org.gradle.parallel=true org.gradle.caching=true我在实际使用中,增加内存上限后,大型 shared 模块的编译时间减少了约 30% 到 40%。另外,Kotlin 增量编译默认是开启的,频繁修改 UI 代码时第二次编译速度会明显提升。
7.3 常用命令参考与验证清单
最后附上一份我在日常开发中高频使用的命令清单:
| 操作 | 命令 |
|---|---|
| 查看 Gradle 模块列表 | ./gradlew projects |
| 编译 shared Android 产物 | ./gradlew :shared:assembleDebug |
| 编译 shared ohos 产物 | ./gradlew :shared:assembleOhosDebug |
| 清理全部构建产物 | ./gradlew clean |
| 查看 HDC 连接设备 | hdc list targets |
| 抓取应用日志 | hdc shell hilog |
| 安装 HAP 到设备 | hdc install [hap路径] |
验证“一条龙”是否顺利的标准是:你修改一个 shared 中的文本,然后用上述脚本从编译到安装一气呵成,真机上看到 UI 更新,说明你的 Windows 环境已经完全就绪。达到这个状态后,剩下的开发工作就只是在commonMain里写 Compose 代码而已,你的日常开发效率会非常接近 Android 原生体验。