2501_94452576头像

开源鸿蒙平台 KMP_CMP 三方库「kotlin-faker」适配全流程

本文记录 kotlin-faker 接入 OpenHarmony 的完整过程,覆盖 KMP 工程盘点、ohosArm64 目标、Kotlin/Native 动态库、C ABI/N-API 桥接、ArkUI 交互工作台、HAP 构建、签名准备和真机验收。

本次适配保留 JVM 版本的完整 locale 字典能力,同时为 OpenHarmony 增加 Native 安全的 Faker 核心路径。ArkTS 页面调用的是真实 Kotlin/Native 生成结果,支持人物资料、联系方式和文本素材三种场景,不是只展示固定测试数据。

项目地址: AtomGit/oh-tpc/kotlin-faker

上游仓库: serpro69/kotlin-faker

开发工具: 华为云码道

环境安装: 环境安装指南

一、背景

1.1 为什么做开源鸿蒙平台 KMP/CMP 适配

kotlin-faker 是一个面向测试数据、原型数据和数据脱敏场景的 Kotlin Faker 库,原始工程以 JVM 为主,使用 locale 字典和 JVM 依赖生成姓名、地址、网络数据、随机字符串以及大量领域数据。

如果只把页面重新写成 ArkTS,再在页面里写几组固定姓名和邮箱,无法证明 Faker 的 Kotlin API、Native 动态库和 OpenHarmony 宿主已经连通。完整适配需要同时解决下面的问题:

障碍具体问题
目标缺失原工程主要使用 jvmMain,必须增加 ohosArm64() 才能生成 OpenHarmony KLIB 和 .so。
JVM 依赖边界Jackson、ICU4J、资源流和反射不能直接进入 Kotlin/Native。
API 兼容JVM 端保留完整字典能力,Native 端仍要提供同包、可调用的 Faker 核心入口。
语言边界不同ArkTS 不能直接持有 Kotlin data class,必须经过 C ABI、C++ N-API 和 JSON。
数据交互页面需要能选择场景、调整数量、批量生成、追加和清空,而不是只显示自检数字。
构建链路复杂Gradle、Kotlin/Native、OpenHarmony LLVM、CMake、Hvigor、HAP 和签名需要分层验证。
交付安全证书、profile、p12、别名和密码不能进入 AtomGit 仓库。

因此,本项目把适配边界放在三个地方:Native 目标和依赖隔离、C ABI/N-API 桥接层、ArkUI 交互工作台。JVM 版本的完整字典实现继续独立运行,OpenHarmony 版本提供可链接的核心 Faker 工作流。

1.2 库提供的能力

OpenHarmony Native 版本提供以下核心能力:

  • FakerConfig:locale、随机源和随机种子配置;
  • Faker:统一 Faker 入口;
  • RandomProvider:整数、布尔值、长整型和随机字符串;
  • Name:名字、姓氏和全名;
  • Address:城市、国家和街道地址;
  • Internet:用户名和邮箱;
  • Lorem:Native 文本词语和句子生成;
  • FakerExamples.generate:交互页面使用的场景化批量生成门面;
  • FakerExamples.runChecks:JVM、Native 和桥接测试复用的共享检查。

交互页面将这些能力组合成三个场景:

场景调用的 Faker 能力页面展示
人物资料name.name、internet.email、address.city、randomString全名、邮箱、城市和随机字符串
联系方式name.firstName、internet.email、address.streetAddress名字、邮箱、街道地址和随机字符串
文本素材randomString、address.country文本标题、随机短字符串、国家和长字符串

1.3 实现适配

维度要求
代码复用JVM 和 Native 共用 Faker 的包名、共享门面、测试结构和 JSON 记录模型。
平台目标core、example/shared 和 example/nativeApp 配置 ohosArm64。
桥接稳定使用少量 C ABI 函数和不可变 JSON,避免 Kotlin 对象地址跨语言传递。
UI 完整页面支持场景切换、数量调节、批量生成、追加一条和清空列表。
可测试JVM 测试、Native 链接、ELF 依赖、CMake、ArkTS 和 HAP 分别验证。
签名安全源码只保留签名工程复制和构建入口,密钥材料由开发者本机配置。
仓库规范项目地址、文章、源码链接和适配说明统一使用 AtomGit。

示例页是独立的交互宿主,公共 API 仍然保持 Kotlin 使用方式。其他 KMP/CMP 应用可以复用 Native Faker 核心,再自行设计业务页面。

二、实现路线图

