@harmonyos-arkts/d2h 0.1.19 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +40 -0
- package/agents/android-to-hmos-00-orchestrator.md +3 -315
- package/agents/d2h.md +53 -38
- package/contracts/workflow/artifacts.md +22 -0
- package/contracts/workflow/delivery.md +54 -0
- package/contracts/workflow/dispatch.md +26 -0
- package/contracts/workflow/execution.md +125 -0
- package/contracts/workflow/generation.md +40 -0
- package/contracts/workflow/orchestration.md +49 -0
- package/contracts/workflow/overview.md +58 -0
- package/contracts/workflow/plan.md +119 -0
- package/contracts/workflow/scope.md +151 -0
- package/dist/bin/install-opencode.js +34 -15
- package/dist/src/install-codex.js +131 -0
- package/dist/src/install-opencode.js +5 -5
- package/dist/src/workflow.js +54 -0
- package/docs/architecture-plan-guide.zh-CN.md +70 -0
- package/docs/incremental-spec-evaluation-design.md +670 -0
- package/docs/spec-plan-guide.md +226 -0
- package/docs/workflow-decoupling.md +59 -0
- package/opencode/interactive-tools/advance-progress-demo.mjs +21 -0
- package/opencode/interactive-tools/browser-host.ts +110 -0
- package/opencode/interactive-tools/core.ts +242 -0
- package/opencode/interactive-tools/demo-workflow.ts +55 -0
- package/opencode/interactive-tools/demo.mjs +37 -0
- package/opencode/interactive-tools/package-lock.json +1876 -0
- package/opencode/interactive-tools/package.json +23 -0
- package/opencode/interactive-tools/panel.ts +40 -0
- package/opencode/interactive-tools/prepare-demo.mjs +17 -0
- package/opencode/interactive-tools/prepare-progress-demo.mjs +13 -0
- package/opencode/interactive-tools/progress.ts +118 -0
- package/opencode/interactive-tools/server-legacy.mjs +2 -0
- package/opencode/interactive-tools/server.mjs +40 -0
- package/opencode/interactive-tools/tui.tsx +230 -0
- package/package.json +9 -1
- package/schemas/native-libs-analysis-report.schema.json +695 -0
- package/schemas/native-libs-verify-report.schema.json +566 -0
- package/schemas/spec-native-libs-shard.schema.json +110 -0
- package/skills/arkts-icon-sizing/SKILL.md +0 -10
- package/skills/cpp/d2h-native-library-analyse/SKILL.md +91 -0
- package/skills/cpp/d2h-native-library-analyse/scripts/analyse-android-so.py +630 -0
- package/skills/cpp/d2h-native-library-build/SKILL.md +403 -0
- package/skills/cpp/d2h-native-library-build/references/build-config-mapping.md +180 -0
- package/skills/cpp/d2h-native-library-build/references/jni-to-napi-mapping.md +74 -0
- package/skills/cpp/d2h-native-library-build/scripts/check-android-so.py +580 -0
- package/skills/cpp/d2h-native-library-verify/SKILL.md +111 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-build-sign-run.md +67 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/AppScope/app.json5 +1 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/AppScope/resources/base/element/string.json +1 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/README.md +25 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/build-profile.json5 +24 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/build-profile.json5 +1 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/hvigorfile.ts +2 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/oh-package.json5 +1 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/src/main/ets/entryability/EntryAbility.ets +5 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/src/main/ets/pages/Index.ets +3 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/src/main/ets/pages/NativeVerifyDemo.ets +276 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/src/main/module.json5 +1 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/src/main/resources/base/element/color.json +1 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/src/main/resources/base/element/string.json +1 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/src/main/resources/base/profile/main_pages.json +1 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/src/ohosTest/ets/test/FFmpegVerify.test.ets +176 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/src/ohosTest/ets/test/List.test.ets +2 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/entry/src/ohosTest/module.json5 +1 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/hvigor/hvigor-config.json5 +1 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/hvigorfile.ts +2 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-project-template/oh-package.json5 +9 -0
- package/skills/cpp/d2h-native-library-verify/references/demo-template.md +176 -0
- package/skills/cpp/d2h-native-library-verify/references/hypium-test-template.md +163 -0
- package/skills/cpp/d2h-native-library-verify/scripts/__pycache__/native_common.cpython-313.pyc +0 -0
- package/skills/cpp/d2h-native-library-verify/scripts/device-verify.py +304 -0
- package/skills/cpp/d2h-native-library-verify/scripts/native_common.py +341 -0
- package/skills/cpp/d2h-native-library-verify/scripts/verify-ohos-native.py +1099 -0
- package/skills/d2h-app-solution/SKILL.md +198 -0
- package/skills/d2h-app-solution/agents/openai.yaml +4 -0
- package/skills/d2h-app-solution/references/framework-evidence.md +117 -0
- package/skills/d2h-app-solution/references/hierarchy-rules.md +88 -0
- package/skills/d2h-app-solution/references/inventory-schema.md +305 -0
- package/skills/d2h-app-solution/references/technical-analysis.md +101 -0
- package/skills/d2h-app-solution/scripts/scan_repositories.py +350 -0
- package/skills/d2h-app-solution/scripts/validate_inventory.py +337 -0
- package/skills/d2h-architecture-plan/SKILL.md +35 -0
- package/skills/d2h-architecture-plan/references/directory-creation.md +43 -0
- package/skills/d2h-architecture-plan/references/hybrid-design.md +84 -0
- package/skills/d2h-architecture-plan/references/layout-reference.md +83 -0
- package/skills/d2h-architecture-plan/references/plan-contract.md +51 -0
- package/skills/d2h-architecture-plan/references/source-review.md +50 -0
- package/skills/d2h-cloud-knowledge/SKILL.md +28 -7
- package/skills/d2h-cloud-knowledge/kb_query.mjs +8 -0
- package/skills/d2h-dashboard/SKILL.md +56 -0
- package/skills/d2h-product-family-migration/SKILL.md +103 -0
- package/skills/d2h-product-family-migration/agents/openai.yaml +3 -0
- package/skills/d2h-product-family-migration/assets/incremental-plan.template.md +55 -0
- package/skills/d2h-product-family-migration/references/advanced/behavioral-verification.md +59 -0
- package/skills/d2h-product-family-migration/references/advanced/existing-skill-integration.md +30 -0
- package/skills/d2h-product-family-migration/references/advanced/packaging-and-verification.md +43 -0
- package/skills/d2h-product-family-migration/references/advanced/platform-probes.md +26 -0
- package/skills/d2h-product-family-migration/references/advanced/product-line-design.md +40 -0
- package/skills/d2h-product-family-migration/references/baseline-and-delta.md +50 -0
- package/skills/d2h-product-family-migration/tests/markdown-cases.md +76 -0
- package/skills/{d2h-page-develop → d2h-spec-develop}/SKILL.md +143 -132
- package/skills/d2h-spec-develop/agents/openai.yaml +7 -0
- package/skills/d2h-spec-develop/references/worker-workflow.md +26 -0
- package/skills/{d2h-page-spec-generate → d2h-spec-generate}/SKILL.md +24 -13
- package/skills/d2h-spec-generate/assets/spec-template.md +109 -0
- package/skills/d2h-spec-generate/references/from-plan.md +19 -0
- package/skills/d2h-spec-generate/references/spec-content.md +34 -0
- package/skills/{d2h-page-spec-generate → d2h-spec-generate}/scripts/build_batch_report.py +35 -84
- package/skills/d2h-spec-plan/SKILL.md +38 -0
- package/skills/d2h-spec-plan/agents/openai.yaml +4 -0
- package/skills/d2h-spec-plan/references/architecture-handoff.md +9 -0
- package/skills/d2h-spec-plan/references/plan-contract.md +13 -0
- package/skills/d2h-spec-plan/references/planning-method.md +46 -0
- package/skills/d2h-spec-plan/references/round-scope-assessment.md +49 -0
- package/skills/d2h-spec-plan/references/work-packets.md +61 -0
- package/skills/d2h-utg-ai-generate/references/click-paths-schema.json +2 -2
- package/skills/d2h-utg-ai-generate/references/page-schema.json +2 -2
- package/skills/d2h-utg-ai-generate/references/utg-schema.json +2 -2
- package/skills/d2h-utg-static-generate/SKILL.md +2 -2
- package/skills/managing-d2h-toolchain/environment-requirements.json +1 -1
- package/skills/managing-d2h-toolchain/toolchain.json +1 -1
- package/skills/preparing-migration-workspace/SKILL.md +32 -2
- package/workflow/__pycache__/artifact_bindings.cpython-313.pyc +0 -0
- package/workflow/__pycache__/spec_runtime.cpython-313.pyc +0 -0
- package/workflow/artifact_bindings.py +224 -0
- package/workflow/assets/dashboard.html +88 -0
- package/workflow/build_batch_report.py +8 -0
- package/workflow/collect_code_metrics.py +75 -0
- package/workflow/dashboard_overview.py +109 -0
- package/workflow/delivery_view.py +82 -0
- package/workflow/feature_plan.py +234 -0
- package/workflow/page_batches.py +223 -0
- package/workflow/spec_generation.py +120 -0
- package/workflow/spec_runtime.py +890 -0
- package/workflow/work_packets.py +85 -0
- package/skills/d2h-page-develop/agents/openai.yaml +0 -7
- package/skills/harmonyos-migration-playbook/SKILL.md +0 -83
- package/skills/harmonyos-migration-playbook/agents/openai.yaml +0 -7
- package/skills/harmonyos-migration-playbook/references/arkts-compile.md +0 -24
- package/skills/harmonyos-migration-playbook/references/harmony-runtime.md +0 -53
- package/skills/harmonyos-migration-playbook/references/lesson-lifecycle.md +0 -45
- package/skills/harmonyos-migration-playbook/references/protocol-e2e.md +0 -23
- package/skills/harmonyos-migration-playbook/references/ui-automation.md +0 -53
- package/skills/harmonyos-migration-playbook/references/windows-environment.md +0 -38
- package/skills/native-library-substitution/SKILL.md +0 -385
- package/skills/native-library-substitution/references/native-library-substitution.json +0 -56906
- package/skills/native-library-substitution/references/native-library-substitution.md +0 -163
- package/skills/porting-cmake-native-libraries/SKILL.md +0 -57
- package/skills/porting-cmake-native-libraries/references/platform-adaptation.md +0 -49
- package/skills/porting-cmake-native-libraries/references/report-and-build.md +0 -60
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: d2h-native-library-build
|
|
3
|
+
description: Android C/C++ 库三种使用方式的鸿蒙适配解决方案。以「使用方式」为主线(① 源码编译成 .so/.a + JNI 引用 ② 源码集成后自己写脚本/patch 修改再编译 ③ 引入三方预编译 .so + 头文件),对每种情况给出:迁移前检查(scripts/check-android-so.py 判断现有 .so/.a 能否直接用于鸿蒙)→ 识别特征 → 分步处置方案 → 验证。内置编译与桥接共享参考(ndk-build/CMake/Gradle externalNativeBuild vs DevEco CMake/externalNativeOptions/OHOS NDK;JNI + System.loadLibrary vs NAPI + napi_module_register + import libxxx.so;类型映射)以及三方预编译库的替代决策树(查鸿蒙替代/获取上游源码/系统 API 重实现/裁剪+风险标记)。当用户需要把 C/C++ 原生库、.so、JNI 迁移/编译到鸿蒙,或询问「现有 so 能不能直接在鸿蒙用」「源码编译的 so 怎么迁」「带 patch 的源码怎么迁」「三方 so 没源码怎么办」「JNI 怎么转 NAPI」「so 怎么打包进鸿蒙」「VLC/ffmpeg 怎么在鸿蒙上用」「NDK 对应鸿蒙的什么」时触发。区别于 native-library-substitution(只提供替代包查询数据,本 Skill 负责三种情况的完整处置流程)。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Android C/C++ 库三种使用方式 → HarmonyOS 适配解决方案
|
|
7
|
+
|
|
8
|
+
本 Skill 以 Android 工程里 **C/C++ 库的三种使用方式**为主线,针对每种情况给出从「迁移前检查 → 识别特征 → 分步处置 → 验证」的完整方案。三种情况:
|
|
9
|
+
|
|
10
|
+
| 情况 | Android 侧使用方式 | 关键差异 | 处置主线 |
|
|
11
|
+
|------|--------------------|----------|----------|
|
|
12
|
+
| **①** | 源码编译成 .so/.a,用 JNI 引用 | 有完整源码 | 源码重编 + JNI→NAPI |
|
|
13
|
+
| **②** | 源码集成后,自己写脚本/patch 修改再编译成 .so | 有源码 + 修改脚本/patch | patch 适配 + 源码重编 + JNI→NAPI |
|
|
14
|
+
| **③** | 引入三方预编译 .so + 头文件 | **无源码** | 查替代 / 获取源码 / 系统 API 重实现 / 裁剪 |
|
|
15
|
+
|
|
16
|
+
> 三种情况的共同前提:**Android 编译出的 .so(无论自编还是三方)绝大多数不能直接放进鸿蒙工程**,原因是 Bionic libc 与 musl libc 的 ABI 不同、Android 系统库(`liblog.so`/`libandroid.so` 等)鸿蒙无同 ABI、JNI 依赖 ART 运行时(鸿蒙用 NAPI)、目标三元组不同(`aarch64-linux-android` vs `aarch64-linux-ohos`)。①②的解决方案是「重编+桥接改写」,③的解决方案是「替代/获取源码/重实现/裁剪」。
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 一、迁移前检查(先判断,再动手)
|
|
21
|
+
|
|
22
|
+
迁移第一步不是改代码,而是**先检查工程里已有的 .so/.a 能否直接用于鸿蒙**,并据此确定它属于哪种情况、该走哪条处置路线。
|
|
23
|
+
|
|
24
|
+
### 1.1 自动检查脚本
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# D2h 流程内推荐:按 facts/native-libs.json 分片清单对账检查(不重扫,含分片①②③初分类比对)
|
|
28
|
+
python3 scripts/check-android-so.py <Android工程目录> \
|
|
29
|
+
--from-facts <迁移工作区>/.migration/spec/facts/native-libs.json --json
|
|
30
|
+
|
|
31
|
+
# 独立使用:全工程扫描
|
|
32
|
+
python3 scripts/check-android-so.py <Android工程目录> # 文本报告
|
|
33
|
+
python3 scripts/check-android-so.py <Android工程目录> --json # 机器可读 JSON
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
脚本扫描工程下所有 `.so`/`.a`(或按 `--from-facts` 只查分片列出的产物),输出每个库的:架构、动态依赖(NEEDED)、SONAME、JNI 符号(`Java_*`/`JNI_OnLoad`)、Bionic 版本符号、Android 专用符号,以及「可直接使用 / 不能直接使用」结论 + 情况分类(①②③)+ 分步方案。`--from-facts` 模式还会回显分片的 `usageCase` 初分类与 `loadCalls` 清单供两边对账。
|
|
37
|
+
|
|
38
|
+
> 已知盲区:AAR/Maven 依赖内嵌的 `jniLibs/*.so` 不在工程仓库内,静态扫描与 `--from-facts` 都看不到——分片只会有 `loadCalls` 线索(`usageCase: load-only`)。遇到 load-only 线索时,先从 Gradle 缓存定位并解包对应 AAR(`~/.gradle/caches/modules-2/files-2.1/<group>/<artifact>/`,`unzip -l` 找 `jni/`),对解出的 .so 跑本脚本,再按情况③处置。
|
|
39
|
+
|
|
40
|
+
**跨平台(macOS / Linux / Windows)**,仅需 Python 3,且**不依赖 `file`**:文件类型用魔数判断、架构用 `llvm-readelf`/`readelf`,符号用 `llvm-nm`/`nm`。所需工具 `llvm-readelf`/`llvm-nm`/`llvm-objdump` 由 Android NDK 与 DevEco/OpenHarmony SDK 三平台同名自带;脚本自动发现顺序:① PATH → ② 环境变量 `ANDROID_NDK_HOME`/`ANDROID_HOME`/`OHOS_SDK_HOME`/`DEVECO_SDK_HOME` → ③ DevEco 内置 SDK 常见安装目录。Windows 未设 PATH 时,先设 `ANDROID_NDK_HOME`(指向 `ndk/<版本>`)或 `OHOS_SDK_HOME`(指向 SDK 根目录)即可。
|
|
41
|
+
|
|
42
|
+
### 1.2 判定规则(技术依据)
|
|
43
|
+
|
|
44
|
+
| 检查项 | 判定信号 | 含义 |
|
|
45
|
+
|--------|----------|------|
|
|
46
|
+
| JNI 桥接层 | 导出符号含 `Java_*` / `JNI_OnLoad` | 需 JNI→NAPI 改写 |
|
|
47
|
+
| Android 系统库 | `NEEDED` 命中 `liblog.so`/`libandroid.so`/`libnativehelper.so`/`libEGL.so` 等 | 需替换/重编 |
|
|
48
|
+
| Bionic 版本符号 | 未定义符号带 `@LIBC`/`@LIBLOG`/`@LIBDL` 等版本后缀 | 需 OHOS 工具链重编 |
|
|
49
|
+
| Android 专用符号 | 引用 `__android_log_*`/`AAssetManager_*`/`ANativeWindow_*` 等 | 需替换为鸿蒙 Native API |
|
|
50
|
+
| 静态库 | `.a`(ar archive),对象文件为 android 三元组 | 需 OHOS 工具链重编 |
|
|
51
|
+
|
|
52
|
+
任一「Android 特征」命中即判定**不能直接用**;全部未命中(musl/unversioned)才判定可直接用。
|
|
53
|
+
|
|
54
|
+
### 1.3 手动检查(无脚本时)
|
|
55
|
+
|
|
56
|
+
三平台可用 `llvm-readelf`/`llvm-nm`(NDK / DevEco SDK 自带)替代下面的 GNU 工具:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
readelf -h libfoo.so # 架构 + Class(ELF32/64)
|
|
60
|
+
readelf -d libfoo.so | grep -E 'NEEDED|SONAME' # 依赖
|
|
61
|
+
readelf -sW libfoo.so | grep -E 'Java_|JNI_OnLoad' # JNI 符号
|
|
62
|
+
nm -D -u libfoo.so | grep -E '@LIBC|__android' # Bionic 版本/专用符号
|
|
63
|
+
# 无 readelf 时:objdump -p libfoo.so | grep -E 'NEEDED|SONAME'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 1.4 情况识别:一眼定位三种情况
|
|
67
|
+
|
|
68
|
+
| 特征 | 情况 |
|
|
69
|
+
|------|------|
|
|
70
|
+
| 工程有 `CMakeLists.txt`/`Android.mk` + `.c/.cpp` 源码,`jniLibs` 里的 .so 由它编出 | **①** 源码编译 |
|
|
71
|
+
| 有源码 + `.patch`/`.diff` 文件或 `build.sh`/自定义 `.mk` 修改脚本 | **②** 源码+patch |
|
|
72
|
+
| 只有 `libs/<abi>/libxxx.so` + `include/*.h`,无源码、无构建脚本 | **③** 三方预编译 |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 二、情况①:源码编译成 .so/.a + JNI 引用
|
|
77
|
+
|
|
78
|
+
**现状**:你有完整 C/C++ 源码,`CMakeLists.txt`/`Android.mk` 把它编成 .so,Java/Kotlin 用 `System.loadLibrary` + `native`/`external` 方法通过 JNI 调用。
|
|
79
|
+
|
|
80
|
+
### 2.1 检查结论
|
|
81
|
+
|
|
82
|
+
现有 .so **不能直接用**(Bionic + JNI 依赖),但**有完整源码**,是三种情况里迁移成本最低的。核心工作 = **源码用 OHOS 工具链重编 + JNI 桥接层改写成 NAPI**。
|
|
83
|
+
|
|
84
|
+
### 2.2 处置流程
|
|
85
|
+
|
|
86
|
+
1. **盘点**:确认构建方式(CMake / ndk-build)、依赖的系统库、ABI 列表、JNI 接口清单(`Java_*` 方法签名)。
|
|
87
|
+
2. **源码重编**:
|
|
88
|
+
- `ndk-build`(`Android.mk`)→ 改写为 `CMakeLists.txt`(鸿蒙无 ndk-build)。
|
|
89
|
+
- 已有 `CMakeLists.txt` → 复用,改三点:目标三元组 `aarch64-linux-android`→`aarch64-linux-ohos`、日志库 `-llog`→`libhilog_ndk.z.so`、头文件 `<android/log.h>`→`<hilog/log.h>`。
|
|
90
|
+
- 详见「六、共享参考:构建与桥接映射」。
|
|
91
|
+
3. **建工程骨架**:DevEco 新建工程,`src/main/cpp/` 放源码,`build-profile.json5` 配 `externalNativeOptions` + `abiFilters`。
|
|
92
|
+
4. **JNI→NAPI 桥接改写**:按接口逐条把 `Java_com_xxx_xxx` / `JNI_OnLoad` 改成 `napi_value` 函数 + `napi_module_register`(见「6.3 JNI ↔ NAPI 桥接对照」)。
|
|
93
|
+
5. **ArkTS 封装 + .d.ts**:把 NAPI 裸接口包成 ArkTS class/对象。
|
|
94
|
+
6. **构建验证**:`hvigor` 构建,确认 `libs/<abi>/libxxx.so` 进 HAP;真机 `import libxxx.so` 调用验证。
|
|
95
|
+
|
|
96
|
+
### 2.3 识别到 JNI 桥接层的额外提示
|
|
97
|
+
|
|
98
|
+
- 若 .so 是「JNI 桥接层 + 核心库」分层(如 `libxxx.so` 桥接 JNI,`libxxx_core.so` 是纯 C 逻辑):核心库只需重编,桥接层重编 + 改写 NAPI,两层都要处理。
|
|
99
|
+
- 依赖的第三方 C/C++ 库同样按本情况重编,或用 `native-library-substitution` 查鸿蒙替代包。
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 三、情况②:源码集成 + 自己写脚本/patch 修改后编译
|
|
104
|
+
|
|
105
|
+
**现状**:你有上游源码 + 自己的一套修改脚本/patch(`.patch`/`.diff`、`build.sh`、自定义 `.mk`),跑完脚本才产出 .so。这比情况①多一层**平台差异适配**:你的 patch/脚本里通常含有 Android 特有代码。
|
|
106
|
+
|
|
107
|
+
### 3.1 检查结论
|
|
108
|
+
|
|
109
|
+
现有 .so **不能直接用**,但**有源码 + patch**。核心工作 = **在 OHOS 工具链下重放 patch/脚本 + 逐条适配 Android 特有代码 + JNI→NAPI 重编**。
|
|
110
|
+
|
|
111
|
+
### 3.2 处置流程
|
|
112
|
+
|
|
113
|
+
1. **盘点 patch/脚本内容**:grep 出脚本和 patch 里的 Android 特有引用(`__ANDROID__` 宏、`__android_log_*`、`AAssetManager_*`、`ANativeWindow_*`、`#include <android/...>`、`-llog`/`-landroid` 等)。
|
|
114
|
+
2. **重放 patch/脚本**:把构建目标切到 OHOS 工具链(`--target=aarch64-linux-ohos`),重跑修改脚本;patch 用 `git apply`/`patch` 在源码上重放。
|
|
115
|
+
3. **平台差异适配**:按「3.3 Android 特有 C/C++ API → 鸿蒙 Native API 对照」逐条替换 Android 特有 API。
|
|
116
|
+
4. **源码重编**:同情况①(CMake 改写 + `libhilog_ndk.z.so`)。
|
|
117
|
+
5. **JNI→NAPI 桥接改写**:同情况①。
|
|
118
|
+
6. **验证**:构建 + 真机调用,重点回归 patch 修改过的功能点。
|
|
119
|
+
|
|
120
|
+
### 3.3 Android 特有 C/C++ API → 鸿蒙 Native API 对照
|
|
121
|
+
|
|
122
|
+
| Android(patch 里常出现) | 鸿蒙对应 | 说明 |
|
|
123
|
+
|---------------------------|----------|------|
|
|
124
|
+
| `<android/log.h>` `__android_log_print` | `<hilog/log.h>` `OH_LOG_Print` | 日志 |
|
|
125
|
+
| `<android/asset_manager.h>` `AAssetManager_*` | `OH_ResourceManager_*`(rawfile) | 资源/文件 |
|
|
126
|
+
| `ANativeWindow_*` | `OH_NativeWindow_*` / XComponent `OH_NativeXComponent` | 渲染表面 |
|
|
127
|
+
| `ANativeActivity_*` | 无直接对应(NAPI + Ability 生命周期) | Activity 桥 |
|
|
128
|
+
| `AHardwareBuffer_*` | `OH_NativeBuffer_*` | 图形缓冲 |
|
|
129
|
+
| `ACameraManager_*` / `ACameraDevice_*` | `OH_Camera_*`(Camera NDK) | 相机 |
|
|
130
|
+
| `AMediaCodec_*` / `AMediaExtractor_*` | `OH_AVCodec_*` / `OH_AVFormat_*` | 音视频编解码 |
|
|
131
|
+
| `ASensorManager_*` | `OH_Sensor_*` | 传感器 |
|
|
132
|
+
| `AAudio_*` | `OH_Audio_*`(OHAudio) | 音频 |
|
|
133
|
+
| `AChoreographer_*` | 无直接对应 | 帧回调 |
|
|
134
|
+
| `JavaVM*` / `JNIEnv*` | `napi_env` | JNI→NAPI 环境 |
|
|
135
|
+
| `-llog` / `liblog.so` | `libhilog_ndk.z.so` | 日志库 |
|
|
136
|
+
| `-landroid` / `libandroid.so` | 拆分到各 Native 模块 | 系统库 |
|
|
137
|
+
| `<sys/system_properties.h>` `__system_property_get` | 无直接对应 | 系统属性 |
|
|
138
|
+
|
|
139
|
+
> 适配原则:先看鸿蒙是否有「同名语义」的 Native API(上表);没有则看能否用系统库/ArkTS 侧能力替代;再没有则重新实现该功能点并记录差异。
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 四、情况③:三方预编译 .so + 头文件(无源码)
|
|
144
|
+
|
|
145
|
+
**现状**:只有 `libs/<abi>/libxxx.so`(或 `jniLibs/`)和 `include/*.h`,**没有源码**。这是三种情况里最麻烦的,不能靠重编解决。
|
|
146
|
+
|
|
147
|
+
### 4.1 识别特征
|
|
148
|
+
|
|
149
|
+
- 工程里只有 `.so` + `.h`,无对应 `.c/.cpp`、无 `CMakeLists.txt`/`Android.mk`。
|
|
150
|
+
- 头文件只暴露 C/C++ API(可能是 `Java_*` 的 JNI 封装,也可能是纯 C API)。
|
|
151
|
+
- 用 `nm -D` 看导出符号可判断它是什么:有 `Java_*`/`JNI_OnLoad` → JNI 封装;纯 C 函数名 → 纯 C 库。
|
|
152
|
+
|
|
153
|
+
### 4.2 检查结论
|
|
154
|
+
|
|
155
|
+
预编译 Android .so **不能直接用于鸿蒙**:即使无 JNI、纯 C,也因 Bionic libc ABI 不同而无法加载;且无源码无法重编。必须走替代路线。
|
|
156
|
+
|
|
157
|
+
### 4.3 决策树(按优先级,命中即走)
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
三方预编译 .so + 头文件(无源码)
|
|
161
|
+
│
|
|
162
|
+
├─ 1. 查鸿蒙替代 / 鸿蒙化版 ──── 命中 → 用替代包(ohpm install / 官方鸿蒙 SDK)
|
|
163
|
+
│ · native-library-substitution(ohpm 2678 映射,含「C++/C鸿蒙化库」133 条)
|
|
164
|
+
│ · ohpm 仓库在线搜索:https://ohpm.harmonyos.com
|
|
165
|
+
│ · 厂商官方鸿蒙 SDK(MMKV、推送、地图、支付、IM 等)
|
|
166
|
+
│
|
|
167
|
+
├─ 2. 查上游是否开源 ────────── 有源码 → 退回情况①/②,OHOS 工具链重编 + JNI→NAPI
|
|
168
|
+
│ · 用 .so 库名 + 头文件里的函数名/版权声明反查 GitHub/Gitee
|
|
169
|
+
│
|
|
170
|
+
├─ 3. 鸿蒙系统 API 重实现 ────── 无包无源码 → 用 @ohos.* / @kit.* 或 Native API 重写该功能
|
|
171
|
+
│ · 按头文件暴露的 API 逐条找系统 API 对应
|
|
172
|
+
│
|
|
173
|
+
└─ 4. 功能裁剪 / 降级 ────────── 以上都不行 → 评估能否移除该功能,标记 risk_items(high)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 4.4 各分支详解
|
|
177
|
+
|
|
178
|
+
**分支 1 — 查鸿蒙替代**:调用 `native-library-substitution` 技能(或本地查它的 `references/native-library-substitution.json`),按库名/功能查 `ohpm_package` 与 `source_type`(`安卓鸿蒙化库`/`C++/C鸿蒙化库` 优先)。命中后 `ohpm install`,并用替代包的 ArkTS/NAPI 接口替换原 JNI 调用。
|
|
179
|
+
|
|
180
|
+
**分支 2 — 获取上游源码**:通过头文件里的函数名、类名、版权/仓库注释反查开源地址;找到源码即退回情况①/②。
|
|
181
|
+
|
|
182
|
+
**分支 3 — 系统 API 重实现**:按头文件 API 语义逐个找鸿蒙系统能力(`@ohos.*` / `@kit.*` 模块,或 Native API)。例:加密 .so → `@ohos.security.cryptoFramework`;网络 .so → `@ohos.net.http`;音视频 .so → `@ohos.multimedia.media`。
|
|
183
|
+
|
|
184
|
+
**分支 4 — 裁剪/降级**:功能可去则去除依赖并降级体验;不可去则标记阻塞。输出 `risk_items`。
|
|
185
|
+
|
|
186
|
+
### 4.5 输出格式(写入迁移规划)
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"native_dependency_mapping": [
|
|
191
|
+
{
|
|
192
|
+
"original_platform": "android",
|
|
193
|
+
"original_lib": "libvlc.so(三方预编译,无源码)",
|
|
194
|
+
"original_usage": "视频播放",
|
|
195
|
+
"ohos_solution_type": "ohpm_package | custom_implementation | not_available",
|
|
196
|
+
"ohos_package": "命中时的 ohpm 包名 | null",
|
|
197
|
+
"ohos_module": "系统 API 重实现时的模块名 | null",
|
|
198
|
+
"install_command": "ohpm install xxx | null",
|
|
199
|
+
"confidence": "high | medium | low",
|
|
200
|
+
"notes": "决策分支、能力覆盖度、已知限制、备选方案摘要"
|
|
201
|
+
}
|
|
202
|
+
],
|
|
203
|
+
"risk_items": [
|
|
204
|
+
{
|
|
205
|
+
"description": "预编译库 {库名} 无鸿蒙替代、无源码、无系统 API 对应",
|
|
206
|
+
"severity": "high",
|
|
207
|
+
"mitigation": "评估移除该功能或换渠道;阻塞级别:partial | full"
|
|
208
|
+
}
|
|
209
|
+
]
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## 五、情况对照速查
|
|
216
|
+
|
|
217
|
+
| 情况 | 有无源码 | 现有 .so 能否直接用 | 主工作 | 难点 | 典型工作量 |
|
|
218
|
+
|------|---------|--------------------|--------|------|-----------|
|
|
219
|
+
| ① 源码编译 + JNI | 有 | ❌ | 源码重编 + JNI→NAPI | 桥接改写 | 低 |
|
|
220
|
+
| ② 源码 + patch | 有 | ❌ | patch 适配 + 重编 + JNI→NAPI | 平台差异适配 | 中 |
|
|
221
|
+
| ③ 三方预编译 | 无 | ❌ | 替代/获取源码/重实现/裁剪 | 无源码,依赖外部 | 高 |
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## 六、共享参考:构建与桥接映射(情况①②使用)
|
|
226
|
+
|
|
227
|
+
以下映射是情况①②「源码重编 + 桥接改写」的技术底稿。
|
|
228
|
+
|
|
229
|
+
### 6.1 Android 构建方式 → 鸿蒙构建方式
|
|
230
|
+
|
|
231
|
+
| Android | HarmonyOS | 说明 |
|
|
232
|
+
|---------|-----------|------|
|
|
233
|
+
| NDK(LLVM/clang) | HarmonyOS NDK / OpenHarmony SDK Native(LLVM/clang) | 同源工具链,目标三元组不同 |
|
|
234
|
+
| ndk-build(`Android.mk`+`Application.mk`) | 无对应,统一 CMake | `Android.mk` 需改写为 `CMakeLists.txt` |
|
|
235
|
+
| CMake(`CMakeLists.txt`) | CMake(`CMakeLists.txt`) | 基本复用,改链接库/头文件/三元组 |
|
|
236
|
+
| `externalNativeBuild.cmake.path` | `buildOption.externalNativeOptions.path` | 配置位置不同 |
|
|
237
|
+
| `ndk.abiFilters` | `externalNativeOptions.abiFilters` | 语义相同 |
|
|
238
|
+
| 预编译 .so 放 `src/main/jniLibs/<abi>/` | 放 `libs/<abi>/` 或 CMake IMPORTED | 位置不同 |
|
|
239
|
+
|
|
240
|
+
Android ABI:`arm64-v8a`(主流)、`armeabi-v7a`、`x86_64`、`x86`;鸿蒙以 `arm64-v8a` 为必备,`x86_64` 供模拟器。
|
|
241
|
+
|
|
242
|
+
**鸿蒙构建配置(`build-profile.json5`)**:
|
|
243
|
+
|
|
244
|
+
```json5
|
|
245
|
+
{
|
|
246
|
+
"modules": [{
|
|
247
|
+
"name": "entry",
|
|
248
|
+
"targets": [{
|
|
249
|
+
"name": "default",
|
|
250
|
+
"buildOption": {
|
|
251
|
+
"externalNativeOptions": {
|
|
252
|
+
"path": "./src/main/cpp/CMakeLists.txt",
|
|
253
|
+
"abiFilters": ["arm64-v8a", "x86_64"]
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}]
|
|
257
|
+
}]
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**鸿蒙 CMakeLists.txt**:
|
|
262
|
+
|
|
263
|
+
```cmake
|
|
264
|
+
cmake_minimum_required(VERSION 3.5.0)
|
|
265
|
+
project(mylib)
|
|
266
|
+
add_library(mylib SHARED napi_init.cpp)
|
|
267
|
+
target_link_libraries(mylib PUBLIC libhilog_ndk.z.so)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**交叉编译三元组对照**:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
# Android
|
|
274
|
+
$NDK/.../bin/aarch64-linux-android21-clang -shared -fPIC -o libmylib.so mylib.c
|
|
275
|
+
# HarmonyOS
|
|
276
|
+
$OHOS_SDK/native/llvm/bin/clang --target=aarch64-linux-ohos \
|
|
277
|
+
--sysroot=$OHOS_SDK/native/sysroot -shared -fPIC -o libmylib.so mylib.c
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### 6.2 系统库依赖对照(常用)
|
|
281
|
+
|
|
282
|
+
| Android 库 | HarmonyOS 库 | 用途 |
|
|
283
|
+
|-----------|--------------|------|
|
|
284
|
+
| `-llog` / `liblog.so` | `libhilog_ndk.z.so` | 日志 |
|
|
285
|
+
| `-lz` / `libz.so` | `libz.so` | 压缩 |
|
|
286
|
+
| `-lcrypto -lssl` | 系统 OpenSSL 或自编 | 加解密 |
|
|
287
|
+
| `-landroid` | 无对应(拆到各 Native API) | Android 特有 |
|
|
288
|
+
| OpenGL ES | `libGLESv3.so` / EGL | 图形(XComponent + OpenGL) |
|
|
289
|
+
| `libdl.so` | `libdl.so` | 动态加载 |
|
|
290
|
+
| `-lm` | `libm.so` | 数学库 |
|
|
291
|
+
|
|
292
|
+
### 6.3 JNI ↔ NAPI 桥接对照
|
|
293
|
+
|
|
294
|
+
**Java 侧 → ArkTS 侧**:
|
|
295
|
+
|
|
296
|
+
| Android JNI | HarmonyOS NAPI |
|
|
297
|
+
|-------------|----------------|
|
|
298
|
+
| `<jni.h>` + `JNIEnv*` | `napi/native_api.h` + `napi_env` |
|
|
299
|
+
| `JNIEXPORT ... JNICALL Java_com_x_y_z()` | `static napi_value fn(napi_env, napi_callback_info)` |
|
|
300
|
+
| `System.loadLibrary("x")` | `import x from 'libx.so'` |
|
|
301
|
+
| `native` / `external` 方法声明 | `napi_define_properties` + `.d.ts` 导出 |
|
|
302
|
+
| `JNI_OnLoad` 动态注册 | `napi_module_register` + `__attribute__((constructor))` |
|
|
303
|
+
| `env->GetStringUTFChars` | `napi_get_value_string_utf8` |
|
|
304
|
+
| `env->NewStringUTF` | `napi_create_string_utf8` |
|
|
305
|
+
| `jobject` 回调 Java | `napi_create_function` / `napi_call_function` 回调 ArkTS |
|
|
306
|
+
| `jbyteArray` | `napi_create_arraybuffer` / `napi_create_typedarray` |
|
|
307
|
+
| `NewGlobalRef` 保持引用 | `napi_create_reference` |
|
|
308
|
+
|
|
309
|
+
**NAPI 模块模板**:
|
|
310
|
+
|
|
311
|
+
```cpp
|
|
312
|
+
#include "napi/native_api.h"
|
|
313
|
+
|
|
314
|
+
static napi_value Hello(napi_env env, napi_callback_info info) {
|
|
315
|
+
size_t argc = 1;
|
|
316
|
+
napi_value args[1] = {nullptr};
|
|
317
|
+
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
|
318
|
+
// ...
|
|
319
|
+
napi_value result;
|
|
320
|
+
napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &result);
|
|
321
|
+
return result;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
EXTERN_C_START
|
|
325
|
+
static napi_value Init(napi_env env, napi_value exports) {
|
|
326
|
+
napi_property_descriptor desc[] = {
|
|
327
|
+
{ "hello", nullptr, Hello, nullptr, nullptr, nullptr, napi_default, nullptr }
|
|
328
|
+
};
|
|
329
|
+
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
|
|
330
|
+
return exports;
|
|
331
|
+
}
|
|
332
|
+
EXTERN_C_END
|
|
333
|
+
|
|
334
|
+
static napi_module mylibModule = {
|
|
335
|
+
.nm_version = 1, .nm_flags = 0, .nm_filename = nullptr,
|
|
336
|
+
.nm_register_func = Init, .nm_modname = "mylib",
|
|
337
|
+
.nm_priv = ((void*)0), .reserved = { 0 },
|
|
338
|
+
};
|
|
339
|
+
extern "C" __attribute__((constructor)) void RegisterMylibModule(void) {
|
|
340
|
+
napi_module_register(&mylibModule);
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
ArkTS 调用 + 类型声明:
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
import mylib from 'libmylib.so';
|
|
348
|
+
let r = mylib.hello('world');
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
`entry/src/main/cpp/types/libmylib/index.d.ts`:
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
export const hello: (name: string) => string;
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### 6.4 类型映射对照
|
|
358
|
+
|
|
359
|
+
| Java/Kotlin | JNI 类型 | NAPI 类型 |
|
|
360
|
+
|-------------|----------|-----------|
|
|
361
|
+
| `String` | `jstring` | `napi_value`(string) |
|
|
362
|
+
| `Int` | `jint` | `napi_value`(number) |
|
|
363
|
+
| `Long` | `jlong` | `napi_value`(bigint/number) |
|
|
364
|
+
| `Boolean` | `jboolean` | `napi_value`(boolean) |
|
|
365
|
+
| `ByteArray` | `jbyteArray` | `napi_value`(ArrayBuffer/TypedArray) |
|
|
366
|
+
| `Object` | `jobject` | `napi_value`(object) |
|
|
367
|
+
| `void` | `void` | `napi_get_undefined` |
|
|
368
|
+
|
|
369
|
+
### 6.5 典型库示例:VLC (libvlc)
|
|
370
|
+
|
|
371
|
+
Android:`LibVLC(context, args)` → `libvlcjni.so`(JNI)→ `libvlc.so`(核心)。
|
|
372
|
+
鸿蒙:OHOS 工具链交叉编译 libvlc 核心得到 `arm64-v8a/libvlc.so`,再写一层 `libvlc_napi.so` 把 `libvlc_new`/`libvlc_media_new_path`/`libvlc_media_player_play` 等 C API 导出给 ArkTS。
|
|
373
|
+
|
|
374
|
+
| Android(Java 封装) | libvlc C API | HarmonyOS(NAPI 导出) |
|
|
375
|
+
|----------------------|--------------|------------------------|
|
|
376
|
+
| `LibVLC(context, args)` | `libvlc_new` | `libvlc_new` |
|
|
377
|
+
| `Media(libVLC, uri)` | `libvlc_media_new_path` | `libvlc_media_new_path` |
|
|
378
|
+
| `MediaPlayer(libVLC)` | `libvlc_media_player_new` | `libvlc_media_player_new` |
|
|
379
|
+
| `player.play()` | `libvlc_media_player_play` | `libvlc_media_player_play` |
|
|
380
|
+
|
|
381
|
+
关键点:视频渲染 Android 用 `SurfaceView`(`libvlc_media_player_set_android_surface`),鸿蒙用 XComponent(`OH_NativeXComponent`);回调用 `napi_threadsafe_function` 跨线程。
|
|
382
|
+
|
|
383
|
+
### 6.6 常见坑与规避
|
|
384
|
+
|
|
385
|
+
| 坑 | 规避 |
|
|
386
|
+
|----|------|
|
|
387
|
+
| `-llog` / `liblog` 找不到 | 换成 `libhilog_ndk.z.so`,头文件 `<hilog/log.h>` |
|
|
388
|
+
| 目标三元组错 | Android `aarch64-linux-android` → 鸿蒙 `aarch64-linux-ohos` |
|
|
389
|
+
| 少了 `napi_module_register` | NAPI 模块必须注册 constructor 才能被 `import` 识别 |
|
|
390
|
+
| 预编译 .so 架构不对 | 只放 `arm64-v8a`,缺失架构在对应设备崩溃 |
|
|
391
|
+
| `.d.ts` 缺失导致 import 报类型错 | 建 `types/libmylib/index.d.ts` |
|
|
392
|
+
| JNI 回调对象被 GC | 用 `napi_create_reference` 保持引用 |
|
|
393
|
+
| 大块二进制拷贝慢 | 用 `napi_create_arraybuffer` + 直接指针读写 |
|
|
394
|
+
| 依赖的系统库差异 | 用 `native-library-substitution` 或 OHOS SDK 文档核对可用 Native API |
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## 七、参考文件
|
|
399
|
+
|
|
400
|
+
- [scripts/check-android-so.py](scripts/check-android-so.py):迁移前 .so/.a 检查脚本(能否直接用于鸿蒙 + 三种情况的处置方案)。
|
|
401
|
+
- [references/jni-to-napi-mapping.md](references/jni-to-napi-mapping.md):JNI ↔ NAPI 逐函数对照速查表。
|
|
402
|
+
- [references/build-config-mapping.md](references/build-config-mapping.md):build.gradle / CMakeLists / Android.mk ↔ build-profile.json5 / CMakeLists 对照模板。
|
|
403
|
+
- `native-library-substitution`(独立技能):情况③ 分支 1 的替代包查询数据源(ohpm 2678 映射)。
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# 构建配置对照模板:Android ↔ HarmonyOS
|
|
2
|
+
|
|
3
|
+
用于把 Android 的 native 构建配置平移为鸿蒙构建配置。
|
|
4
|
+
|
|
5
|
+
## 一、整体配置位置对照
|
|
6
|
+
|
|
7
|
+
| 关注点 | Android | HarmonyOS |
|
|
8
|
+
|--------|---------|-----------|
|
|
9
|
+
| 模块构建脚本 | `app/build.gradle`(或 `.kts`) | `entry/build-profile.json5` |
|
|
10
|
+
| 包/模块声明 | `build.gradle` 的 `android { }` | `oh-package.json5` |
|
|
11
|
+
| 原生构建脚本 | `src/main/cpp/CMakeLists.txt` 或 `jni/Android.mk` | `src/main/cpp/CMakeLists.txt` |
|
|
12
|
+
| ABI 过滤 | `android.defaultConfig.ndk.abiFilters` | `buildOption.externalNativeOptions.abiFilters` |
|
|
13
|
+
| 预编译 .so 目录 | `src/main/jniLibs/<abi>/` | `entry/libs/<abi>/`(或 CMake IMPORTED) |
|
|
14
|
+
|
|
15
|
+
## 二、build.gradle → build-profile.json5
|
|
16
|
+
|
|
17
|
+
### Android(app/build.gradle)
|
|
18
|
+
|
|
19
|
+
```gradle
|
|
20
|
+
android {
|
|
21
|
+
defaultConfig {
|
|
22
|
+
ndk { abiFilters 'arm64-v8a', 'armeabi-v7a' }
|
|
23
|
+
}
|
|
24
|
+
externalNativeBuild {
|
|
25
|
+
cmake {
|
|
26
|
+
path "src/main/cpp/CMakeLists.txt"
|
|
27
|
+
version "3.22.1"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### HarmonyOS(entry/build-profile.json5)
|
|
34
|
+
|
|
35
|
+
```json5
|
|
36
|
+
{
|
|
37
|
+
"app": { "signingConfigs": [], "products": [{ "name": "default", "signingConfig": "default" }] },
|
|
38
|
+
"modules": [
|
|
39
|
+
{
|
|
40
|
+
"name": "entry",
|
|
41
|
+
"srcPath": "./entry",
|
|
42
|
+
"targets": [
|
|
43
|
+
{
|
|
44
|
+
"name": "default",
|
|
45
|
+
"applyToProducts": ["default"],
|
|
46
|
+
"buildOption": {
|
|
47
|
+
"externalNativeOptions": {
|
|
48
|
+
"path": "./src/main/cpp/CMakeLists.txt",
|
|
49
|
+
"arguments": "",
|
|
50
|
+
"cppFlags": "",
|
|
51
|
+
"abiFilters": ["arm64-v8a", "x86_64"]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 三、CMakeLists.txt 对照
|
|
62
|
+
|
|
63
|
+
### Android 版
|
|
64
|
+
|
|
65
|
+
```cmake
|
|
66
|
+
cmake_minimum_required(VERSION 3.18)
|
|
67
|
+
project(mylib)
|
|
68
|
+
|
|
69
|
+
add_library(mylib SHARED native.cpp)
|
|
70
|
+
|
|
71
|
+
find_library(log-lib log)
|
|
72
|
+
target_link_libraries(mylib ${log-lib})
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### HarmonyOS 版(差异点:日志库、头文件、三元组)
|
|
76
|
+
|
|
77
|
+
```cmake
|
|
78
|
+
cmake_minimum_required(VERSION 3.5.0)
|
|
79
|
+
project(mylib)
|
|
80
|
+
|
|
81
|
+
add_library(mylib SHARED napi_init.cpp)
|
|
82
|
+
|
|
83
|
+
# 鸿蒙日志库替换 Android 的 liblog
|
|
84
|
+
target_link_libraries(mylib PUBLIC libhilog_ndk.z.so)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
对应头文件替换:
|
|
88
|
+
|
|
89
|
+
| Android | HarmonyOS |
|
|
90
|
+
|---------|-----------|
|
|
91
|
+
| `<android/log.h>` + `__android_log_print` | `<hilog/log.h>` + `OH_LOG_Print` |
|
|
92
|
+
|
|
93
|
+
## 四、Android.mk(ndk-build)→ CMakeLists.txt
|
|
94
|
+
|
|
95
|
+
### Android.mk(遗留)
|
|
96
|
+
|
|
97
|
+
```makefile
|
|
98
|
+
LOCAL_PATH := $(call my-dir)
|
|
99
|
+
include $(CLEAR_VARS)
|
|
100
|
+
LOCAL_MODULE := mylib
|
|
101
|
+
LOCAL_SRC_FILES := native.cpp
|
|
102
|
+
LOCAL_LDLIBS := -llog
|
|
103
|
+
include $(BUILD_SHARED_LIBRARY)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 等价 CMakeLists.txt(鸿蒙)
|
|
107
|
+
|
|
108
|
+
```cmake
|
|
109
|
+
cmake_minimum_required(VERSION 3.5.0)
|
|
110
|
+
project(mylib)
|
|
111
|
+
add_library(mylib SHARED napi_init.cpp)
|
|
112
|
+
target_link_libraries(mylib PUBLIC libhilog_ndk.z.so)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 五、预编译 .so 引入对照
|
|
116
|
+
|
|
117
|
+
### Android(jniLibs 目录,自动打包)
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
app/src/main/jniLibs/arm64-v8a/libfoo.so
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
无需额外配置,Gradle 自动打入 APK。
|
|
124
|
+
|
|
125
|
+
### HarmonyOS(CMake IMPORTED)
|
|
126
|
+
|
|
127
|
+
```cmake
|
|
128
|
+
add_library(foo SHARED IMPORTED)
|
|
129
|
+
set_target_properties(foo PROPERTIES IMPORTED_LOCATION
|
|
130
|
+
${CMAKE_SOURCE_DIR}/../libs/${CMAKE_ANDROID_ABI}/libfoo.so) # 注意用 OHOS 变量
|
|
131
|
+
target_link_libraries(mylib PUBLIC foo)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
或将预编译 .so 放 `entry/libs/arm64-v8a/libfoo.so`,在 CMake 里引入。
|
|
135
|
+
|
|
136
|
+
## 六、交叉编译工具链对照
|
|
137
|
+
|
|
138
|
+
| 项 | Android NDK | HarmonyOS NDK |
|
|
139
|
+
|----|-------------|---------------|
|
|
140
|
+
| 编译器 | `$NDK/toolchains/llvm/prebuilt/<host>/bin/aarch64-linux-android<api>-clang` | `$OHOS_SDK/native/llvm/bin/clang` |
|
|
141
|
+
| 目标三元组 | `aarch64-linux-android` | `aarch64-linux-ohos` |
|
|
142
|
+
| sysroot | `$NDK/toolchains/llvm/prebuilt/<host>/sysroot` | `$OHOS_SDK/native/sysroot` |
|
|
143
|
+
| C++ 库 | `libc++`(`-stdlib=libc++` 默认) | `libc++`(默认) |
|
|
144
|
+
|
|
145
|
+
### 编译命令对照
|
|
146
|
+
|
|
147
|
+
Android:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
$NDK/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android21-clang \
|
|
151
|
+
-shared -fPIC -o libmylib.so mylib.c
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
HarmonyOS:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
$OHOS_SDK/native/llvm/bin/clang \
|
|
158
|
+
--target=aarch64-linux-ohos --sysroot=$OHOS_SDK/native/sysroot \
|
|
159
|
+
-shared -fPIC -o libmylib.so mylib.c
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## 七、系统库依赖对照(常用)
|
|
163
|
+
|
|
164
|
+
| Android 库 | HarmonyOS 库 | 用途 |
|
|
165
|
+
|-----------|--------------|------|
|
|
166
|
+
| `-llog` / `liblog.so` | `libhilog_ndk.z.so` | 日志 |
|
|
167
|
+
| `-lz` / `libz.so` | `libz.so` | 压缩 |
|
|
168
|
+
| `-lcrypto -lssl` | 系统 OpenSSL 或自编 | 加解密 |
|
|
169
|
+
| `-landroid` | 无对应(用 Native API) | Android 特有(如 AssetManager) |
|
|
170
|
+
| OpenGL ES | `libGLESv3.so` / EGL | 图形(鸿蒙用 XComponent + OpenGL) |
|
|
171
|
+
| `libdl.so` | `libdl.so` | 动态加载 |
|
|
172
|
+
| `-lm` | `libm.so` | 数学库 |
|
|
173
|
+
|
|
174
|
+
## 八、验证命令
|
|
175
|
+
|
|
176
|
+
| 步骤 | Android | HarmonyOS |
|
|
177
|
+
|------|---------|-----------|
|
|
178
|
+
| 构建 | `./gradlew assembleDebug` | DevEco 构建 / `hvigorw assembleHap` |
|
|
179
|
+
| 产物 | `app/build/intermediates/.../cmake/.../libmylib.so` | `entry/build/default/intermediates/libs/default/<abi>/libmylib.so` |
|
|
180
|
+
| 产物检查 | `unzip -l app-debug.apk | grep .so` | 解包 HAP 检查 `libs/<abi>/` |
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# JNI ↔ NAPI 函数对照速查表
|
|
2
|
+
|
|
3
|
+
本表用于把 Android JNI 桥接代码逐函数改写为 HarmonyOS NAPI 代码。
|
|
4
|
+
|
|
5
|
+
## 一、环境与模块注册
|
|
6
|
+
|
|
7
|
+
| 目的 | Android JNI | HarmonyOS NAPI |
|
|
8
|
+
|------|-------------|----------------|
|
|
9
|
+
| 头文件 | `#include <jni.h>` | `#include "napi/native_api.h"` |
|
|
10
|
+
| 环境类型 | `JNIEnv *env` | `napi_env env` |
|
|
11
|
+
| 导出函数签名 | `JNIEXPORT jstring JNICALL Java_pkg_Class_method(JNIEnv *env, jobject thiz, ...)` | `static napi_value method(napi_env env, napi_callback_info info)` |
|
|
12
|
+
| 获取参数 | 直接来自函数形参 | `napi_get_cb_info(env, info, &argc, args, &this_arg, nullptr)` |
|
|
13
|
+
| 模块加载 | `System.loadLibrary("x")` 触发 `JNI_OnLoad` | `import x from 'libx.so'` 触发 `napi_module_register` |
|
|
14
|
+
| 模块注册 | `JNI_OnLoad(JavaVM*, void*)` 返回版本号 | `static napi_module m = { .nm_register_func = Init, .nm_modname = "x" };` + `__attribute__((constructor)) void f(){ napi_module_register(&m); }` |
|
|
15
|
+
| 导出方法 | `RegisterNatives` 或静态命名 | `napi_define_properties(env, exports, n, desc)` |
|
|
16
|
+
|
|
17
|
+
## 二、基础类型转换
|
|
18
|
+
|
|
19
|
+
| Java/Kotlin | JNI | NAPI 取值 | NAPI 构造 |
|
|
20
|
+
|-------------|-----|-----------|-----------|
|
|
21
|
+
| `String` | `jstring` | `napi_get_value_string_utf8` | `napi_create_string_utf8` |
|
|
22
|
+
| `int` | `jint` | `napi_get_value_int32` | `napi_create_int32` |
|
|
23
|
+
| `long` | `jlong` | `napi_get_value_int64` / `napi_get_value_bigint_int64` | `napi_create_int64` / `napi_create_bigint_int64` |
|
|
24
|
+
| `double` | `jdouble` | `napi_get_value_double` | `napi_create_double` |
|
|
25
|
+
| `boolean` | `jboolean` | `napi_get_value_bool` | `napi_get_boolean` |
|
|
26
|
+
| `void` | `void` | — | `napi_get_undefined` |
|
|
27
|
+
| `null` | `nullptr` | `napi_get_null` | `napi_get_null` |
|
|
28
|
+
| `byte[]` | `jbyteArray` | `napi_get_typedarray_info` / `napi_get_arraybuffer_info` | `napi_create_arraybuffer` / `napi_create_typedarray` |
|
|
29
|
+
|
|
30
|
+
## 三、对象与数组
|
|
31
|
+
|
|
32
|
+
| 目的 | JNI | NAPI |
|
|
33
|
+
|------|-----|------|
|
|
34
|
+
| 创建对象 | `env->NewObject(cls, ctor, ...)` | `napi_new_instance(env, ctor, ...)` |
|
|
35
|
+
| 取字段 | `env->GetObjectField` | `napi_get_named_property` / `napi_get_property` |
|
|
36
|
+
| 设字段 | `env->SetObjectField` | `napi_set_named_property` / `napi_set_property` |
|
|
37
|
+
| 创建数组 | `env->NewObjectArray` | `napi_create_array` / `napi_create_array_with_length` |
|
|
38
|
+
| 取数组元素 | `env->GetObjectArrayElement` | `napi_get_element` |
|
|
39
|
+
| 设数组元素 | `env->SetObjectArrayElement` | `napi_set_element` |
|
|
40
|
+
|
|
41
|
+
## 四、函数与回调
|
|
42
|
+
|
|
43
|
+
| 目的 | JNI | NAPI |
|
|
44
|
+
|------|-----|------|
|
|
45
|
+
| 创建回调函数 | `env->NewGlobalRef(obj)` + 回调方法 ID | `napi_create_function` / `napi_create_threadsafe_function` |
|
|
46
|
+
| 调用 Java/ArkTS 方法 | `env->CallVoidMethod` / `CallStaticObjectMethod` | `napi_call_function` |
|
|
47
|
+
| 跨线程回调 | JNI 线程 attach + CallMethod | `napi_threadsafe_function`(`napi_call_threadsafe_function`) |
|
|
48
|
+
| 保持引用 | `env->NewGlobalRef` | `napi_create_reference` |
|
|
49
|
+
| 释放引用 | `env->DeleteGlobalRef` | `napi_delete_reference` |
|
|
50
|
+
|
|
51
|
+
## 五、异常与字符串
|
|
52
|
+
|
|
53
|
+
| 目的 | JNI | NAPI |
|
|
54
|
+
|------|-----|------|
|
|
55
|
+
| 抛异常 | `env->ThrowNew(cls, msg)` | `napi_throw_error` / `napi_throw_type_error` / `napi_throw_range_error` |
|
|
56
|
+
| 检查异常 | `env->ExceptionCheck()` | `napi_is_exception_pending` |
|
|
57
|
+
| 取字符串 | `GetStringUTFChars` + `ReleaseStringUTFChars` | `napi_get_value_string_utf8` |
|
|
58
|
+
| 字符串长度 | `GetStringUTFLength` | 先 `napi_get_value_string_utf8` 传 `nullptr` 取长度,再取内容 |
|
|
59
|
+
|
|
60
|
+
## 六、同步/异步
|
|
61
|
+
|
|
62
|
+
| 场景 | JNI | NAPI |
|
|
63
|
+
|------|-----|------|
|
|
64
|
+
| 同步返回 | 直接 return | 直接 return `napi_value` |
|
|
65
|
+
| 异步 | 用 Java 线程 + 回调 | `napi_create_async_work` + `napi_queue_async_work`,完成时 `napi_create_promise` / 回调 |
|
|
66
|
+
| Promise | 无内置,需 Java 侧 CompletableFuture | `napi_create_promise` + `napi_resolve_deferred` / `napi_reject_deferred` |
|
|
67
|
+
|
|
68
|
+
## 七、内存与生命周期
|
|
69
|
+
|
|
70
|
+
| 目的 | JNI | NAPI |
|
|
71
|
+
|------|-----|------|
|
|
72
|
+
| 分配 | `env->NewByteArray` / malloc | `napi_create_arraybuffer`(GC 托管)或 `malloc` 自行管理 |
|
|
73
|
+
| 外部缓冲 | `NewDirectByteBuffer` / `GetDirectBufferAddress` | `napi_create_external_arraybuffer` / `napi_get_arraybuffer_info` |
|
|
74
|
+
| 释放 | `env->DeleteLocalRef` | `napi_delete_reference`(引用)/ 托管内存自动回收 |
|