news 2026/10/28 19:10:19

开源鸿蒙平台 CMP 三方库「AboutLibraries」适配全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
开源鸿蒙平台 CMP 三方库「AboutLibraries」适配全流程

本文记录AboutLibraries接入 OpenHarmony 的完整过程,覆盖 KMP 数据模型与解析内核盘点、ohosArm64/ohosX64目标、Kotlin/Native 动态库、C ABI/N-API 桥接、ArkUI 真机页面、HAP 构建、签名和真机验收。

AboutLibraries是与平台耦合度极低的 KMP"关于页面"三段式方案:构建期 Gradle 插件收集依赖元数据生成aboutlibraries.json,运行时aboutlibraries-core解析为Library/License实体,再由 Compose UI 展示。本次适配让数据模型与解析内核这一公共实现进入 OpenHarmony ARM64 运行时,ArkUI 页面作为真机验收宿主,Compose Multiplatform(CMP)应用可以通过同一个 KMP 依赖使用这些解析 API。

项目地址:AtomGit/oh-tpc/AboutLibraries

上游仓库:mikepenz/AboutLibraries

开发工具:华为云码道

环境安装:环境安装指南

一、背景

1.1 为什么做 OpenHarmony 平台 KMP/CMP 适配

AboutLibraries为 Kotlin 项目提供依赖元数据的构建期收集(com.mikepenz.aboutlibraries.plugin插件)、运行时解析(aboutlibraries-core的Libs.Builder().withJson(json).build())和 Compose 渲染(aboutlibraries-compose-m2/m3)三层能力。KMP 项目通常把解析层放在commonMain,由 Android、iOS、桌面、Web 或其他 Native 宿主共享。OpenHarmony 应用同样需要"开源许可页"这套公共能力,但默认构建并不会生成 OpenHarmony 的 Kotlin/Native 变体。

如果只把示例页面改成 ArkTS,页面可以显示列表,却无法证明公共解析实现已经在 OpenHarmony ARM64 设备上完成编译、链接和执行。适配需要同时验证 KMP 核心、Native 动态库、C ABI、N-API、ArkUI 页面和 HAP 交付链路。

障碍具体问题
目标缺失必须增加ohosArm64()/ohosX64()才能生成 OpenHarmony KLIB。
工具链不一致上游使用 Gradle 9 / AGP 9 / Compose 1.12 / Kotlin 2.4,鸿蒙侧工具链为 Kotlin2.2.21-1.0.0/ Gradle 8.14.1。
语言边界不同ArkTS 不能直接持有 Kotlin 对象,需要 C ABI、C++ N-API 和 JSON。
序列化缺位aboutlibraries-core依赖 kotlinx.serialization 解析 JSON,该库无 ohos 制品。
语义必须保持名称排序、许可证按 hash 去重、坏 JSON 吞异常返回空结果,都是上游契约。
交付链路复杂.so、CMake、N-API、HAP、签名和hdc都要单独验收。

因此,本项目把边界放在 KMP 目标配置、内核 1:1 提取、C ABI/N-API 桥接和 ArkUI 验收层。解析语义仍由公共实现负责,ArkTS 只负责调用 Native、解析 JSON 和展示结果。

1.2 库提供的能力

上游三段式中,构建期插件与 UI 层分别工作在构建机和 Compose 宿主上,本次适配的对象是中间的解析内核。示例提供四个可观察场景:

  • 库列表:解析aboutlibraries.json得到全部Library,按上游语义排序展示;
  • 许可证:按许可证分组统计,点击读取许可证全文(内嵌 Apache-2.0 全文约 11 KB);
  • 搜索:在 Native 侧按名称 / 坐标 / 描述过滤库;
  • 状态:版本握手、解析统计和三个错误路径演示。

Library实体包含:

字段作用
uniqueId依赖坐标(groupId:artifactId,去版本)。
artifactVersion版本,可空。
name/description/website名称、描述、网站。
developers/organizationPOM 中的开发者和组织。
scm源码仓库信息,url非空即视为开源。
licenses许可证集合,以 hash 关联顶层许可证表。
funding资助信息(GitHub Sponsors 等)。
tag/targets分组标签与消费该产物的 Kotlin target 集合。