第 1 阶段:项目初始化     ── 盘点 JVM API、Native 边界和 OpenHarmony 示例结构
第 2 阶段:目标与依赖打通 ── 加入 ohosArm64、Kotlin 2.2.21-1.0.0 和独立 example
第 3 阶段:Faker 与序列化 ── 建立 Native Provider、共享记录和 JSON 契约
第 4 阶段:原生桥接       ── Kotlin/Native C ABI、C++ N-API、参数校验和释放
第 5 阶段:交互工作台     ── ArkTS 场景、数量、批量生成、追加和清空
第 6 阶段:示例与验证     ── Native、ELF、CMake、ArkTS、HAP 和效果图

每个阶段都使用真实产物作为下一阶段输入:先用 JVM 验证共享门面,再把同一门面链接为 ARM64 动态库,随后由 CMake 和 N-API 加载到 Stage 工程,最后构建未签名 HAP 并准备本地签名。

三、逐步实现过程

第 1 阶段:项目初始化

1.1 盘点公共 API 和工程边界

项目采用与参考 KMP/CMP 工程一致的分层:

kotlin-faker/                 JVM Faker、Native Faker 和构建约定
core/src/jvmMain/             完整 locale 字典实现
core/src/ohosArm64Main/       Native-compatible Faker 核心
example/shared/               公共门面和 JVM 验收测试
example/nativeApp/            ohosArm64 Kotlin/Native 动态库
example/ohosApp/              DevEco Stage 工程和 ArkUI 页面
scripts/                      Native、HAP、依赖和签名工程脚本
docs/openharmony/             验收记录和效果图

example 是独立 Gradle 工程,不把 DevEco 工程当作根工程的 Kotlin 子模块。这样可以分别执行 Gradle 和 Hvigor,也可以把 ohosApp 复制到独立目录后配置签名。

1.2 固定工具链和版本矩阵
项目配置用途
Kotlin Multiplatform2.2.21-1.0.0JVM、Kotlin/Native 和 OpenHarmony target
JDK21Gradle、Kotlin 编译和 Native 任务
OpenHarmony 目标ohosArm64ARM64 真机动态库
DevEco product6.0.0(20)工程兼容和目标版本
DevEco Studio6.0.0 ReleaseIDE 版本,负责工程同步、HAP 构建与签名
ABIarm64-v8aHAP 原生库架构
生成数量1..8适配手机页面的交互和滚动范围

执行 Gradle 脚本前先选择 JDK 21:

export JAVA_HOME="/path/to/jdk-21"
java -version
1.3 创建 OpenHarmony 示例目录

页面围绕“选择场景、控制数量、生成列表”组织:

标题区          Kotlin Faker / 真实数据生成工作台 / 当前条数
控制区          人物资料 / 联系方式 / 文本素材
数量区          减少 / 当前数量 / 增加
操作区          批量生成 / 追加一条 / 清空
结果区          名称、邮箱、地点、随机文本和记录 id
状态区          最近一次操作和错误文本

页面首次进入会自动生成三条人物资料。预览不是固定数据:每次点击批量生成都会通过 N-API 调用 Kotlin/Native Faker,返回一组新的 JSON 记录。

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

2.1 加入 ohosArm64 目标

core/build.gradle.kts 保留原有 JVM 约定,同时加入:

kotlin {
    ohosArm64()

    sourceSets {
        val jvmMain by getting {
            dependencies {
                implementation(libs.bundles.jackson)
                implementation(libs.icu4j)
                implementation(libs.rgxgen)
            }
        }
    }
}

JVM 专属依赖只放在 jvmMain。Native 源集使用 core/src/ohosArm64Main 中不依赖 JVM 的实现,避免将资源流、反射或 JVM-only 库带进 OpenHarmony 动态库。

2.2 Native focused build 的作用

example/nativeApp 构建一个受 linker map 约束的 shared library:

kotlin {
    ohosArm64 {
        binaries.sharedLib {
            baseName = "kotlin_faker"
            linkerOpts(
                "--entry=0",
                "--version-script=${project.file("src/ohosArm64Main/linker/shared-library.map")}",
            )
            linkerOpts("-lace_napi.z", "-luv", "-lhilog_ndk.z")
        }
    }
}

linker map 只导出交互门面所需的函数:

FakerCatalog
FakerGet
FakerRandom
FakerGenerate
FakerRunChecks
FakerFree
2.3 配置仓库和独立消费工程

example/settings.gradle.kts 使用 OpenHarmony 社区 Maven、Maven Central 和 Gradle Plugin Portal:

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()
    }
}

