1. 项目定位与 DAY1 目标拆解
1.1 Kuikly-OH 是什么,为什么值得折腾
先说结论:Kuikly 是一套基于 Kotlin 的跨平台 UI 框架,写法上很接近 Compose Multiplatform,核心思路就是"用一套 Kotlin 代码,输出到 Android、iOS、Web,以及 OpenHarmony(鸿蒙生态)"。Kuikly-OH 这个分支,专门负责把 Kuikly 的应用跑在 OpenHarmony 设备上。对于本来就在 Kotlin/Java 技术栈里的团队,这是个非常现实的需求:公司要做鸿蒙版本,但不想重新养一套 ArkTS 开发团队,也不想把 UI 层完全推倒重写。Kuikly-OH 的价值就在于,至少 UI 声明、业务逻辑、状态管理这一大块可以复用。
第一次听说这个框架的人可能会问:那和华为官方推荐的 ArkTS 开发方式是什么关系?理解成"上层 UI 用 Kotlin 写,编译产物对接 OpenHarmony 的 ArkUI 能力"就行。Kuikly 自己做了抽象层,把声明式 UI 的节点树映射到 OpenHarmony 的组件体系上。这也意味着你不需要成为 ArkTS 专家,也能把页面跑起来,但最好还是了解一点 ArkUI 的基础概念,否则遇到底层组件适配问题时会抓瞎。
我个人愿意在 DAY1 就来折腾它,原因有三:第一,Kotlin 写 UI 的体验确实比某些配置式开发舒服,状态更新、事件回调都要自然很多;第二,跨平台方案如果不从"真机部署"这条链路验证,永远停留在 demo 阶段,而 Day1 恰恰就是要走通这条最难也最有价值的链路;第三,这个方向目前资料少,早踩坑、早总结,对团队后续的技术选型有直接的参考意义。
1.2 一天的路线图:从零到真机
我不打算 DAY1 就搞复杂业务,目标非常克制:把 KuiklyUI-OH 的官方模板跑通,然后在 OpenHarmony 真机上看到自己的页面。整个路线拆成四段:
- 本机搭建工具链:JDK、DevEco Studio(其实主要是取它的 SDK 和 hdc 工具)、Kuikly CLI、Gradle。
- 初始化项目:用模板生成一个 KuiklyUI-OH 工程,先在本机完成编译,确保"源码头不坏"。
- 华为云构建:在华为云上开一台 Linux 云主机,把工具链装好,代码拉上去,在云上完成 HAP 打包。这一步是为了验证"团队多人协作 + 统一构建环境"这条生产链路。
- 真机部署:用 hdc 连接 OpenHarmony 设备,把 HAP 装上、拉起应用,确认 UI 渲染正常。
这四段是依次依赖的,前一段不通过就别往下走。我特别想强调一点:DAY1 的交付物不是"能跑的代码",而是"一条可复现的部署路径"。代码写得多漂亮是后面的事,今天能够把链路完整走通,就已经值回票价了。
1.3 技术选型的几个关键判断
选型层面的几个判断也提一下,方便你理解为什么是这套组合。目标设备我选的是 OpenHarmony 真机,因为 Kuikly-OH 对应的就是 OpenHarmony 适配分支,手机上需要用支持 OpenHarmony 的版本或者开发板、以及开放了开发者模式的设备来验证。
构建机选华为云而不是本地直接打包,主要考虑三点。一是环境一致性:本地机器每个人的 JDK、SDK、系统库都可能不一样,团队协作时"在我电脑上能跑"就是最大的坑,云上统一标准后,问题少一大半。二是可扩展性:后面如果要接 CI/CD,这套云环境就是现成的构建节点。三是成本可控:按量付费,白天用晚上释放,不需要养一台闲置服务器。
有一点要提前说:你可能会看到有人说直接把 DevEco Studio 装到云主机上,通过图形界面操作。我建议 DAY1 不要走这条路,云主机就用命令行工具链,一切指令化。这样既方便脚本化,也避免给云主机装完整 IDE 拖慢性能。后续如果你的团队需要 IDE 远程开发,再单独做环境也不迟。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 本机环境搭建:从 JDK 到 DevEco Studio
2.1 工具链清单与版本搭配
开始动手前,先把工具链版本敲定。以下组合是我实测下来比较稳的,不敢说是唯一标准,但能帮你避开很多兼容性坑:
| 工具 | 版本建议 | 说明 |
|---|---|---|
| JDK | 17(64 位) | Gradle 8.x 对 JDK 17 支持最好 |
| Gradle | 8.x | 项目自带 wrapper,建议以 wrapper 为准 |
| DevEco Studio | 5.x 及以上 | 安装主要是为了拿 OpenHarmony SDK 和 hdc |
| OpenHarmony SDK | API 12 及以上 | 在 DevEco Studio 的 SDK Manager 里勾选 |
| Node.js | 18+ | 部分 CLI 和前端工具链会用到 |
| Git | 最新稳定版 | 代码版本管理,后面上云要用 |
这里有个很容易踩的坑:JDK 版本太新也会有问题。我之前在 JDK 21 上跑过部分 KMP/Compose 相关工程,不少插件和编译器任务会报一些奇怪的反射警告甚至直接失败。所以 DAY1 阶段不要追求"版本越新越好",而是"版本越稳越好"。JDK 17 就是目前 Kotlin 跨平台生态最安全的中间档位。
DevEco Studio 的安装包比较大,下载时保持耐心。装完以后不需要天天打开 IDE,我们真正需要的是它的 SDK 目录和 hdc 工具。如果你本机空间紧张,甚至可以考虑单独下载 OpenHarmony 的命令行 SDK,但我更推荐先完整装一次 DevEco Studio,因为后续调试真机时它的 Device 面板、日志面板还是很好用的。
2.2 环境变量配置细节
环境变量这一步很基础,但恰恰是很多新手卡住的地方。我在 Linux/macOS 上习惯写到 ~/.bashrc 或 ~/.zshrc,Windows 上就是在"系统属性-环境变量"里加。核心变量如下:
bash复制# JDK
export JAVA_HOME=/path/to/jdk-17
export PATH=$JAVA_HOME/bin:$PATH
# DevEco / OpenHarmony SDK
export DEVECO_HOME=/path/to/devecostudio
export HOS_SDK_HOME=$DEVECO_HOME/sdk
export PATH=$HOS_SDK_HOME/command-line-tools/bin:$HOS_SDK_HOME/openharmony/toolchains:$PATH
# hdc 工具,重点确认这个能用
export PATH=$HOS_SDK_HOME/openharmony/toolchains:$PATH
配置完以后,打开新的终端窗口逐项验证:
bash复制java -version
gradle -v
hdc -v
如果 hdc 命令找不到,先别急着百度,直接用绝对路径去看文件是否存在。常见的问题是你安装 DevEco Studio 时没有勾选 OpenHarmony 的 toolchains 组件,SDK 目录里缺了 hdc 相关的文件。这时候回到 SDK Manager 里补装即可,不用重装整个 IDE。
还有一个细节:DevEco Studio 内置的 JRE 和我们配置的 JAVA_HOME 可能是两套,命令行构建时务必确认当前终端用的是你要的版本。多版本 JDK 混用的机器上,运行 which java 和 java -version 是基本操作。
2.3 脚手架初始化 KuiklyUI-OH 项目
工具链就绪后,用 Kuikly 的脚手架生成项目。如果你拿到的是库源码或模板仓库,直接 clone 也行。我这里以 CLI 方式演示,命令结构大致如下:
bash复制kuikly-cli create app --name day1-demo --package com.example.day1demo
执行后,CLI 会问你选哪些目标平台,记得勾上 ohos(OpenHarmony)。如果 CLI 版本的交互参数和你看到的不一样,直接执行 kuikly-cli create --help 看当前支持的命令行参数,按提示来就行——这类脚手架工具更新频繁,以本机实际版本为准是最省事的。
生成后的项目结构大致是这样的(KMP 风格):
text复制day1-demo/
├── build.gradle.kts
├── settings.gradle.kts
├── gradle/
├── commonMain/ # 共享代码:UI、业务逻辑
│ ├── kotlin/
│ └── composeResources/
├── androidMain/ # Android 平台工程
├── ohosMain/ # OpenHarmony 平台工程
├── iosMain/ # iOS 平台工程
└── kuikly-ohos/ # Kuikly 提供给 OH 的适配层依赖配置
第一次同步 Gradle 依赖会非常慢,尤其是在国内网络环境下。我建议提前在 ~/.gradle/init.gradle 或项目 settings.gradle.kts 里配置阿里云 Maven 镜像,能省下大量时间。镜像配置是个常规操作,把仓库地址替换为镜像地址就行,下面给我常用的写法:
kotlin复制// settings.gradle.kts
pluginManagement {
repositories {
maven("https://maven.aliyun.com/repository/public")
maven("https://maven.aliyun.com/repository/google")
maven("https://maven.aliyun.com/repository/gradle-plugin")
google()
mavenCentral()
gradlePluginPortal()
}
}
依赖同步完成后,先不急着写业务代码,直接尝试本机构建。这一步的目的不是产出安装包,而是确认工程本身没问题。我会在下一节详细展开构建命令和配置要点。
3. 跨平台工程结构与 OpenHarmony 接入
3.1 工程目录里的几个关键模块
很多第一次接触 Kuikly-OH 的人会被多模块目录吓到,觉得比单一应用工程复杂太多。其实拆开看就三类东西。
第一类是共享代码,集中在 commonMain。你绝大部分 UI 代码、ViewModel 逻辑、数据请求都写在这里。它是整个工程的核心,也是跨平台复用的价值所在。第二类是平台目录,比如 androidMain 和 ohosMain。这里放的代码非常少,基本就是入口注册、平台相关初始化、偶尔要做的平台差异适配。第三类是 Gradle 模块配置,像 kuikly-ohos 这种适配层依赖,通常以源码模块或 Maven 依赖的形式存在。它的任务是把 commonMain 的声明式 UI 树转换成 OpenHarmony 的 ArkUI 组件树。
理解这个分层后,你写页面时的思考方式就应该固定在"我是在写 commonMain 的共享 UI",而不是"我在写 OpenHarmony 应用"。除了性能敏感或者必须调用系统能力的场景,绝大多数情况下你不需要碰平台代码。
3.2 用 Compose 心智写 OpenHarmony UI
Kuikly 的 UI 写法对熟悉 Compose 的人非常友好。下面的代码就是一个最基本的页面:
kotlin复制@Composable
fun Day1Screen() {
var count by remember { mutableStateOf(0) }
Column(
modifier = Modifier.fillMaxSize().padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "Kuikly-OH DAY1",
style = TextStyle(fontSize = 24.sp, fontWeight = FontWeight.Bold)
)
Text(
text = "点击次数: $count",
style = TextStyle(fontSize = 16.sp)
)
Button(onClick = { count++ }) {
Text("点我")
}
}
}
看到 @Composable、Modifier、remember、mutableStateOf 这些关键字,你就知道心智模型完全一致。状态变了,UI 自动更新;不需要手动操作组件实例;没有 findViewById 那套东西。
把这个页面注册到 OpenHarmony 侧时,通常在 ohosMain 里写一个入口。大致是这样:
kotlin复制class EntryAbility : KuiklyAbility() {
override fun onCreate() {
super.onCreate()
enableAbility(this, "EntryAbility")
setContent {
Day1Screen()
}
}
}
这里的 KuiklyAbility 是 Kuikly-OH 提供的能力基类,它会完成 OpenHarmony 生命周期与 Kuikly 渲染引擎的桥接。你只管在 setContent 里告诉它"首屏长什么样"。
3.3 构建产物与 HAP 打包
构建 OpenHarmony 应用的产物是 HAP 文件,这是 OpenHarmony 的应用安装包格式,可以类比成 Android 的 APK。执行构建时,切换到工程根目录运行:
bash复制./gradlew :kuikly-ohos:assembleHapDebug
如果这个 task 名字不完全一致(不同版本可能叫 assembleHap 或者 packageHap),可以先跑 ./gradlew :kuikly-ohos:tasks 查看所有可用的构建任务。我不建议闭着眼睛照抄命令,学会自己查任务列表是这次实战应该掌握的技能。
构建完成后,产物一般出现在类似这样的目录:
text复制kuikly-ohos/build/outputs/hap/debug/kuikly-ohos-debug.hap
看到文件生成,说明本机的编译链路已经通了。如果卡在这一步,优先检查三点:Gradle 依赖是否全部下载成功、SDK 版本与工程要求的 API Level 是否匹配、Kotlin 编译器插件版本是否和 Kuikly 版本配套。大多数编译错误,日志里会直接指出是谁的问题,不要只看报错红色部分,往上多翻几行看是哪个模块、哪个依赖引起的。
3.4 配置清单里的注意力
OpenHarmony 工程里有个重要的配置文件 module.json5,相当于 Android 的 AndroidManifest.xml。它声明了应用的包名、入口 ability、权限等。Kuikly 模板生成的工程通常已经给你填好了半成品,但有几个字段你最好自己过一遍。
第一个是包名,要和你在 Gradle 里配置的 applicationId 保持一致,否则安装后可能出现无法拉起的问题。第二个是入口 ability 的名称,如果你在 ohosMain 里重命名了 EntryAbility,这里也要同步改。第三个是权限声明,DAY1 这个 demo 可能不需要太多权限,但如果涉及网络请求,记得加:
json5复制{
"module": {
"name": "entry",
"type": "entry",
"deviceTypes": ["phone"],
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ts",
"launchType": "singleton"
}
],
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
有些权限(比如 INTERNET)在调试模式下可能默认不限制,但是一旦要上真机做网络请求,缺失权限会表现为"请求失败但代码看不出问题",这类问题排查起来很费时间。所以从一开始就把配置声明完整,是个好习惯。
4. 华为云构建环境与真机部署实战
4.1 华为云上搭建远程构建机
本机编译通过以后,就可以把战场转移到华为云了。我选择的方案是:一台 Linux 弹性云服务器(ECS),按需购买,地域就近选择,操作系统选 Ubuntu Server 22.04 LTS,配置 2 核 4GB 起步。这个配置做命令行构建足够,不需要上图形界面,所以也不用买高配机型。
创建完实例后,第一件事是更新系统并安装基础工具:
bash复制sudo apt update && sudo apt upgrade -y
sudo apt install -y git unzip curl
然后安装 JDK 17。Ubuntu 源里直接有 OpenJDK 17,执行下面命令即可:
bash复制sudo apt install -y openjdk-17-jdk
java -version
接下来把 DevEco Studio 的命令行 SDK 传到云主机。有两种方式:一是本地把 DevEco Studio 安装目录下 sdk 目录打压缩包,然后通过 scp 传到云主机;二是在云主机上直接下载官方提供的命令行 SDK 包。我个人倾向第一种,因为版本和本地完全一致,避免"本地能出包、云端出包却版本对不上"的尴尬。命令大致这样:
bash复制scp -r devecostudio/sdk user@your-ecs-ip:/opt/
SDK 的安放目录建议固定在 /opt 或者 /usr/local,权限设为当前用户可读写。然后编辑 .bashrc 添加环境变量,配置方式和本机一致。这里有一个细节:云主机上不需要安装完整 DevEco Studio IDE,只要 SDK、hdc 和构建链相关的命令行工具能用即可,这样既省磁盘又省内存。
4.2 部署链路设计
为什么要绕这么一圈在云上构建?很多同学不理解。本地生成 HAP 后直接 adb/hdc 安装到手机,不是更快吗?如果只是自己一个人开发,确实本地一条龙更快。但放到团队协作、后续引入 CI/CD 的场景看,情况就不一样了。
统一构建环境的收益在跨平台工程里体现得尤其明显。KMP/Kuikly 这类工程对 Gradle 版本、JDK 版本、依赖仓库极其敏感,两个人机器配置不同,构建结果可能就不一样。把构建放到华为云上,等于给大家发了一把尺子,所有人用同一把量。再加上云主机按需调度,构建任务跑完就释放,成本也不高。后续完全可以在这个环境上继续接流水线,让每次提交都自动产出 HAP。
链路设计上,我推荐的拓扑是:本地 Git 仓库 → 华为云 ECS(构建机)→ OpenHarmony 真机(hdc 连接)。构建机从 Git 拉代码、执行 Gradle 构建、产出 HAP,然后通过 hdc 直接把 HAP 推到真机安装。如果你手里的 OpenHarmony 设备和构建机不在同一个网络,可以考虑给设备做端口映射,或者把构建机放到和设备同一内网,确保 hdc 能访问到设备的 5555 调试端口。
4.3 真机连接与安装运行
OpenHarmony 设备连接云主机,用 hdc 工具。首先在设备上开启开发者模式,并打开 USB 调试或网络调试(具体入口在不同系统版本上略有差异,一般都在"设置-关于设备"里连点版本号开启开发者选项,然后在开发者选项里打开调试开关)。如果设备通过 USB 连接本地电脑,可以先用本地 hdc 验证设备能被识别:
bash复制hdc list targets
如果你的真机只能在远程网络里访问,云主机上可以用 hdc tconn 建立连接:
bash复制hdc tconn <device-ip>:5555
hdc list targets
连接成功后,直接安装云上构建出来的 HAP 包:
bash复制hdc install /path/to/kuikly-ohos-debug.hap
安装成功后再用 hdc 拉起应用:
bash复制hdc shell aa start -a EntryAbility -b com.example.day1demo
这里 -b 后面跟的是 bundleName,也就是 module.json5 里配置的包名,不是 applicationId 的格式,注意别混淆。如果你不确定 bundleName,可以通过 hdc shell bm dump 查设备上已安装的应用列表,从里面找到对应的名字。
正常跑起来以后,你会看到 Kuikly 默认页面或你自己写的 Day1Screen 出现在屏幕上。这一刻,DAY1 最核心的目标就算完成了。
4.4 从代码提交到设备运行的完整流程
为了让这套流程更有复用价值,我建议把部署步骤固化成脚本,放进工程目录下的 scripts/ 里。下面是一个简单的 deploy.sh 示例,参数根据自己环境改:
bash复制#!/bin/bash
set -e
BUNDLE_NAME="com.example.day1demo"
HAP_PATH="$(pwd)/kuikly-ohos/build/outputs/hap/debug/kuikly-ohos-debug.hap"
DEVICE_IP="${1:-192.168.1.100}"
echo "==> Building HAP"
./gradlew :kuikly-ohos:assembleHapDebug
echo "==> Connecting device $DEVICE_IP"
hdc tconn "$DEVICE_IP":5555
echo "==> Installing HAP"
hdc install "$HAP_PATH"
echo "==> Starting app"
hdc shell aa start -a EntryAbility -b "$BUNDLE_NAME"
echo "==> Done"
把脚本保存后,记得执行 chmod +x scripts/deploy.sh。以后每天开发时,改完代码直接跑 ./scripts/deploy.sh <设备IP>,一条命令完成"构建 → 安装 → 启动"。这个小小的自动化操作,能省掉大量重复劳动,也让团队新人更快上手。别把这当"加分项",这应该成为默认习惯。
5. 常见问题与排查技巧实录
5.1 环境类问题速查表
DAY1 最容易卡住的往往不是代码本身,而是环境问题。下面这个表是根据我实际踩坑总结出来的,优先级从高到低排列:
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
hdc 命令找不到 |
DevEco SDK 未完整安装,或 PATH 未包含 toolchains 目录 | 检查 SDK 目录,补充 PATH,重新打开终端 |
| Gradle 同步极慢或失败 | 依赖从国外仓库拉取 | 配置阿里云 Maven 镜像 |
| 编译报 JDK 版本不支持 | JDK 版本过高或过低 | 统一使用 JDK 17 |
| DevEco Studio 打不开 | 安装包损坏或系统要求不满足 | 确认操作系统版本,重新安装 |
环境类问题有个特点:报错信息往往不是直接告诉你"环境变量少了",而是抛一个莫名其妙的编译异常。所以排查时第一步永远先确认基础命令是否正常:java -version、gradle -v、hdc -v。这三个命令能跑通,一半的环境问题就已经排除了。
5.2 构建类问题
构建时报错主要集中在 Kotlin 编译器插件、依赖冲突、SDK 版本不匹配这三类。有一个高频问题:你拉取的 Kuikly 版本要求某个特定版本的 OpenHarmony SDK,但云主机或本机安装的 SDK 版本对不上,构建时出现类似 Unable to resolve the OHOS SDK 的提示。
解决办法很直接:对比工程里 ohos-sdk 相关的 Gradle 配置和本机 SDK 的实际版本,强制保持一致。如果确实本地 SDK 版本偏旧,就在 SDK Manager 里升级;如果工程里的 API Level 设置得太激进,也可以先把 compileSdkVersion 降到匹配的版本。我的建议是前三种配置(compileSdk、minSdk、targetSdk)最好都用工程默认值,除非你明确知道自己在干什么。
另外一个容易忽略的点是 Gradle 缓存。很多时候你改了依赖版本,构建却还在用旧的缓存产物,导致"改了一点用都没有"。遇到这种诡异情况,先试试:
bash复制./gradlew clean
./gradlew :kuikly-ohos:assembleHapDebug --refresh-dependencies
5.3 真机部署类问题
真机部署阶段的问题,一半出在连接上,一半出在签名和包名上。
连接类问题最常见的是 hdc tconn 卡住或者连不上。排查步骤:
- 确认设备和构建机网络互通:
ping <device-ip> - 确认设备 5555 端口可达:用
nc -zv <device-ip> 5555或telnet <device-ip> 5555 - 确认设备开发者模式和网络调试已打开
- 重新执行
hdc tconn <device-ip>:5555
安装类问题则集中在 install failed。最常见原因是应用已经存在但签名不一致。处理方式:先卸载旧应用,再重新安装:
bash复制hdc uninstall com.example.day1demo
hdc install /path/to/hap
还有一个小细节:如果你同时连着多个设备,hdc 会不知道操作哪一台。先执行 hdc list targets 看设备列表,然后可以用 hdc -t <device-id> 指定目标设备,避免"明明连了设备却说找不到目标"。
5.4 几个值得长期记住的操作心得
DAY1 走下来,我最大的感受是:跨平台开发的坑不在"写代码",而在"对链路每个环节的理解"。说几个操作层面的心得,供后面持续开发时参考。
第一,日志是你最好的朋友。OpenHarmony 侧的应用日志用 hilog 查看。设备连接后,执行下面命令可以实时看应用日志:
bash复制hdc shell hilog | grep -i "your.bundle.name"
比起在代码里到处塞 Log,先学会过滤日志会更高效。很多运行期崩溃、页面不刷新、网络失败的问题,日志一看便知。
第二,构建产物和代码版本要对齐。云上构建时,永远基于最新提交的代码构建,本地改完一定要先 commit 再上云拉取,否则你会在排查 bug 时陷入"我明明改了为什么不生效"的困境。
第三,把环境的多样性当成预期而不是意外。团队成员之间 JDK、Gradle、SDK 不一样是常态,把标准写进 README,并用脚本固化流程,才能从根上减少沟通成本。
第四,也是最重要的:DAY1 的目标不是完美,而是闭环。哪怕页面丑一点、代码糙一点,只要从代码到真机的链路通了,后面所有优化都有抓手。这个"闭环优先"的思路,在跨平台项目里尤其管用——因为它涉及的环节太多,任何一个环节断了,你的学习热情都会被迅速磨灭。先把问题圈定在可控范围内,再逐步扩大战果,这是我做过多次跨平台落地后最真实的体会。