解析层还提供五项派生查询:search、licenses、groupByLicense、stats和licenseContent,全部在 Kotlin 侧完成。

1.3 实现适配

维度要求
代码复用aboutlibraries-core数据模型与解析逻辑 1:1 提取到 KMPcommonMain(同包名同文件名)。
平台目标独立 example 工程增加ohosArm64+ohosX64,生成双 ABI 动态库。
桥接稳定使用 3 个 C ABI 和 UTF-8 JSON,不传递 Kotlin 对象地址。
CMP 兼容CMP 应用复用同一 KMP 依赖;ArkUI 只负责真机验收,Compose UI 待社区工具链对齐后接回。
UI 完整支持库列表、详情展开、许可证全文、搜索、统计和错误展示。
仓库规范项目说明、文章、效果图和源码链接统一使用 AtomGit。

本项目的 ArkUI 页面不是 Compose Multiplatform UI 实现。CMP 工程可以直接依赖 OpenHarmony KMP 变体,在自己的 Compose 页面中使用标准Libs.Builder()解析 API。

二、实现路线图

第 1 阶段:项目初始化 ── 盘点源集、工程边界和 OpenHarmony 交付物 第 2 阶段:目标与依赖打通 ── 独立 example 工程、ohosArm64/ohosX64 与 so 交接 第 3 阶段:内核提取建模 ── core 1:1 提取、MiniJson 解析器和黄金测试 第 4 阶段:原生桥接 ── C ABI、C++ N-API、参数校验和内存释放 第 5 阶段:ArkUI 宿主 ── 四 Tab 页面、真实 Native 数据和错误边界 第 6 阶段:示例与验证 ── HAP、签名、设备安装、真机运行和效果图

三、逐步实现过程

第 1 阶段:项目初始化

1.1 工程边界
AboutLibraries/ 上游仓库原样保留(根构建一行不改) example/ 独立 Gradle 工程(自带 wrapper) ├── nativeApp/ 内核提取、MiniJson、C ABI 桥和 JVM 测试 └── harmonyApp/ DevEco Stage、CMake N-API 和 ArkTS 页面 doc/ 适配文章与真机效果图

example是独立 Gradle 工程,不把 DevEco 工程作为根项目的 Kotlin 子模块,Gradle 和 Hvigor 可以分开执行;上游根构建依赖远程 convention 插件与 AGP 9 / Kotlin 2.4 版本线,保持原样互不干扰,审核面上只有新增文件。

1.2 工具链矩阵
项目配置
Kotlin MultiplatformOpenHarmony 工具链2.2.21-1.0.0(社区 Maven)
JDK21
Gradle8.14.1(example wrapper 钉死)
OpenHarmony 目标ohosArm64+ohosX64
DevEco product6.0.1(21)
DevEco Studio6.0.1 Release
ABIarm64-v8a+x86_64
Bundlecom.mikepenz.aboutlibraries.ohos
exportJAVA_HOME="/path/to/jdk-21"java-version
1.3 页面边界
标题区 ABOUTLIBRARIES · OPENHARMONY / 版本握手行 Tab 区 库 / 许可证 / 搜索 / 状态 库列表区 名称、版本、许可证徽章、runtime/build 标签,点击展开全字段 许可证区 许可证分组列表 + 元数据 + 全文滚动阅读 搜索区 关键字输入 + native 过滤结果 状态区 版本、统计、target 覆盖和三个错误路径演示按钮

页面启动时通过aboutLibrariesVersion()完成握手,读取 rawfile 中内置的aboutlibraries.json后交给 Native 解析,自动填充库列表与许可证分组。

第 2 阶段:目标与依赖打通