示例通过 composite build 使用根工程的 io.github.serpro69:kotlin-faker,不要求先发布临时包:

includeBuild("..")
2.4 通过构建产物消费共享库

prepareOhos 在 Native 链接成功后复制 .so 和 C 头文件:

val prepareOhos by tasks.registering(Copy::class) {
    dependsOn("linkDebugSharedOhosArm64")
    from(layout.buildDirectory.dir("bin/ohosArm64/debugShared")) {
        include("libkotlin_faker.so")
        into("libs/arm64-v8a")
    }
    from(layout.buildDirectory.dir("bin/ohosArm64/debugShared")) {
        include("libkotlin_faker_api.h")
        into("src/main/cpp/include")
    }
    into(rootProject.layout.projectDirectory.dir("ohosApp/entry"))
}

动态库和生成头文件属于本地构建产物,仓库通过 .gitignore 排除。每台开发机可以从源码重新生成和自身 SDK 匹配的文件。

第 3 阶段:Faker 与序列化

3.1 为什么需要统一 JSON 契约
ArkTS 操作
        ↓ mode + count
FakerClient.ets
        ↓ N-API
napi_init.cpp
        ↓ C ABI
FakerExamples.generate
        ↓ Kotlin/Native
JSON records
        ↓
ArkUI ForEach 列表

页面只消费解析后的不可变记录,不重新实现姓名、地址和邮箱生成规则。这样 JVM 测试、Native 动态库和 ArkUI 页面走的是同一份共享门面。

3.2 FakerConfig 和 Native Faker
public class Faker(
    public val config: FakerConfig = fakerConfig {},
) {
    public val random: RandomProvider
    public val name: Name
    public val address: Address
    public val internet: Internet
    public val lorem: Lorem
}

Native Provider 使用固定的轻量数据表和 kotlin.random.Random,避免读取 JVM locale 资源。JVM 端仍然加载完整 locale 字典,因此两端的可用范围不同,但共同 API 的调用方式保持一致。

3.3 场景化批量生成
public fun generate(mode: Int, count: Int): List<FakerExample> {
    require(mode in 0..2) { "Unknown Faker mode: $mode" }
    require(count in 1..8) { "Faker count must be between 1 and 8" }
    val faker = Faker()
    return (0 until count).map { index ->
        when (mode) {
            0 -> person(faker, index)
            1 -> contact(faker, index)
            else -> text(faker, index)
        }
    }
}
3.4 自检和错误边界

FakerExamples.runChecks() 覆盖八项公共检查:确定性记录、姓名、邮箱、城市、随机字符串边界、随机整数边界、配置实例和不可变 JSON 契约。Native 异常转换为 {"error":"..."},C++ 创建 ArkTS 字符串后立即调用 FakerFree。

第 4 阶段:原生桥接(技术难点)

4.1 Kotlin/Native 对象不能直接交给 ArkTS
ArkTS
  │ JSON string
  ▼
C++ N-API entry
  │ const char*
  ▼
Kotlin/Native C ABI
  │ FakerExamples
  ▼
UTF-8 JSON + explicit free
4.2 方案对比
方案优点缺点选用
直接导出 Kotlin 对象代码少ABI、生命周期和类型不可控❌
只导出几个字符串实现简单页面需要自行拼装数据❌
C ABI + JSON边界清晰、易扩展、易调试有一次序列化开销✅
在 ArkTS 重写 Faker页面调用简单JVM/Native 与 ArkTS 逻辑分叉❌
4.3 Kotlin/Native 导出函数
@CName("FakerGenerate")
public fun generateNative(mode: Int, count: Int): CPointer<ByteVar> = response {
    FakerExamples.generate(mode, count)
        .joinToString(prefix = "[", postfix = "]") { it.toJson() }
}

@CName("FakerFree")
public fun freeNative(pointer: CPointer<ByteVar>?) {
    if (pointer != null) nativeHeap.free(pointer.rawValue)
}
4.4 C++ N-API 方法分发
napi_property_descriptor methods[] = {
    {"getCatalog", nullptr, Catalog, nullptr, nullptr, nullptr,
        napi_default, nullptr},
    {"getFaker", nullptr, GetFaker, nullptr, nullptr, nullptr,
        napi_default, nullptr},
    {"randomFaker", nullptr, RandomFaker, nullptr, nullptr, nullptr,
        napi_default, nullptr},
    {"generateFaker", nullptr, GenerateFaker, nullptr, nullptr, nullptr,
        napi_default, nullptr},
    {"runChecks", nullptr, RunChecks, nullptr, nullptr, nullptr,
        napi_default, nullptr},
};

