Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kmptpc_kotlin_capi_sample_IR001_SR002
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zhangying
kmptpc_kotlin_capi_sample_IR001_SR002
Commits
554d9283
Commit
554d9283
authored
Feb 12, 2026
by
zhangying
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改
parent
0f31a59a
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
61 additions
and
133 deletions
+61
-133
README.md
README.md
+61
-133
No files found.
README.md
View file @
554d9283
# KMP
-CAPI HarmonyOS Interop 示例项目
# KMP
–HarmonyOS C-API 互操作示例
本项目
是一个 Kotlin Multiplatform (KMP) 工程,展示了如何在 HarmonyOS (OpenHarmony) 平台上,通过 Kotlin/Native 与 HarmonyOS 的 C-API (ArkUI Native Node API & Custom Dialog API) 进行深度交互
。
本项目
以 HarmonyOS C-API 为主体,展示 Kotlin/Native 调用鸿蒙 C-API 的通用方法论与工程实践。Demo 中的 AV 能力查询与 ArkUI 自定义弹窗只是示例,工程结构可扩展到任意 C-API(Ability、ArkUI、AVCodec、Window、Telephony 等)
。
核心特色:
**在 Kotlin/C++ 侧直接构建原生 UI 并控制系统组件,无需完全依赖 ArkTS。**
**核心价值**
-
在 Kotlin 侧以类型安全的方式封装鸿蒙 C-API
-
通过
`@CName`
暴露函数给 C++/NAPI,供 ArkTS/Harmony 应用侧调用
-
使用 Gradle 产出
`.so`
与头文件,Harmony 工程通过 CMake IMPORTED 链接
## 1. 项目结构
## 1. 项目结构
*
**`composeApp/`**
: KMP 共享代码模块。
-
composeApp:KMP 主模块
*
`src/commonMain`
: 跨平台通用业务逻辑。
-
src/commonMain:跨平台通用逻辑
*
`src/ohosArm64Main`
:
**[核心]**
HarmonyOS 特有的 Kotlin/Native 实现。包含与 C-API 交互的绑定(
`cinterop`
)和导出给 C++ 的接口(
`OhosExports.kt`
)。
-
src/ohosArm64Main:鸿蒙专属实现,包含 C-API 绑定与
`@CName`
暴露(示例:AV 能力查询)
*
**`harmonyApp/`**
: HarmonyOS 原生工程(DevEco Studio 工程)。
-
构建输出:
`build/bin/ohosArm64/<type>Shared/libkn.so`
、
`libkn_api.h`
*
`entry/src/main/cpp`
:
**[核心]**
C++ 桥接层(NAPI)。负责实现具体的 UI 构建逻辑(
`entry_module.cpp`
),并将 Kotlin 接口暴露给 ArkTS。
-
harmonyApp:HarmonyOS 原生工程
*
`entry/src/main/ets`
: ArkTS UI 界面,作为应用入口。
-
entry/src/main/cpp:NAPI 桥接层(示例:AVCodecKit 导出),CMake 以 IMPORTED 链接
`libkn.so`
-
entry/src/main/ets:ArkTS UI 与页面逻辑
-
iosApp:Xcode 工程(与本文无关)
参考文件
-
Kotlin
`@CName`
示例:
[
AVCapability.kt
](
file:///Users/liluo/mine/projects/kmp/kmptpc_kotlin_capi_sample_ir001_sr002/composeApp/src/ohosArm64Main/kotlin/com/example/test/AVCodecKit/AVCapability.kt
)
-
NAPI 导出示例:
[
AVCodecKit.cpp
](
file:///Users/liluo/mine/projects/kmp/kmptpc_kotlin_capi_sample_ir001_sr002/harmonyApp/entry/src/main/cpp/kits/AVCodecKit.cpp
)
-
CMake 链接:
[
CMakeLists.txt
](
file:///Users/liluo/mine/projects/kmp/kmptpc_kotlin_capi_sample_ir001_sr002/harmonyApp/entry/src/main/cpp/CMakeLists.txt
)
-
ETS 入口:
[
ResourceAbility.ets
](
file:///Users/liluo/mine/projects/kmp/kmptpc_kotlin_capi_sample_ir001_sr002/harmonyApp/entry/src/main/ets/entryability/ResourceAbility.ets
)
## 2. 环境要求
## 2. 环境要求
*
**IDE**
:
-
IDE
*
IntelliJ IDEA / Android Studio (用于编写 Kotlin 代码)
-
Android Studio(用于 Gradle 同步与 KMP 构建,推荐 2024.2+)
*
DevEco Studio (用于编译和运行 HarmonyOS 应用)
-
DevEco Studio(用于 Harmony 工程构建与真机调试,推荐最新稳定版)
*
**SDK**
:
-
SDK/工具
*
HarmonyOS SDK (API 12+ / OpenHarmony 5.0+) -
**必须支持 ArkUI Native Node API**
-
OpenHarmony/HarmonyOS SDK:API 12+(示例工程使用 6.0.1 target 21)
*
**语言**
:
-
Gradle Wrapper:项目内置
`./gradlew`
*
Kotlin 1.9+
-
JDK:17
*
Java 17+
-
HDC:随 DevEco Studio 安装
*
C++ (CMake)
## 3. 启动与运行(以 C-API 能力为对象)
## 3. 如何启动运行
### 步骤 1:在 Android Studio 同步并发布 KMP 产物
### 步骤 1: 编译 Kotlin/Native 产物
-
打开项目根目录,等待 Gradle Sync 完成
在项目根目录下运行以下命令,将 Kotlin 代码编译为动态库(
`libkn.so`
)并发布到 HarmonyOS 工程中:
-
在 Gradle 工具窗口执行:
-
`composeApp > Tasks > publishDebugBinariesToHarmonyApp`
-
或
`publishReleaseBinariesToHarmonyApp`
-
期望结果:
-
`harmonyApp/entry/libs/arm64-v8a/libkn.so`
存在
-
`harmonyApp/entry/src/main/cpp/include/libkn_api.h`
存在
命令行等价:
```
bash
```
bash
./gradlew publishDebugBinariesToHarmonyApp
./gradlew publishDebugBinariesToHarmonyApp
# 或
./gradlew publishReleaseBinariesToHarmonyApp
```
```
*此任务会自动将生成的 `.so` 文件和头文件复制到 `harmonyApp/entry/libs` 和 `harmonyApp/entry/src/main/cpp/include` 目录。*
### 步骤 2: 运行 HarmonyOS 应用
1.
使用
**DevEco Studio**
打开
`harmonyApp`
目录。
2.
等待 Sync 完成。
3.
连接 HarmonyOS 真机或启动模拟器(API 12+)。
4.
点击
**Run 'entry'**
。
---
## 4. 核心功能详解:Kotlin 调用 HarmonyOS Native 弹窗
本项目成功实现了一个复杂的场景:
**在 C++ 层构建 UI 节点树,传递给 Kotlin 层,再由 Kotlin 层调用 ArkUI C-API 显示原生自定义弹窗。**
### 实现原理
1.
**C++ (ArkUI Node API)**
: 动态创建 UI 组件树(Column, Row, Text, Button)。
2.
**Kotlin/Native (Interop)**
: 接收 C++ 创建的 Node 指针,封装为
`ArkUI_CustomDialogOptions`
。
3.
**ArkUI Dialog API**
: 调用
`OH_ArkUI_CustomDialog_OpenDialog`
显示弹窗。
### 详细实现步骤
#### 1. C++ 侧构建复杂 UI (`entry_module.cpp`)
我们在 C++ 中使用
`ArkUI_NativeNodeAPI_1`
手动构建一个包含标题栏、内容区和底部按钮的复杂布局。
```
cpp
// 示例:创建复杂的弹窗内容节点
ArkUI_NodeHandle
root
=
api
->
createNode
(
ARKUI_NODE_COLUMN
);
// 设置 Padding
ArkUI_NumberValue
paddingValue
[]
=
{{.
f32
=
12.0
f
},
{.
f32
=
12.0
f
},
...};
api
->
setAttribute
(
root
,
NODE_PADDING
,
&
paddingItem
);
// 创建标题栏 (Row)
### 步骤 2:在 DevEco Studio 构建并运行 Harmony 工程
ArkUI_NodeHandle
titleRow
=
api
->
createNode
(
ARKUI_NODE_ROW
);
-
打开
`harmonyApp`
目录,等待 hvigor/ohpm 同步
ArkUI_NodeHandle
titleText
=
CreateTextNode
(
api
,
"标题"
,
20.0
f
);
-
校验 CMake IMPORTED 链接是否正确指向
`libkn.so`
ArkUI_NodeHandle
closeBtn
=
CreateTextNode
(
api
,
"X"
,
20.0
f
);
-
连接真机或模拟器(API 12+)
-
选择
`entry`
模块,点击 Run,观察日志与 UI 行为
// 注册点击事件 (关闭弹窗)
## 4. 通用互操作模式(如何扩展到更多 C-API)
api
->
registerNodeEvent
(
closeBtn
,
NODE_ON_CLICK
,
0
,
nullptr
);
api
->
addNodeEventReceiver
(
closeBtn
,
OnCloseDialog
);
// OnCloseDialog 调用 closeBasicDialog()
// ... 组装节点树 ...
1.
在
`composeApp/src/ohosArm64Main`
中为目标 C-API 编写 Kotlin 封装
api
->
addChild
(
root
,
titleRow
);
-
通过 cinterop 绑定原生头文件
api
->
addChild
(
root
,
contentText
);
-
定义
`@CName("...")`
函数作为对外稳定接口
api
->
addChild
(
root
,
buttonRow
);
2.
在
`harmonyApp/entry/src/main/cpp/kits`
中添加或更新 NAPI 导出
-
为
`@CName`
对应的函数创建 JavaScript/ArkTS 可调用的导出
3.
执行发布任务,将
`.so`
与头文件复制到 Harmony 工程
4.
在 ArkTS 页面中通过 NAPI 导出进行调用与展示
// 将生成的根节点指针转换为 long 传递给 Kotlin
说明:当前 demo 仅保留了 AV 能力查询相关的 28 项导出用于演示;工程结构允许你以相同模式扩展到任意 C-API 模块。
openBasicDialog
(
reinterpret_cast
<
int64_t
>
(
root
));
```
#### 2. Kotlin 侧定义弹窗逻辑 (`OhosExports.kt`)
Kotlin 侧通过
`@CName`
暴露接口给 C++,接收 Node 指针,并配置弹窗样式。
```
kotlin
@OptIn
(
kotlinx
.
cinterop
.
ExperimentalForeignApi
::
class
)
@CName
(
"openBasicDialog"
)
fun
openBasicDialog
(
nodeAddress
:
Long
):
Int
{
// 1. 将 long 转换回 C 指针
val
node
=
if
(
nodeAddress
==
0L
)
null
else
nodeAddress
.
toCPointer
<
COpaque
>()
if
(
node
==
null
)
return
-
31
// 2. 创建弹窗选项 (Options)
val
options
=
OH_ArkUI_CustomDialog_CreateOptions
(
node
)
// 3. 配置弹窗样式 (去除默认大圆角,设置白底)
OH_ArkUI_CustomDialog_SetModalMode
(
options
,
true
)
OH_ArkUI_CustomDialog_SetCornerRadius
(
options
,
10f
,
10f
,
10f
,
10f
)
// 设置 10vp 圆角
OH_ArkUI_CustomDialog_SetBackgroundColor
(
options
,
0
xFFFFFFFF
.
toUInt
())
// 白色背景
// 4. 定义回调 (DialogId 用于关闭)
val
cb
=
staticCFunction
{
dialogId
:
Int
->
lastDialogId
=
dialogId
// 保存 ID 用于后续关闭
Unit
}
// 5. 打开弹窗
val
code
=
OH_ArkUI_CustomDialog_OpenDialog
(
options
,
cb
)
return
code
}
```
#### 3. C++ 侧事件处理与关闭
当用户点击 C++ 创建的按钮时,触发回调,调用 Kotlin 暴露的关闭函数。
```
cpp
// entry_module.cpp
void
OnCloseDialog
(
ArkUI_NodeEvent
*
event
)
{
closeBasicDialog
();
// 调用 Kotlin 暴露的关闭函数
}
// OhosExports.kt
@
CName
(
"closeBasicDialog"
)
fun
closeBasicDialog
()
:
Int
{
return
OH_ArkUI_CustomDialog_CloseDialog
(
lastDialogId
)
}
```
#### 4. ArkTS 入口调用
最终在 ArkTS 侧,只需要简单地调用 NAPI 暴露的方法即可触发整个流程。
```
typescript
// Index.ets
import
{
openBasicDialog
}
from
'libentry.so'
;
Button
(
"Options样式弹窗"
)
.
onClick
(()
=>
{
// 触发 C++ -> Kotlin -> ArkUI Native 的调用链
openBasicDialog
();
})
```
## 5. 常见问题排查
## 5. 常见问题排查
*
**Crash (SIGSEGV)**
: 通常是因为传递了无效的 Node 指针给
`OH_ArkUI_CustomDialog_CreateOptions`
。请确保 Node 已正确创建且未被释放。
-
`.so`
或头文件缺失:未执行发布任务或路径不正确
*
**弹窗样式异常(大圆角/透明)**
: 默认系统样式可能带有较大的圆角。使用
`OH_ArkUI_CustomDialog_SetCornerRadius`
和
`OH_ArkUI_CustomDialog_SetBackgroundColor`
进行显式配置。
-
NAPI 映射异常:导出函数名与
`@CName`
不一致
*
**Error -31**
: 自定义错误码,表示传入的 Node 指针为空。
-
设备构建失败:SDK 版本与
`build-profile.json5`
不匹配
---
---
Happy Coding with KMP & HarmonyOS!
欢迎基于本工程快速集成与验证更多 HarmonyOS C-API 能力。
*** End Patch**
*)}$** End Patch***
}$ ?
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment