本文记录
okio接入 OpenHarmony 的完整过程,覆盖 KMP/CMP 工程盘点、ohosArm64目标、Kotlin/Native 动态库、C ABI/N-API 桥接、ArkUI 真机页面、HAP 签名和真机验收。本次适配复用 Okio 的 Kotlin Multiplatform 公共 API 和 Buffer 实现,再由 OpenHarmony Stage 宿主通过 C ABI 和 N-API 调用 Kotlin/Native 动态库。这样验证的是同一份 KMP 代码在 OpenHarmony ARM64 设备上的运行结果,而不是在 ArkTS 页面中重新实现一套字符串处理逻辑。
项目地址:AtomGit/oh-tpc/okio
开发工具:华为云码道
一、背景
1.1 为什么做开源鸿蒙平台 KMP/CMP 适配
Okio 是 Kotlin 生态中用于字节流、缓冲区、文件系统和数据处理的基础库。KMP/CMP 应用通常把业务和数据处理放在commonMain,再由不同平台提供底层实现。要让 OpenHarmony 应用继续使用同一套 Okio API,关键是让核心库真正进入ohosArm64Kotlin/Native 运行时,并完成从 Native 到 ArkUI 的调用链路。
如果只在 ArkTS 页面中拼接一个“通过”文本,无法证明 Okio 的Buffer、UTF-8 编解码和 Kotlin/Native 内存边界已经工作。完整适配需要解决下面几个问题:
| 障碍 | 具体问题 |
|---|---|
| 目标缺失 | KMP 模块默认没有 OpenHarmony 目标,必须增加ohosArm64()才能生成 OpenHarmony KLIB。 |
| 平台实现差异 | Okio 的 POSIX 文件系统代码依赖DEFFILEMODE、statx等 Unix 接口,OpenHarmony 头文件并不完全提供这些符号。 |
| 工具链不一致 | Kotlin/Native、OpenHarmony LLVM、Native SDK、CMake、Ninja 和 Gradle 插件必须使用匹配版本。 |
| 语言边界不同 | ArkTS 不能直接持有 KotlinBuffer或 Kotlin data class,需要经过 C ABI、C++ N-API 和字符串边界。 |
| 内存生命周期 | Kotlin/Native 返回的 C 字符串必须由明确的Free入口释放,否则页面反复点击会造成 Native 堆泄漏。 |
| 交付链路复杂 | Native 动态库、CMake、HAP、签名、设备安装和 ARM64 ABI 需要分别验证。 |
因此,本项目把适配边界放在三个地方:Okio 的ohosArm64平台配置、Kotlin/Native C ABI/N-API 桥接层和 ArkUI 验收页面。Okio 的公共 API 保持不变,ArkTS 只负责宿主生命周期和结果展示。
1.2 库提供的能力
本次示例使用 Okio 的基础 Buffer API 验证跨语言链路:
Buffer():创建 Okio 缓冲区;writeUtf8():把 UTF-8 文本写入缓冲区;readUtf8():从缓冲区读取完整文本;- KMP
commonMain代码:由 JVM 和ohosArm64共用; OkioExamples.checks():在共享 Kotlin 代码中返回验收结果;- Kotlin/Native C ABI:返回 JSON 字符串并提供显式释放函数。
示例的结果约定如下:
| 字段 | 示例值 | 含义 |
|---|---|---|
value | OpenHarmony / Okio | Buffer UTF-8 写入和读取后的文本。 |
checks | passed | 共享 Kotlin 验收逻辑通过。 |
示例只验证基础 Buffer 路径。文件系统、压缩、同步、Socket 和其他 Okio API 仍应结合实际业务补充专项测试。
1.3 实现适配
| 维度 | 要求 |
|---|---|
| 代码复用 | Okio 的公共 API和commonMain实现继续由 KMP 管理。 |
| 平台目标 | 增加ohosArm64,生成 OpenHarmony KLIB 和libokio.so。 |
| 平台兼容 | 在ohosMain提供 OpenHarmony POSIX 兼容实现。 |
| 桥接稳定 | 使用少量 C ABI 函数和 JSON,避免把 Kotlin 对象地址交给 ArkTS。 |
| UI 完整 | 页面支持 Native 调用、结果展示和错误显示。 |
| 可测试 | JVM 测试、Kotlin/Native 链接、HAP 构建、签名安装和真机页面分别验收。 |
| 签名安全 | 仓库只保留签名配置入口,证书和密钥材料由开发者本机配置。 |
| 仓库规范 | 项目说明、文章、效果图和源码链接统一使用 AtomGit。 |
本项目的 ArkUI 页面是独立的真机验收宿主,Okio 公共 API 仍然保持平台无关。CMP 应用可以在
commonMain中继续依赖 Okio,再由自己的 OpenHarmony 宿主决定 UI 和系统能力封装方式。
二、实现路线图
第 1 阶段:项目初始化 ── 盘点 Okio KMP 模块、公共 API 和 OpenHarmony 示例边界 第 2 阶段:目标与依赖打通 ── 加入 ohosArm64、独立 example 工程和 Native 构建任务 第 3 阶段:平台兼容处理 ── 增加 ohosMain,兼容 OpenHarmony POSIX 头文件差异 第 4 阶段:原生桥接 ── Kotlin/Native C ABI、C++ N-API、JSON 和内存释放 第 5 阶段:ArkUI 宿主 ── Stage 工程、CMake、资源、页面和 Native 模块注册 第 6 阶段:示例与验证 ── HAP 构建、签名、设备安装、Okio Buffer 和效果图每个阶段都使用真实产物作为下一阶段输入:先用 JVM 验证共享示例,再把 Okio 链接为 ARM64 动态库,随后由 CMake 和 N-API 加载到 Stage 工程,最后安装签名 HAP 观察页面返回结果。
三、逐步实现过程
第 1 阶段:项目初始化
1.1 盘点公共 API 和工程边界
项目采用与参考 KMP/CMP 工程一致的分层:
okio/ Okio 核心 KMP 模块 okio/src/ohosMain/ OpenHarmony 平台兼容实现 example/shared/ 共享示例门面和 JVM 验收测试 example/nativeApp/ ohosArm64 Kotlin/Native 动态库 example/ohosApp/ DevEco Stage 工程和 ArkUI 页面 scripts/ OpenHarmony Native 构建辅助脚本 docs/openharmony/ 验收记录和真机效果图example是独立 Gradle 工程,不把 DevEco 工程作为 Kotlin 子模块。这样可以分别执行 Gradle 和 Hvigor,也可以将ohosApp复制到其他目录后在 DevEco Studio 中配置签名。
1.2 固定工具链和版本矩阵
本项目使用以下版本约定:
| 项目 | 配置 | 用途 |
|---|---|---|
| Kotlin Multiplatform | 仓库libs.versions.toml中的版本 | JVM、Kotlin/Native 和 KLIB |
| OpenHarmony 目标 | ohosArm64 | ARM64 真机动态库 |
| DevEco product | 6.0.0(20) | 工程兼容和目标版本 |
| ABI | arm64-v8a | HAP 原生库架构 |
| Native 构建 | CMake + Ninja | 构建 N-API 入口和链接 Okio |
执行 Gradle 脚本前先确认 JDK 和 DevEco SDK:
java-version/Applications/DevEco-Studio.app/Contents/tools/node/bin/node\\/Applications/DevEco-Studio.app/Contents/tools/hvigor/bin/hvigorw.js--versionOpenHarmony SDK 的实际路径以本机 DevEco Studio 配置为准。工具链可用只说明工程可以编译,不能替代 ARM64 真机上的运行验证。
1.3 创建 OpenHarmony 示例目录
示例页面围绕“共享 Okio 结果、Native 调用和验收状态”组织:
标题区 KMP Okio OpenHarmony 结果区 {"value":"OpenHarmony / Okio","checks":"passed"} 操作区 运行 Okio 检查按钮调用真实的libentry.soN-API 方法,Native 方法继续调用 Kotlin/Native 导出的OkioText,而不是在 ArkTS 页面中直接写死结果。
第 2 阶段:目标与依赖打通
2.1 加入ohosArm64目标
Okio 模块在保留现有平台目标的基础上增加 OpenHarmony:
kotlin{ohosArm64()sourceSets{valohosMainbygetting{dependsOn(nonJvmMain)}}}ohosArm64继承公共 KMP 源集和非 JVM 实现,平台差异集中放在okio/src/ohosMain。JVM 和其他平台的 API 不需要因为 OpenHarmony 示例而改变。
核心目标可以单独编译:
./gradlew :okio:compileKotlinOhosArm642.2 Native focused build 的作用
example/nativeApp只负责生成受 linker map 约束的 shared library:
kotlin{ohosArm64{binaries.sharedLib{baseName="okio"linkerOpts("--entry=0","--version-script=${project.file("src/ohosArm64Main/linker/shared-library.map")}","-lace_napi.z","-luv","-lhilog_ndk.z",)}}}示例只导出两个业务相关 C ABI 符号和一个释放符号:
OkioText OkioFree减少 ABI 符号可以降低跨语言生命周期和兼容风险。Okio 的内部类、Buffer 对象和 Kotlin 运行时对象不会暴露给 ArkTS。
2.3 配置仓库和独立消费工程
example/settings.gradle.kts使用 Maven Local、Maven Central 和 OpenHarmony Kotlin 插件仓库:
pluginManagement{repositories{maven("https://maven.eazytec-cloud.com/nexus/repository/maven-public/")mavenCentral()gradlePluginPortal()}}dependencyResolutionManagement{repositories{mavenLocal()maven("https://maven.eazytec-cloud.com/nexus/repository/maven-public/")mavenCentral()}}共享示例使用 OpenHarmony 版本的 Okio:
sourceSets{commonMain.dependencies{api("com.squareup.okio:okio:3.19.0-ohos.1")}}发布到本机 Maven Local 后,也可以让独立示例消费最新构建产物:
./gradlew :okio:publishToMavenLocal-PsigningEnabled=false2.4 通过构建产物消费共享库
prepareOhos在 Native 链接成功后复制动态库和 C 头文件:
valprepareOhosbytasks.registering(Copy::class){dependsOn("linkDebugSharedOhosArm64")from(layout.buildDirectory.dir("bin/ohosArm64/debugShared")){include("libokio.so")into("libs/arm64-v8a")}from(layout.buildDirectory.dir("bin/ohosArm64/debugShared")){include("libokio_api.h")into("src/main/cpp/include")}into(rootProject.layout.projectDirectory.dir("ohosApp/entry"))}动态库和头文件来自同一次 Native 构建,避免头文件与.so版本不一致。准备完成后应存在:
example/ohosApp/entry/libs/arm64-v8a/libokio.so example/ohosApp/entry/src/main/cpp/include/libokio_api.h第 3 阶段:平台兼容处理
3.1 OpenHarmony POSIX 兼容边界
Okio 的 Unix 实现依赖系统文件模式和文件状态查询。OpenHarmony Native SDK 中部分头文件与常见 Linux/macOS 头文件不同,因此不能简单复制 Linux 实现。
本次适配采用以下边界:
| 代码 | OpenHarmony 处理 |
|---|---|
| 文件创建默认模式 | 使用等价的0666权限值,避免依赖不存在的DEFFILEMODE。 |
| 文件状态查询 | 使用lstat/stat组合实现statx所需的最小字段。 |
| 其他 Okio 公共逻辑 | 继续复用commonMain和已有平台实现。 |
兼容代码位于:
okio/src/ohosMain/kotlin/okio/OhosPosixVariant.kt这样做只解决 OpenHarmony SDK 的声明差异,不改变 Okio 对外 API,也不把 OpenHarmony 特有类型泄漏到公共源集。
3.2 平台代码的编译验证
先编译 Okio 目标:
./gradlew :okio:compileKotlinOhosArm64再链接示例动态库:
cdexample ./gradlew :nativeApp:prepareOhos --no-daemon如果平台兼容代码有错误,失败会出现在 Kotlin/Native 编译阶段;如果 C ABI、CMake 或链接器有错误,失败会出现在linkDebugSharedOhosArm64或 DevEco 的 Ninja 阶段。分别保留这两个边界,便于定位问题。
第 4 阶段:原生桥接(技术难点)
4.1 Kotlin/Native 对象不能直接交给 ArkTS
Kotlin/Native 的Buffer和 Kotlin 对象属于 Kotlin 运行时对象。ArkTS 只能接收 JavaScript 值,C++ 也不能把 Kotlin 对象地址直接当成 JavaScript 对象。
最终采用三层桥接:
ArkTS │ JSON string ▼ C++ N-API entry │ const char* ▼ Kotlin/Native C ABI │ Okio Buffer ▼ UTF-8 JSON + explicit free4.2 方案对比
| 方案 | 优点 | 缺点 | 选用 |
|---|---|---|---|
| 直接导出 Kotlin 对象 | 代码少 | ABI、生命周期和类型不可控 | ❌ |
| 只导出文本常量 | 页面调用简单 | 无法证明 Okio 实际执行 | ❌ |
| C ABI + JSON | 边界清晰、易扩展、易调试 | 有一次序列化开销 | ✅ |
| 在 ArkTS 重写 Buffer 逻辑 | 不需要 Native 桥 | KMP 和 ArkTS 逻辑容易分叉 | ❌ |
4.3 Kotlin/Native 导出函数
桥接文件位于example/nativeApp/src/ohosArm64Main/kotlin/OkioNative.kt:
@CName("OkioText")publicfunokioTextNative():CPointer<ByteVar>=response{"{\"value\":\"${OkioExamples.roundTrip()}\",\"checks\":\"${OkioExamples.checks()}\"}"}@CName("OkioFree")publicfunfreeNative(pointer:CPointer<ByteVar>?){if(pointer!=null)nativeHeap.free(pointer.rawValue)}返回值是 Native heap 分配的、以0结尾的 UTF-8 C 字符串。每一次调用都由OkioFree释放返回缓冲区,避免按钮重复点击造成 Native 堆泄漏。
4.4 C++ N-API 方法分发
C++ 入口位于example/ohosApp/entry/src/main/cpp/napi_init.cpp,注册一个okioText方法:
staticnapi_valueText(napi_env env,napi_callback_info){void*raw=OkioText();constchar*value=static_cast<constchar*>(raw);napi_value result=nullptr;napi_create_string_utf8(env,value,NAPI_AUTO_LENGTH,&result);OkioFree(raw);returnresult;}C++ 只负责调用 Native 函数、创建 ArkTS 字符串和释放 Native 缓冲区。Okio 的 Buffer 逻辑仍然位于共享 Kotlin 代码。
4.5 N-API 生命周期
ArkTS okio.okioText() │ ▼ N-API Text() │ ▼ OkioText() │ ▼ napi_create_string_utf8(...) │ ▼ OkioFree(raw) │ ▼ return JS stringN-API 不保存 Native 指针,也不把 Kotlin 对象放进全局缓存。这样页面重建或按钮多次点击时,不需要额外处理跨线程对象生命周期。
第 5 阶段:ArkUI 宿主封装
5.1 ArkTS 调用 N-API 模块
页面通过类型声明加载libentry.so:
importokiofrom'libentry.so'this.value=okio.okioText()类型声明位于:
example/ohosApp/entry/src/main/cpp/types/libentry/index.d.ts5.2 CMake 导入 Kotlin/Native 动态库
add_library(okio SHARED IMPORTED) set_target_properties(okio PROPERTIES IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/arm64-v8a/libokio.so") add_library(entry SHARED napi_init.cpp) target_include_directories(entry PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") target_link_libraries(entry PRIVATE okio libace_napi.z.so)libokio.so作为 imported library 参与entry链接,HAP 最终携带arm64-v8a原生库。若库文件未执行prepareOhos,Ninja 会报告libokio.so缺失。
5.3 ArkUI 页面状态
Index.ets保存 Native 调用结果和错误文本:
@Statevalue:string='Okio OpenHarmony'Button('运行 Okio 检查').onClick(()=>{try{this.value=okio.okioText()}catch(error){this.value=`调用失败:${String(error)}`}})页面不复制 Okio 的 UTF-8 实现,也不根据字符串内容伪造passed。结果只能来自libokio.so的 Kotlin/Native 调用。
5.4 页面交互预设
页面提供一个真实操作按钮:
- 运行 Okio 检查:触发 N-API、Kotlin/Native 和 Okio Buffer 全链路。
- 结果文本:显示 Native 返回的 JSON。
- 错误文本:显示 N-API 或 Native 异常转换后的信息。
这样页面尽量保持简单,把重点放在三方库实际功能是否通过。
第 6 阶段:示例与验证
6.1 example 工程结构
example/ ├── shared/ │ ├── src/commonMain/.../OkioExamples.kt │ └── src/commonTest/.../OkioExamplesTest.kt ├── nativeApp/ │ ├── src/ohosArm64Main/kotlin/OkioNative.kt │ └── src/ohosArm64Main/linker/shared-library.map └── ohosApp/ ├── AppScope/ ├── entry/src/main/cpp/ │ ├── CMakeLists.txt │ └── napi_init.cpp └── entry/src/main/ets/ ├── entryability/EntryAbility.ets └── pages/Index.etsshared验证公共 Okio 调用,nativeApp产生 Native 动态库,ohosApp负责 ArkUI 页面和 N-API。三者边界清晰,任何一层失败都能单独定位。
6.2 原生模块注册
napi_init.cpp通过napi_module_register注册entry模块,ArkTS 使用:
importokiofrom'libentry.so'模块类型声明位于:
example/ohosApp/entry/src/main/cpp/types/libentry/index.d.ts6.3 Native 动态库准备
执行:
./gradlew :okio:publishToMavenLocal-PsigningEnabled=falsecdexample ./gradlew :shared:jvmTest :nativeApp:prepareOhos --no-daemon成功后生成:
example/ohosApp/entry/libs/arm64-v8a/libokio.so example/ohosApp/entry/src/main/cpp/include/libokio_api.h6.4 构建、签名和安装
在 DevEco Studio 打开example/ohosApp,完成本机签名配置后构建 HAP:
/Applications/DevEco-Studio.app/Contents/tools/node/bin/node\\/Applications/DevEco-Studio.app/Contents/tools/hvigor/bin/hvigorw.js\\--productdefault assembleHap--parallel--incremental--no-daemon产物位于:
example/ohosApp/entry/build/default/outputs/default/entry-default-signed.hap安装并启动:
hdc list targets hdc-t<设备序列号>install-r\\example/ohosApp/entry/build/default/outputs/default/entry-default-signed.hap hdc-t<设备序列号>shell aa start\\-aEntryAbility-bcom.squareup.okio.sample签名证书、profile、p12 和密码只保存在本机,不要提交到 AtomGit。
四、完整代码对照
4.1 整体架构
ArkUI Index.ets │ okioText() ▼ libentry.so / C++ N-API │ OkioText / OkioFree ▼ libokio.so │ Kotlin/Native C ABI ▼ OkioExamples │ Buffer.writeUtf8 + Buffer.readUtf8 ▼ JSON result4.2 文件清单
| 文件 | 职责 |
|---|---|
okio/build.gradle.kts | 注册ohosArm64和 OpenHarmony 源集。 |
okio/src/ohosMain/kotlin/okio/OhosPosixVariant.kt | OpenHarmony POSIX 兼容实现。 |
example/shared/.../OkioExamples.kt | 共享 Okio Buffer 示例和自检。 |
example/nativeApp/.../OkioNative.kt | C ABI、JSON 返回和内存释放。 |
example/ohosApp/entry/src/main/cpp/napi_init.cpp | C++ N-API 导出和 Native 字符串转换。 |
example/ohosApp/entry/src/main/cpp/CMakeLists.txt | 导入libokio.so并链接libentry.so。 |
example/ohosApp/entry/src/main/ets/pages/Index.ets | ArkUI 真机验收页面。 |
scripts/build-openharmony.sh | OpenHarmony 核心库构建辅助脚本。 |
docs/openharmony/VALIDATION.md | 自动检查和真机验收记录。 |
docs/openharmony/images/okio-openharmony-result.png | 本次适配效果图。 |
4.3 关键 API 对照
| 层次 | API | 作用 |
|---|---|---|
| Okio | Buffer.writeUtf8 | 写入 UTF-8 文本。 |
| Okio | Buffer.readUtf8 | 读取 UTF-8 文本。 |
| Kotlin | OkioExamples.roundTrip | 执行共享 Buffer 往返。 |
| Kotlin | OkioExamples.checks | 返回共享验收结果。 |
| Native | OkioText | 返回 JSON C 字符串。 |
| Native | OkioFree | 释放 Native 返回缓冲区。 |
| N-API | okioText | 向 ArkTS 暴露 Native 方法。 |
4.4 ArkTS 与 Kotlin 的边界
ArkTS 只负责页面和调用生命周期:
this.value=okio.okioText()Kotlin 负责 Buffer 操作和验收:
publicfunroundTrip():String{valbuffer=Buffer()buffer.writeUtf8("OpenHarmony / Okio")returnbuffer.readUtf8()}两者之间只传输 UTF-8 JSON 字符串,不传输 Kotlin 对象、ArkTS class 实例或未校验的动态结构。
五、关键决策说明
决策 1:把ohosArm64加入公共构建约定
只有真正链接ohosArm64动态库,才能证明共享 Okio 代码可以进入 OpenHarmony 运行时。只在 JVM 上通过测试不足以证明 OpenHarmony Native 兼容。
决策 2:独立消费者必须通过构建产物消费
example单独解析共享代码,ohosApp单独接收.so和头文件,避免根工程编译通过却无法在 DevEco 中打包。
决策 3:在ohosMain处理 POSIX 差异
平台头文件差异属于 OpenHarmony 适配边界,不应把条件分支散落在公共代码中。集中放入ohosMain,可以保留 Okio 其他平台的实现和 API。
决策 4:JSON 作为跨语言数据契约
JSON 让 ArkTS、C++ 和 Kotlin/Native 的边界清楚可调试,并避免暴露 Buffer 和 Kotlin 运行时对象布局。
决策 5:桥接层只开放必要的 C ABI 入口
示例只需要结果和释放能力,少量 ABI 符号可以降低 Native 生命周期和版本兼容风险。
决策 6:把库验证和设备验证分开
JVM 测试验证 Buffer 规则,Native 链接验证 ABI,Hvigor 验证 HAP,真机验证 ArkUI 到 Kotlin/Native 的完整调用链。每一层都有明确的失败边界。
六、测试与验证
6.1 测试环境
本次验证使用:
- macOS;
- 项目 Gradle Wrapper 和 Kotlin Multiplatform 工具链;
- DevEco Studio 及 OpenHarmony ARM64 Native SDK;
- 已配置本机调试签名的 Stage 工程;
- ARM64 OpenHarmony 真机;
- HDC 设备连接。
6.2 静态检查与单元测试
./gradlew :okio:compileKotlinOhosArm64 ./gradlew :okio:publishToMavenLocal-PsigningEnabled=false(cd example&&./gradlew :shared:jvmTest)测试覆盖共享示例的 UTF-8 往返和passed验收逻辑。compileKotlinOhosArm64验证 Okio 核心模块可生成 OpenHarmony KLIB。
6.3 原生桥接和 HAP 验证
(cd example&&./gradlew :nativeApp:prepareOhos --no-daemon)/Applications/DevEco-Studio.app/Contents/tools/node/bin/node\\/Applications/DevEco-Studio.app/Contents/tools/hvigor/bin/hvigorw.js\\--productdefault assembleHap--parallel--incremental--no-daemon验证结果:
libokio.so generated libokio_api.h generated BuildNativeWithNinja successful Hvigor BUILD SUCCESSFUL entry-default-signed.hap generated6.4 功能验证用例
用例 1:默认页面
启动 HAP 后页面显示KMP Okio OpenHarmony标题、结果区域和“运行 Okio 检查”按钮。
用例 2:Native 调用
点击“运行 Okio 检查”,ArkTS 调用libentry.so,C++ 调用OkioText,Kotlin/Native 创建 OkioBuffer并返回 JSON。
用例 3:UTF-8 往返
确认页面结果中的value为OpenHarmony / Okio,说明writeUtf8和readUtf8在 OpenHarmony ARM64 动态库中执行成功。
用例 4:共享自检
确认结果中的checks为passed,说明自检逻辑来自共享 Kotlin 代码,而不是页面固定文本。
用例 5:重复点击和释放
连续点击按钮,确认页面仍能返回同样结果且应用不崩溃。每次返回的 Native 缓冲区都由OkioFree释放。
用例 6:Native 错误边界
如果 Native 调用发生异常,页面显示调用失败文本,不应出现无响应或崩溃。
6.5 验证结论
自动测试、Kotlin/Native ARM64 编译、N-API/CMake 链接、Hvigor HAP 构建、签名安装和真机页面自检均已完成。真机页面显示OpenHarmony / Okio与checks: passed,说明从 ArkUI 到 Okio Buffer 的链路可用。
七、运行效果
7.1 真机截图
截图中可以看到:
- 页面标题为“KMP Okio OpenHarmony”;
- 结果区域返回
OpenHarmony / Okio; checks状态为passed;- “运行 Okio 检查”按钮位于结果区域下方;
- 页面运行在 OpenHarmony Stage 宿主中,结果来自 Native Okio 调用。
7.2 命令速查
# 编译 Okio OpenHarmony 目标./gradlew :okio:compileKotlinOhosArm64# 发布本地依赖并准备 Native 产物./gradlew :okio:publishToMavenLocal-PsigningEnabled=false(cd example&&./gradlew :shared:jvmTest :nativeApp:prepareOhos --no-daemon)# 在已配置签名的工程中构建 HAPcdexample/ohosApp /Applications/DevEco-Studio.app/Contents/tools/node/bin/node\\/Applications/DevEco-Studio.app/Contents/tools/hvigor/bin/hvigorw.js\\--productdefault assembleHap--parallel--incremental--no-daemon# 安装和启动hdc list targets hdc-t<设备序列号>install-r\\entry/build/default/outputs/default/entry-default-signed.hap hdc-t<设备序列号>shell aa start\\-aEntryAbility-bcom.squareup.okio.sample八、遗留问题与改进方向
8.1 踩坑复盘
- 只改 ArkTS 页面不算 KMP 适配:必须把 Okio 共享代码真正编译成
ohosArm64动态库。 - 只生成
.so也不够:CMake、导出的头文件、N-API 和 HAP 需要使用同一次产物。 - 平台头文件差异要集中处理:
DEFFILEMODE和statx的兼容代码放在ohosMain,避免污染其他平台。 - N-API 必须释放返回字符串:C++ 创建 ArkTS 字符串后应立即调用
OkioFree。 - 签名和构建是两个步骤:Hvigor 构建成功不代表 HAP 已签名,真机安装必须使用签名产物。
8.2 已知问题
- 当前示例只覆盖 ARM64,未提供
x86_64或armeabi-v7aHAP 原生库; - 示例页面验证 Buffer 基础能力,未覆盖全部 Okio 文件系统和网络 API;
- OpenHarmony Native 工具链需要与 DevEco Studio SDK 版本匹配;
- 签名配置属于本机环境,其他开发者需要重新配置证书和 profile;
libokio.so和生成头文件属于构建产物,重新拉取仓库后需要再次执行prepareOhos。
8.3 未来优化方向
- 增加 OpenHarmony 文件系统、压缩和异步 I/O 的专项示例;
- 为 CMP 应用提供可复用的
commonMainOkio 数据层示例; - 增加 Native 依赖检查和 HAP 构建的 CI 任务;
- 为更多 OpenHarmony ABI 提供构建矩阵;
- 为 N-API 增加更细粒度的错误码和异步 API。
九、总结
9.1 核心难点回顾
本次适配真正需要处理的不是一个按钮,而是一条完整跨端链路:
KMP/CMP commonMain → Okio ohosArm64 → Kotlin/Native C ABI → C++ N-API → ArkUI Stage 页面 → OpenHarmony ARM64 真机9.2 封装层次
- Okio KMP 层:提供稳定的 Buffer API 和平台公共实现;
ohosMain层:处理 OpenHarmony POSIX 声明差异;- Native 层:生成 ARM64 动态库,并通过 C ABI 输出有限入口;
- N-API 层:完成字符串转换和 Native 内存释放;
- ArkTS 层:管理页面调用、错误显示和用户操作;
- DevEco 层:完成 CMake、HAP、签名、安装和运行。
9.3 三条经验
- 先让共享 Okio 代码在 JVM 和 OpenHarmony Native 分别通过,再接入 ArkUI;
- 用 JSON 和少量 C ABI 代替跨语言对象传递,降低边界复杂度;
- 把自动测试、HAP 构建和真机调用分别记录,避免把“编译成功”误认为“三方库功能可用”。
9.4 适配成果
当前 Okio OpenHarmony 适配已完成:
ohosArm64KMP 目标;- OpenHarmony
ohosMainPOSIX 兼容实现; - JVM 和 OpenHarmony ARM64 共用的 Buffer 示例;
- Kotlin/Native + C ABI + C++ N-API 桥接;
- CMake 导入
libokio.so; - Stage ArkUI 验收页面;
- 签名 HAP 构建、设备安装和效果图;
- 与参考 KMP/CMP 工程一致的模块和脚本组织;
- AtomGit 项目文档和 OpenHarmony 验收记录。
参考文档
- AtomGit/oh-tpc/okio
- OpenHarmony 官方文档
- OpenHarmony N-API
- Kotlin Multiplatform
- DevEco Studio
- 华为云码道