generateFaker 会校验场景 0/1/2 和数量 1..8。Native 层先做参数校验,Kotlin 层再做业务范围校验。

4.5 N-API 生命周期
ArkTS generateFaker(mode, count)
        │
        ▼
napi_get_cb_info + argument check
        │
        ▼
FakerGenerate(mode, count)
        │
        ▼
napi_create_string_utf8(...)
        │
        ▼
FakerFree(nativeBuffer)
        │
        ▼
return JS string

第 5 阶段:交互工作台封装

5.1 ArkTS 调用 N-API Faker
import fakerNative from 'libentry.so';

export function generateFaker(mode: number, count: number): FakerExample[] {
  return JSON.parse(fakerNative.generateFaker(mode, count)) as FakerExample[];
}
5.2 场景和数量状态
const MODES: string[] = ['人物资料', '联系方式', '文本素材'];

@State private mode: number = 0;
@State private count: number = 3;
@State private records: FakerExample[] = [];

加减按钮把数量限制在 1..8,场景切换后立即生成新列表。

5.3 列表状态和操作
private appendOne(): void {
  const next: FakerExample[] = generateFaker(this.mode, 1);
  this.records = next.concat(this.records).slice(0, 8);
}

private clearRecords(): void {
  this.records = [];
  this.status = '列表已清空';
}
5.4 页面交互预设

页面提供人物资料、联系方式和文本素材三个真实数据场景;结果卡片展示姓名、邮箱、地点、随机文本和记录 id。截图中的 6 条、人物资料选中态、批量生成、追加一条、清空和多条结果卡片均来自当前 ArkUI 页面。

第 6 阶段:示例与验证

6.1 example 工程结构
example/
├── shared/
│   ├── src/commonMain/.../FakerExamples.kt
│   └── src/commonTest/.../FakerExamplesTest.kt
├── nativeApp/
│   ├── src/ohosArm64Main/.../NativeBridge.kt
│   └── src/ohosArm64Main/linker/shared-library.map
└── ohosApp/
    ├── AppScope/
    ├── entry/src/main/cpp/
    │   ├── CMakeLists.txt
    │   └── napi_init.cpp
    └── entry/src/main/ets/
        ├── faker/FakerClient.ets
        └── pages/Index.ets
6.2 原生模块注册

napi_init.cpp 通过 napi_module_register 注册 entry 模块,类型声明位于:

example/ohosApp/entry/src/main/cpp/types/libentry/index.d.ts

ArkTS 使用:

import fakerNative from 'libentry.so';
6.3 Native 动态库准备
export JAVA_HOME="/path/to/jdk-21"
./scripts/build-openharmony.sh

成功后生成:

example/ohosApp/entry/libs/arm64-v8a/libkotlin_faker.so
example/ohosApp/entry/src/main/cpp/include/libkotlin_faker_api.h
6.4 构建、签名和安装

未配置签名时,可以在 DevEco Studio 构建未签名 HAP;真机安装需要签名 HAP。配置签名后执行:

python3 scripts/prepare-signing-project.py /path/to/kotlin-faker-signing
./scripts/build-hap.sh /path/to/kotlin-faker-signing

签名证书、profile、p12 和密码只保存在本机,不要提交到 AtomGit。

四、完整代码对照

4.1 整体架构

ArkUI Index.ets
    │ mode + count
    ▼
FakerClient.ets
    │ N-API
    ▼
libentry.so / napi_init.cpp
    │ C ABI
    ▼
libkotlin_faker.so
    │ Kotlin/Native
    ▼
FakerExamples.generate -> Faker -> Faker Provider -> JSON

4.2 文件清单

文件职责
core/src/ohosArm64Main/.../Faker.ktNative FakerConfig、Faker 和核心 Provider
example/shared/.../FakerExamples.kt场景化记录、批量生成和共享自检
example/shared/.../FakerExamplesTest.ktJVM 公共门面测试
example/nativeApp/.../NativeBridge.ktC ABI、JSON 返回和内存释放
example/ohosApp/.../FakerClient.etsN-API JSON 解析和类型封装
example/ohosApp/.../Index.ets交互式生成工作台
example/ohosApp/entry/src/main/cpp/napi_init.cppN-API 导出和参数检查
scripts/build-openharmony.sh测试、Native 链接和产物复制
scripts/build-hap.sh已配置签名工程的 HAP 构建
scripts/prepare-signing-project.py复制独立签名工程
docs/openharmony/images/kotlin-faker-workbench.jpg交互页面效果图