2.1 仓库置顶与独立工程
pluginManagement{repositories{// HarmonyOS Kotlin 工具链仓库必须排在最前,// 否则插件解析回落官方 Kotlin,ohosArm64() 无从解析maven("https://maven.eazytec-cloud.com/nexus/repository/maven-public/")maven("https://maven.eazytec-cloud.com/nexus/content/groups/harmonyos")gradlePluginPortal()google()mavenCentral()}}rootProject.name="ohos_aboutlibraries"include(":nativeApp")
2.2 构建 Native 产物并交接
kotlin{applyDefaultHierarchyTemplate()jvm()// 保留 JVM 目标承载黄金交叉验证ohosArm64{binaries.sharedLib{baseName="ohosaboutlibraries"}}ohosX64{binaries.sharedLib{baseName="ohosaboutlibraries"}}}

链接任务finalizedBy拷贝任务,把libohosaboutlibraries.so与对应 triple 的libc++_shared.so自动放入harmonyApp/entry/libs/{arm64-v8a,x86_64}/:

./gradlew :nativeApp:linkDebugSharedOhosArm64 :nativeApp:linkDebugSharedOhosX64 ./gradlew :nativeApp:jvmTest
2.3 零第三方依赖的提取层
sourceSets{commonMain.dependencies{}// 提取层零第三方依赖}

kotlinx.serialization 没有 ohos 制品,提取层不引入任何序列化库,JSON 解析由自带的 MiniJson 完成(第 3 阶段)。

第 3 阶段:内核提取与语义建模(技术难点)

3.1 JSON 契约
aboutlibraries.json(HAP rawfile) ↓ ArkTS 读取文本 Libs.Builder().withJson(json).build() ↓ parseData(上游语义) MiniJson 递归下降解析 ↓ Result(libraries, licenses) Bridge.kt 派生查询 ↓ UTF-8 JSON N-API aboutLibrariesParse/Query ↓ ArkUI Index.ets 四 Tab 页面

页面不复制任何解析逻辑,每个字段由提取的公共 Kotlin 代码生成。

3.2 内核 1:1 提取

上游aboutlibraries-core约 605 行、15 个文件,全部为平台无关纯 Kotlin。提取规则:同包名同文件名,文件头注释标明上游路径与差异,可逐文件 diff 复核:

上游文件处置
commonMain/.../Libs.kt与entity/*.kt(8 文件)1:1 复制,仅剥离@Serializable/@SerialName注解
multiplatformMain/.../MultiplatformParser.kt+MultiplatformExtensions.kt与commonMain/.../Parser.kt合并为单一声明,getJSONObject/optString/forEachObject/forEachString等 helper 命名与上游一一对应
androidMain/**(org.json 实现)不提取
funparseData(json:String):Result{try{valmetaData=MiniJson.parse(json).let{itasMiniJson.Node.Obj}vallicenses=metaData.getJSONObject("licenses").forEachObject{key->License(getString("name"),optString("url"),optString("year"),optString("spdxId"),optString("content"),key)}// ……与上游 actual 逐行同构}catch(t:Throwable){println("Failed to parse the meta data *.json file:$t")}returnResult(emptyList(),emptyList())// 上游吞异常语义原样保留}
3.3 MiniJson 解析器

aboutlibraries.json是深嵌套文档(licenses还是以 hash 为键的对象表),平面解析器无法胜任,因此 MiniJson 实现了完整语法:对象 / 数组 / 字符串 / 数字 / 布尔 / null、全部转义序列、LinkedHashMap保持键序;约 190 行、零依赖、commonMain单文件,JVM 与 ohos 两侧编译同一份。

3.4 黄金交叉验证

jvmTest用与 HAP rawfile 同一份 JSON 钉住上游数值:8 库 / 3 许可证、按小写名称排序、artifactId拼接、许可证按 hash 去重(Apache-2.0 被多个库共享但集合只有一条)、缺版本时坐标带尾冒号、坏 JSON 返回空结果、MiniJson 转义与畸形输入行为,共 13 个用例。

第 4 阶段:原生桥接

4.1 三层桥接
ArkTS │ JSON string ▼ C++ N-API entry │ const char* ▼ Kotlin/Native C ABI │ Libs.Builder / 派生查询 ▼ UTF-8 JSON + DisposeString

直接导出 Kotlin 对象会暴露 ABI 和生命周期问题;只导出整数又会让页面复制解析语义,所以选择 C ABI + JSON。

4.2 Kotlin/Native 导出函数
@CName("AboutLibrariesVersion")funaboutLibrariesVersion():String// 版本握手@CName("AboutLibrariesParse")funaboutLibrariesParse(request:String):String// {"json": "<aboutlibraries.json>"} → counts + libraries + licenses 摘要@CName("AboutLibrariesQuery")funaboutLibrariesQuery(request:String):String// {"op": "search|licenses|groupByLicense|stats|licenseContent", ...}

每个导出整体 try/catch,响应统一为{"ok":true,...}或{"ok":false,"error":"..."},Kotlin 异常绝不跨 FFI 边界;相同 JSON 文本复用会话缓存,派生查询无需重复解析。

4.3 C++ N-API 方法分发
napi_property_descriptor desc[]={{"aboutLibrariesVersion",nullptr,NapiVersion,nullptr,nullptr,nullptr,…,nullptr},{"aboutLibrariesParse",nullptr,NapiParse,nullptr,nullptr,nullptr,…,nullptr},{"aboutLibrariesQuery",nullptr,NapiQuery,nullptr,nullptr,nullptr,…,nullptr},};

N-API 只负责参数类型检查、字符串转换和释放,不实现解析语义。KN 返回字符串创建 ArkTS 字符串后,立即经libohosaboutlibraries_symbols()->DisposeString归还 Kotlin 运行时,绝不free()。

4.4 CMake 和类型声明
add_library(ohosaboutlibraries SHARED IMPORTED) set_target_properties(ohosaboutlibraries PROPERTIES IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libohosaboutlibraries.so" IMPORTED_NO_SONAME TRUE) add_library(aboutlibraries_napi SHARED napi_init.cpp) target_link_options(aboutlibraries_napi PRIVATE "-Wl,-rpath,\$ORIGIN") target_link_libraries(aboutlibraries_napi PUBLIC libace_napi.z.so libhilog_ndk.z.so ohosaboutlibraries)
exportconstaboutLibrariesVersion:()=>string;exportconstaboutLibrariesParse:(request:string)=>string;exportconstaboutLibrariesQuery:(request:string)=>string;

第 5 阶段:ArkUI 宿主

5.1 加载数据
import{aboutLibrariesVersion,aboutLibrariesParse,aboutLibrariesQuery}from'libaboutlibraries_napi.so';import{util}from'@kit.ArkTS';constcontext=this.getUIContext().getHostContext();constraw=context.resourceManager.getRawFileContentSync('aboutlibraries.json');consttext=util.TextDecoder.create('utf-8').decodeToString(raw);constreq:Record<string,string>={'json':text};constmodel=JSON.parse(aboutLibrariesParse(JSON.stringify(req)))asParseInfo;this.libraries=model.libraries??[];
5.2 页面交互

页面支持库列表(点击展开上游全部字段,含 funding / organization / scm / targets)、许可证分组与全文阅读、native 搜索和状态统计。所有数据来自共享 Kotlin 结果,ArkTS 不重新实现排序、去重或过滤。

5.3 对比度和错误边界

选中项使用深蓝底白字,标签徽章用浅色底深色字,错误横幅为红底白字。状态页提供三个错误路径演示按钮(坏 JSON / 未知 op / 坏 hash),任何输入下页面不崩溃,错误显示在状态行。

第 6 阶段:示例与验证

6.1 工程结构
example/ ├── nativeApp/src/ │ ├── commonMain/.../com/mikepenz/aboutlibraries/ # 内核 1:1 提取(8 文件) │ ├── commonMain/.../example/nativeapp/MiniJson.kt │ ├── jvmTest/.../GoldenJsonTest.kt + MiniJsonTest.kt │ └── ohosMain/.../example/nativeapp/Bridge.kt └── harmonyApp/entry/src/main/ ├── cpp/CMakeLists.txt + napi_init.cpp + include/libohosaboutlibraries_api.h ├── ets/pages/Index.ets └── resources/rawfile/aboutlibraries.json
6.2 构建、签名和安装
exportJAVA_HOME="/path/to/jdk-21"cdexample ./gradlew :nativeApp:linkDebugSharedOhosArm64 :nativeApp:linkDebugSharedOhosX64# DevEco Studio 打开 example/harmonyApp → Signing Configs → 自动生成签名hvigorw assembleHap--modemodule-pproduct=default-pbuildMode=debug
hdc list targets-vhdc-t<设备序列号>install-r\entry/build/default/outputs/default/entry-default-signed.hap hdc-t<设备序列号>shell aa start\-aEntryAbility-bcom.mikepenz.aboutlibraries.ohos-mentry

四、完整代码对照

4.1 整体架构

Parser.kt(上游解析语义 + MiniJson) │ parseData / Libs.Builder ▼ Bridge.kt │ AboutLibrariesVersion / Parse / Query ▼ libaboutlibraries_napi.so │ aboutLibrariesVersion / Parse / Query ▼ Index.ets │ JSON parse + state update ▼ ArkUI 真机页面(库 / 许可证 / 搜索 / 状态)

4.2 文件清单

文件职责
example/settings.gradle.kts工具链仓库置顶、独立工程边界
example/nativeApp/build.gradle.ktsohosArm64/ohosX64sharedLib 与 so 拷贝
nativeApp/.../aboutlibraries/**(8 文件)core 1:1 提取(同包名同文件名)
nativeApp/.../MiniJson.kt零依赖 JSON 解析与转义
nativeApp/.../GoldenJsonTest.kt上游语义黄金断言
nativeApp/.../Bridge.ktC ABI、会话缓存和派生查询
harmonyApp/.../napi_init.cppN-API 导出、hilog 和 DisposeString
harmonyApp/.../CMakeLists.txtIMPORTED KN so 与 rpath
harmonyApp/.../Index.etsArkUI 四 Tab 验收页面
README.OpenHarmony_CN.md适配主文档(5000+ 字)

4.3 关键 API 对照

层次API作用
KMPLibs.Builder().withJson().build()解析 JSON 并按上游语义排序去重
KMPparseDataJSON →Result(libraries, licenses)
NativeAboutLibrariesVersion版本握手
NativeAboutLibrariesParse返回完整模型
NativeAboutLibrariesQuerysearch / licenses / groupByLicense / stats / licenseContent
N-APIaboutLibrariesParse/aboutLibrariesQuery向 ArkTS 暴露数据
ArkTSloadAndParse/doSearch触发解析并刷新 UI

4.4 ArkTS 与 Kotlin 的边界

constmodel=JSON.parse(aboutLibrariesParse(JSON.stringify(req)))asParseInfo;
@CName("AboutLibrariesParse")funaboutLibrariesParse(request:String):String

两者之间只传输 JSON 字符串,不传输 Kotlin 对象或未校验的动态结构。

五、关键决策说明

决策 1:上游根构建一行不改,example 独立成工程

上游版本线(Gradle 9 / AGP 9 / Kotlin 2.4)与鸿蒙工具链不兼容,改动根构建会引入不可审计的 diff。独立 example 工程让适配面只有新增文件。

决策 2:内核 1:1 提取而不是重写

同包名同文件名提取让每一份副本都能与上游 diff 复核;文件头注释声明差异(仅剥序列化注解),解析语义的"没有漂移"由黄金测试背书。

决策 3:MiniJson 零依赖替代 kotlinx.serialization

工具链无 ohos 制品,自写 190 行完整语法解析器比引入不可控垫片更可审计;JVM 与 ohos 编译同一份源码,行为一致性由 13 个测试用例钉住。

决策 4:JSON 作为跨语言数据契约 + 会话缓存

JSON 让 ArkTS、C++ 和 Kotlin/Native 的边界清楚可调试;Parse携带全文时重建会话,相同文本直接复用,派生查询不重复解析。

决策 5:ArkUI 作为验收宿主,CMP 复用 KMP 解析内核

当前页面验证 OpenHarmony Native 链路;上游 Compose 模块源码原样保留,待社区 CMP 的 ohos 制品与上游版本对齐后接回,届时 ArkUI 页面退化为验收工具。

六、测试与验证

6.1 测试环境

本次验证使用 macOS(Apple Silicon)、JDK 21、DevEco Studio 6.0.1 Release、OpenHarmony SDK6.0.1(21)与华为真机(arm64-v8a)。

6.2 共享样例测试

cdexample ./gradlew :nativeApp:jvmTest

13 个用例(7 黄金 + 6 MiniJson)全部通过,验证库数量与排序、许可证 hash 去重、artifactId拼接、可空字段回退、坏 JSON 空结果、转义序列和畸形输入拒绝。

6.3 符号与 HAP 验证

AboutLibrariesParse / AboutLibrariesQuery / AboutLibrariesVersion / libohosaboutlibraries_symbols → llvm-nm -D 全局 T 符号(双 ABI) CompileArkTS: finished PackageHap: finished BUILD SUCCESSFUL install bundle successfully start ability successfully

未签名 HAP(约 6.5 MB)解包含双 ABI 六件 so(NAPI so + KN so + libc++_shared.so × 2)。

6.4 功能用例

  1. 启动后自动完成版本握手并加载 8 个库、3 个许可证;
  2. 库列表点击展开上游全部字段(描述、坐标、开发者、组织、SCM、targets、资助);
  3. 许可证 Tab 分组浏览,Apache-2.0 全文(约 11 KB)可滚动阅读;
  4. 搜索kotlin命中 1 项、aboutlibraries命中 2 项,过滤在 Native 侧执行;
  5. 状态页显示解析耗时与 target 覆盖(jvm / ohosArm64 / ohosX64);
  6. 坏 JSON / 未知 op / 坏 hash 三个演示按钮均返回明确错误文案,页面不崩溃。

6.5 验证结论

Native 动态库、C ABI、N-API、ArkUI 页面和签名 HAP 已完成链路验证。应用在真机上成功安装并进入前台,页面展示了真实解析结果的库列表、许可证分组与统计信息。

七、运行效果

7.1 真机截图

7.2 命令速查

gitclone https://atomgit.com/oh-tpc/AboutLibraries.gitcdAboutLibraries/exampleexportJAVA_HOME="/path/to/jdk-21"./gradlew :nativeApp:linkDebugSharedOhosArm64 :nativeApp:linkDebugSharedOhosX64 ./gradlew :nativeApp:jvmTestcdharmonyApp hvigorw assembleHap--modemodule-pproduct=default-pbuildMode=debug hdc-t<设备序列号>install-r\entry/build/default/outputs/default/entry-default-signed.hap

八、遗留问题与改进方向

8.1 踩坑复盘

  1. 工具链仓库必须写在pluginManagement最前,否则ohosArm64()报Unresolved reference;
  2. String.format在 Kotlin/Native 不存在,\uXXXX转义改为手写十六进制拼接;
  3. libc++_shared.so不随 KN so 产出,必须从 Konan 依赖目录拷入entry/libs/<abi>/,否则 HAP 安装报 9568347;
  4. hvigor 的signingConfigs不接受空骨架,提交版直接整体去掉签名块,证书留在本机;
  5. ArkTS 中 Native 函数返回值不要先赋局部变量(推断为 any),直接嵌套JSON.parse(...) as X;
  6. 运行结果要来自真实 Native 调用,而不是页面静态文字;
  7. 签名工程必须与源码分离,证书不能进入 AtomGit。

8.2 已知问题

  • 上游 Compose UI 模块(aboutlibraries-compose*)未编译进鸿蒙,由 ArkUI 页面替代演示;
  • MiniJson 只实现本库用到的 JSON 读取语法,不含 streaming / schema 校验;
  • Demo 的aboutlibraries.json按插件 schema 手工构建(描述本 HAP 真实供应链),生产业务应运行上游 Gradle 插件生成同名文件替换;
  • 上游 Gradle 插件可照常在构建机工作,但未接入 hvigor 工程自动生成 rawfile;
  • aboutlibraries-compose-wear-m3为纯 Android 模块,与鸿蒙无关,未处理。

8.3 未来优化方向

  • 跟踪社区 CMP 的 ohos 制品版本,把上游 Compose UI 模块接回鸿蒙宿主;
  • 评估 klib / Maven 制品发布路径,替代 so + NAPI 交付形态;
  • 在 CI 中加入 Native 链接、ELF 符号检查和 HAP 构建;
  • 补充不同设备 ABI、API 版本的验收矩阵;
  • 为 hvigor 工程写插件接线脚本,自动生成并同步aboutlibraries.json。

九、总结

9.1 核心难点回顾

KMP commonMain 解析内核(1:1 提取) → ohosArm64/ohosX64 Kotlin/Native → C ABI → C++ N-API → ArkTS JSON 解析 → ArkUI 真机页面

9.2 封装层次

  • KMP 层:提供Libs.Builder、Library/License实体和上游解析语义(排序、hash 去重、容错);
  • Native 层:生成双 ABI 动态库并通过 3 个 C ABI 输出 JSON;
  • N-API 层:完成参数检查、字符串转换和 Native 内存释放;
  • ArkTS 层:管理列表、许可证、搜索、统计和错误状态;
  • DevEco 层:完成 CMake、HAP、签名、安装和真机运行。

9.3 三条经验

  1. 先让解析内核在 KMP 与 Native 侧通过黄金测试,再接入 ArkUI 或 CMP UI;
  2. 用 JSON 和少量 C ABI 代替跨语言对象传递,并明确字符串释放责任;
  3. 分别记录自动测试、Native 链接、HAP 构建和真机运行,避免把编译成功误认为设备链路可用。

9.4 适配成果

当前适配已完成:

  • aboutlibraries-core数据模型与解析内核的 1:1 提取(ohosArm64+ohosX64双目标);
  • 13 个 JVM 黄金交叉验证用例全部通过;
  • 3 个 C ABI 符号和 C++ N-API 包装(llvm-nm -D全局 T 符号验证);
  • DevEco Stage ArkUI 四 Tab 验收页面;
  • HAP 构建、双 ABI 三件套 so、签名安装和真机运行验证;
  • AtomGit 项目文档(README 四件套)、适配文章和本地效果图。

适配过程 FAQ

以下问题来自ohosArm64目标接入、NAPI 桥接、HAP 构建与真机验收的实际流程,按出现频率排序。

Q1:DevEco Studio Sync 失败或 ohpm 依赖下载超时,怎么处理?

  • 确认 DevEco Studio 版本与工程build-profile.json5的compatibleSdkVersion一致;
  • 在File > Settings > Build, Execution, Deployment > Ohpm配置可用的 ohpm 仓库镜像或代理;
  • 删除oh_modules、oh-package-lock.json5与.hvigor缓存后重新 Sync;
  • 公司网络需要代理时,同时给 ohpm 与 hvigor 配置http.proxy。

Q2:CMake 报Missing .../libxxx.so或找不到 Kotlin/Native 动态库?

  • 先在example目录执行./gradlew :nativeApp:linkDebugSharedOhosArm64(模拟器用linkDebugSharedOhosX64);
  • 确认libxxx.so与libc++_shared.so已复制到ohos/entry/libs/<abi>/;
  • 检查entry/build-profile.json5的abiFilters与设备 ABI 是否一致(真机arm64-v8a,模拟器x86_64);
  • 清理entry/.cxx与entry/build后重试。

Q3:ArkTS 报Cannot find module 'libxxx_napi.so'或调用返回undefined?

  • 确认 CMake 的add_library(<target> SHARED ...)名称与import ... from 'libxxx_napi.so'完全一致;
  • 解包 HAP,确认libs/<abi>/libxxx_napi.so已打包;
  • 删除entry/build、entry/.cxx与oh_modules后重新构建;
  • 检查module.json5的srcEntry与页面路径是否正确。

Q4:真机安装报signature verification failed或install failed?

  • 在 DevEco Studio 的Signing Configs配置证书、Profile 与密码;
  • bundleName必须与签名 profile 中的 bundle name 一致;
  • 设备需加入 profile 的deviceIds,调试证书有效期需覆盖当前时间;
  • 用hdc list targets确认设备在线,再执行hdc install -r xxx-signed.hap。

Q5:应用启动白屏、闪退或 NAPI 调用崩溃?

  • 用hdc hilog | grep -i "napi\|kotlin"查看原生日志;
  • 确认libc++_shared.so与 Kotlin/Native 工具链版本匹配,且 ABI 与设备一致;
  • 检查 C ABI 返回的字符串是否由 Native 侧分配、ArkTS 侧复制后是否调用XxxFree释放;
  • 在 DevEco 的 Native 调试配置中附加lldb,定位空指针与越界访问。

Q6:Gradle 报ohosArm64目标不存在或 Kotlin/Native 编译失败?

  • 使用鸿蒙发行版 Kotlin(如2.2.21-1.0.0),并在settings.gradle.kts配置 eazytec 仓库;
  • Gradle 建议 8.x、JDK 21,版本不匹配时先统一工具链;
  • 确认kotlin { ohosArm64() }已应用,且local.properties的 SDK 路径有效;
  • 清理~/.gradle/caches中对应版本的 Kotlin/Native 缓存后重试。

Q7:HAP 构建报 SDK 版本不匹配或compatibleSdkVersion错误?

  • 对齐 DevEco Studio、HarmonyOS SDK 与build-profile.json5中的compatibleSdkVersion;
  • 升级 DevEco Studio 后同步升级 hvigor 与 SDK,避免modelVersion与 IDE 不匹配;
  • 命令行构建时设置DEVECO_SDK_HOME指向 DevEco 的sdk目录。

Q8:命令行 hvigor 构建失败,但 DevEco 里能构建?

  • 使用 DevEco 自带的 node 与 hvigor:
    "$DEVECO/Contents/tools/node/bin/node" "$DEVECO/Contents/tools/hvigor/bin/hvigorw.js" ...;
  • 设置JAVA_HOME、NODE_HOME、DEVECO_SDK_HOME;
  • 加上--no-daemon排除守护进程缓存影响,并清理entry/build与.hvigor。

参考文档

  • AtomGit/oh-tpc/AboutLibraries
  • mikepenz/AboutLibraries(上游)
  • Kotlin Multiplatform
  • Compose Multiplatform
  • OpenHarmony N-API
  • DevEco Studio
  • OpenHarmony ArkUI
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/28 19:09:51

3个硬核降AIGC平台,让你的论文查重降AI两不误[必看]

一、降AI率&#xff0c;到底在降什么&#xff1f; 很多人把“降AI率”简单理解为“改写”&#xff0c;这是误区。AIGC检测核心是识别文本的“机器指纹”&#xff0c;比如用词过于规整、逻辑衔接过于平滑、缺乏人类写作的随机性和情感波动。因此&#xff0c;有效的降AI率工具&am…

作者头像 李华
网站建设 2026/10/28 19:09:16

【笔记】直流减速电机(GA25-370)调速

一句话&#xff1a;直流有刷电机的转速只由电枢端电压决定&#xff0c;所以"调速"就是"调平均电压"。 单片机没法直接调电压&#xff0c;于是用 PWM 斩波 H 桥把电池的固定电压切成可调的平均电压。 0. 速查表#环节干什么关键量代码位置1电机本体电压 → …

作者头像 李华
网站建设 2026/10/28 19:07:19

问数平台为什么越用越准,FewShot 样本库那只看不见的手

把每一次人工纠正&#xff0c;变成系统下次能复用的经验。机制一样本沉淀每一次人工纠正&#xff0c;都会被记成一张样本卡存进库。比如模型把「带看转化佣金」按错口径算了&#xff0c;业务老师改回正确算法&#xff0c;这条问法到正确结果就落成一张卡。卡里不只存答案&#…

作者头像 李华
网站建设 2026/10/28 19:05:16

怎么在客户拜访前快速了解一家企业

一、商务精准化趋势下&#xff0c;拜访前调研的效率瓶颈当前企业商务合作、供应链对接、客户拓展都在向精细化转型&#xff0c;面对面拜访仍是建立信任、推进合作的核心环节&#xff0c;但拜访前的信息准备工作&#xff0c;普遍成为制约效率的瓶颈。无论是金融机构对公客户经理…

作者头像 李华
网站建设 2026/10/28 19:02:49

【C/C++ std::string 的 SSO:你以为省了分配,其实可能复制了更多字节】

🔥 个人主页: flos chen ❄️ 个人专栏: 《系统分析师》 《C/C++》 《Qt》 《Linux》 《SQL》 《深度学习》 🌟 边学习,边记录,一起学习进步! 文章目录 前言 1.1 问题:短字符串的堆分配浪费 1.2 解决方案:在对象内部预留缓冲区 2. 内存布局 2.1 l…

作者头像 李华
网站建设 2026/10/28 18:54:03

《AI Agent原理与实战》2026版 第25课 可信赖的 Agent:边界与审核

本文收录于专栏 《AI Agent原理与实战》2026版 —— 专栏系统覆盖 AI Agent 的记忆、工具、插件与实战&#xff0c;点击订阅可跟踪后续更新。 本课定位&#xff1a;系统能跑只是及格线&#xff0c;能被信任才能上线。本课讲三道防线&#xff1a;输出质量&#xff08;系统消息框…

作者头像 李华