4.3 关键 API 对照

层次API作用
KotlinFakerConfig配置 locale 和随机源
KotlinFaker.name生成名字和全名
KotlinFaker.address生成城市、国家和街道
KotlinFaker.internet生成用户名和邮箱
KotlinFaker.random生成随机值和字符串
SharedFakerExamples.generate生成场景化批量记录
NativeFakerGenerate返回记录数组 JSON
N-APIgenerateFaker向 ArkTS 暴露批量生成
ArkTSgenerateBatch更新页面列表

4.4 ArkTS 与 Kotlin 的边界

ArkTS 只负责交互状态和渲染:

this.records = generateFaker(this.mode, this.count);

Kotlin 负责生成数据:

val records = FakerExamples.generate(mode, count)

两者之间只传递整数参数和 JSON 字符串,不传递 Kotlin 对象、ArkTS class 实例或未校验的动态结构。

五、关键决策说明

决策 1:保留 JVM 完整实现,Native 提供轻量核心

原始字典服务依赖 JVM 资源流、Jackson、ICU4J 和反射,直接搬到 Native 会破坏原有 JVM 构建。拆分目标后,JVM 用户保持完整能力,OpenHarmony 获得可链接核心 API。

决策 2:把 ohosArm64 加入 core 和 example

只有真正编译 ohosArm64 动态库,才能证明 Faker 逻辑可以进入 OpenHarmony 运行时,而不是只在 JVM 示例里通过。

决策 3:独立消费者通过构建产物消费

example 单独解析 core,DevEco 工程单独接收 .so 和头文件,避免根工程编译通过却无法在 HAP 中打包。

决策 4:JSON 作为跨语言数据契约

JSON 让 ArkTS、C++ 和 Kotlin/Native 的边界清晰可调试,并允许后续增加字段而不暴露内部对象布局。

决策 5:交互页面调用真实批量 API

场景、数量、追加和清空都通过 FakerGenerate 进入 Kotlin/Native,页面只负责状态管理和展示,避免把适配做成固定数据 Demo。

决策 6:把库验证和页面验证分开

JVM 测试验证共享门面,Native 链接验证 ABI,CMake/ArkTS 验证宿主,HAP 验证打包,真机验证页面操作和安装环境。每一层都有明确失败边界。

六、测试与验证

6.1 测试环境

本次验证使用 macOS、JDK 21、Kotlin Multiplatform 2.2.21-1.0.0、DevEco Studio OpenHarmony Native SDK、ARM64 HAP 构建链路和可选的 hdc。

6.2 静态检查与单元测试

JAVA_HOME=/path/to/jdk-21 ./gradlew :kotlin-faker:jvmTest
(cd example && JAVA_HOME=/path/to/jdk-21 ./gradlew :shared:jvmTest)
JAVA_HOME=/path/to/jdk-21 ./gradlew spotlessCheck

6.3 原生桥接和 HAP 验证

JAVA_HOME=/path/to/jdk-21 ./scripts/build-openharmony.sh
python3 scripts/check-native-deps.py \
  /Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/native \
  example/ohosApp/entry/libs/arm64-v8a
python3 scripts/prepare-signing-project.py /path/to/kotlin-faker-signing
JAVA_HOME=/path/to/jdk-21 ./scripts/build-hap.sh /path/to/kotlin-faker-signing

本次已验证:

JVM shared tests: BUILD SUCCESSFUL
ohosArm64 Native link: BUILD SUCCESSFUL
libkotlin_faker.so: 0 unresolved strong imports
Hvigor HAP build: BUILD SUCCESSFUL

6.4 功能验证用例

用例 1:默认页面和初始生成

启动页面后默认选中“人物资料”,生成数量为 3,列表出现 3 条实时生成数据。

用例 2:切换三种场景

依次点击人物资料、联系方式和文本素材,确认选中态切换,结果列表被替换为对应字段组合。

用例 3:调整批量数量

点击加减按钮,将数量从 1 调到 8,再点击“批量生成”,确认列表条数与数量一致。

用例 4:追加一条

点击“追加一条”,确认新记录出现在列表顶部,列表最多保持 8 条。

用例 5:清空结果

点击“清空”,确认列表消失、状态显示“列表已清空”,页面出现空状态提示。

用例 6:重复批量生成

保持场景和数量不变,连续点击“批量生成”,确认姓名、邮箱、地点或随机文本会重新生成。

6.5 验证结论

自动测试、Kotlin/Native ARM64 链接、ELF 依赖检查、Hvigor CMake/ArkTS 编译和未签名 HAP 构建均已完成。交互工作台调用的是 Kotlin/Native Faker 真实结果,页面可以完整演示库的核心功能。

七、运行效果

7.1 页面截图

在这里插入图片描述

截图中可以看到:

  • 页面标题为“Kotlin Faker”;
  • 副标题为“真实数据生成工作台”;
  • 顶部显示当前结果条数;
  • 三个生成场景有明确选中态;
  • 数量控制和批量生成、追加、清空按钮均可操作;
  • 结果卡片展示姓名、邮箱、地点、随机文本和记录 id;
  • 页面内容来自 Kotlin/Native Faker,不是固定图片数据。

7.2 命令速查

export JAVA_HOME="/path/to/jdk-21"
./scripts/build-openharmony.sh
(cd example && ./gradlew :shared:jvmTest)
python3 scripts/check-native-deps.py \
  /Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/native \
  example/ohosApp/entry/libs/arm64-v8a
python3 scripts/prepare-signing-project.py /path/to/kotlin-faker-signing
./scripts/build-hap.sh /path/to/kotlin-faker-signing

八、遗留问题与改进方向

8.1 踩坑复盘

  1. 只改 ArkTS 页面不算 KMP 适配:必须把共享 Faker 逻辑真正编译成 ohosArm64 动态库。
  2. JVM 依赖不能进入 Native:字典服务和 ICU/Jackson 需要与 Native Provider 分开。
  3. N-API 不负责业务生成:C++ 只做类型检查、字符串转换和释放,Faker 语义放在 Kotlin。
  4. 批量数据需要边界:数量限制在 1..8,避免页面一次生成过多记录造成滚动和性能问题。
  5. 签名与构建分开:未签名 HAP 能验证工程,证书和 profile 只在独立工程中配置。

8.2 已知问题

  • OpenHarmony Native 当前交付的是核心 Faker Provider 子集,不包含 JVM 端所有 locale 字典和领域模块;
  • 当前示例是单页面生成工作台,多页面应用需要在业务层集中管理 Faker 实例和列表状态;
  • 设备安装和运行仍需要 ARM64 OpenHarmony 设备以及匹配的签名 profile。

8.3 未来优化方向

  • 将 Native Provider 数据表拆分为可更新的 commonMain 字典资源;
  • 增加 locale 选择和中文姓名、地址数据集;
  • 为 CMP 页面提供 Compose Multiplatform 共享 UI 状态层;
  • 增加复制 JSON、导出 CSV 和自定义字段模板;
  • 在持续集成中加入 Native 链接、HAP 未签名构建和 AtomGit 自动检查任务。

九、总结

9.1 核心难点回顾

Kotlin Faker Provider
    → Kotlin/Native ohosArm64
    → C ABI
    → C++ N-API
    → ArkTS FakerClient
    → ArkUI 交互工作台

9.2 封装层次

  • JVM 层:保留完整字典和原有 Faker Provider;
  • Native 层:提供可链接的核心 Faker Provider 和 ARM64 动态库;
  • Shared 层:组合人物、联系方式和文本素材生成门面;
  • N-API 层:完成参数检查、JSON 转换和 Native 内存释放;
  • ArkTS 层:管理场景、数量、列表、错误和页面视觉展示;
  • DevEco 层:完成 CMake、HAP、签名、安装和运行。

9.3 三条经验

  1. 先让共享 Faker 门面在 JVM 和 Native 通过,再接入 ArkUI;
  2. 用 JSON 和少量 C ABI 代替跨语言对象传递;
  3. 把自动测试、HAP 构建和页面交互分别记录,避免把“编译成功”误认为“功能可用”。

9.4 适配成果

当前 kotlin-faker 已完成:

  • ohosArm64 Kotlin/Native 目标;
  • JVM 完整实现与 Native 核心实现的依赖隔离;
  • FakerConfig、Faker、随机数、姓名、地址、网络和文本 Provider;
  • Kotlin/Native + C ABI + C++ N-API 桥接;
  • 人物资料、联系方式、文本素材三种交互场景;
  • 批量生成、追加一条、清空和结果列表;
  • 未签名 HAP 构建、ARM64 ELF 依赖检查和效果图;
  • AtomGit 项目文档、构建脚本和签名工程准备流程。

适配过程 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。

参考文档

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/2501_94452576/article/details/169070030

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--