作者:王石
在《#跟着小白一起学鸿蒙#[六]第一个hap应用》我们熟悉了如何在开源鸿蒙开发hap应用,后期的文章我们会写在hap应用里调用系统库甚至是动态库。此篇文章,我们主要是熟悉下NAPI框架,并一起写一个支持NAPI的子系统,这样以后当我们想在hap应用里加自己功能的时候就可以方便的添加。
NAPI框架简介
NAPI(Native API)组件是一套对外接口基于Node.js N-API规范开发的原生模块扩展开发框架。类似于Android的JNI,NAPI框架实现了应用层ts/ets/js语言编写的代码和开源鸿蒙的native代码(c/c++)交互的能力。此框架由Node.js N-API框架扩展而来。
注意:开源鸿蒙的标准系统是采用NAPI框架的,轻量系统则是采用jerryscript框架
详细的内容介绍在一下链接内可以看到官方的说明:
参考链接:https://gitee.com/openharmony/arkui_napi
NAPI的使用
graph LR
创建d.ts --> 执行napi_generator --> 建立子系统 --> 引入子系统 --> 编译生成
-
创建d.ts: @ohos.napitest.d.ts, basic.d.ts
- @ohos.napitest.d.ts是NAPI的声明文件,在DevEco Studio开发的时候会用到d.ts来检查语法和提供代码帮助;
import {AsyncCallback} from './basic'; /** * Provides interfaces to napitest. * * @since 7 */ declare namespace napitest { /** * Shuts down the system. * * <p>This method requires the ohos.permission.SHUTDOWN permission. * * @param reason Indicates the shutdown reason. * @systemapi * @since 7 */ function shutdownDevice(reason: string): void; /** * Restarts the system. * * <p>This method requires the ohos.permission.REBOOT permission. * * @param reason Indicates the restart reason. For example, "updater" indicates entering the updater mode * after the restart. If the parameter is not specified, the system enters the normal mode after the restart. * @since 7 */ function rebootDevice(reason: string): void; /** * Checks whether the screen of a device is on or off. * * @return Returns true if the screen is on; returns false otherwise. * @since 7 */ function isScreenOn(callback: AsyncCallback<boolean>): void; function isScreenOn(): Promise<boolean>; } export default napitest;
- basic.d.ts:一些基础方法的声明
export interface Callback<T> { (data: T): void; } export interface ErrorCallback<T extends Error = BusinessError> { (err: T): void; } export interface AsyncCallback<T> { (err: BusinessError, data: T): void; } export interface BusinessError extends Error { code: number; }
-
执行napi_generator
建立个文件夹,将上面建立的两个d.ts和napi_generator放在一起
//准备环境 mkdir napitest cd napitest vim @ohos.napitest.d.ts vim basic.d.ts //拷贝napi_generator cp [路径]/napi_generator-linux . chmod +x napi_generator-linux //生成napitest代码 ./napi_generator-linux -f @ohos.napitest.d.ts -o out //当看到success则说明烧录成功 //检视out目录 ├── binding.gyp //工具中间文件 ├── BUILD.gn //之后需要用到的gn文件 ├── napi_gen.log //工具log ├── napitest.cpp //自动生成的接口调用的实际代码 ├── napitest.h //自动生成的接口调用的实际代码 ├── napitest_middle.cpp //自动生成的napi适配代码 ├── test.sh //生成js代码的脚本,官方没给说明,试了下不可用 ├── tool_utility.cpp //自动生成的napi适配代码 └── tool_utility.h //自动生成的napi适配代码
-
建立子系统
- 在鸿蒙源码目录下建立foundation/napitest,将之前生成的文件拷贝到文件夹内
foundation ├── ability ├── ai ├── arkui ├── barrierfree ├── bundlemanager ├── communication ├── deviceprofile ├── distributeddatamgr ├── distributedhardware ├── filemanagement ├── graphic ├── multimedia ├── multimodalinput ├── napitest │ ├── binding.gyp │ ├── BUILD.gn │ ├── bundle.json │ ├── napi_gen.log │ ├── napitest.cpp │ ├── napitest.h │ ├── napitest_middle.cpp │ ├── test.sh │ ├── tool_utility.cpp │ └── tool_utility.h ├── resourceschedule
- 在目录里创建bundle.json,使用一下内容
{ "name": "@ohos/napitest", "description": "napitest provides atomic capabilities", "version": "3.1", "license": "Apache License 2.0", "publishAs": "code-segment", "segment": { "destPath": "foundation/napitest" }, "dirs": {}, "scripts": {}, "component": { //部件名称 "name": "napitest_interface", //子系统名称 "subsystem": "napitest", "features": [], "adapted_system_type": [ "standard" ], "rom": "10000KB", "ram": "10000KB", "deps": { "components": [ "ace_napi", "ipc_core", "libhilog" ], "third_party": [ "node" ] }, "build": { "sub_component": [ "//foundation/napitest:napitest" ], "inner_kits": [ { "header": { "header_base": "//foundation/napitest", "header_files": [ "tool_utility.h", "napitest.h" ] }, "name": "//foundation/napitest:napitest" } ] } } }
- 为了和bundle.json对应,将BUILD.gn改成如下:
import("//build/ohos.gni") ohos_shared_library("napitest") { sources = [ "napitest_middle.cpp", "napitest.cpp", "tool_utility.cpp", ] include_dirs = [ ".", "//third_party/node/src", "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", ] deps=[ "//foundation/arkui/napi:ace_napi", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", ] remove_configs = [ "//build/config/compiler:no_rtti" ] cflags=[ ] cflags_cc=[ "-frtti", ] ldflags = [ ] relative_install_dir = "module" //部件名称 part_name = "napitest_interface" //子系统名称 subsystem_name = "napitest" }
-
引入子系统
-
增加子系统,修改build/subsystem_config.json
//在文件后增加 { //前面省略的内容 ... //新增内容 "napitest": { "path": "foundation/napitest", "name": "napitest" } }
-
增加编译入口(已目前的master版本为基础,3.2后改过编译路径)
//修改 vendor/hihope/[PRODUCT_NAME]/config.json 文件增加如下行 { "subsystem": "napitest", "components": [ { "component": "napitest_interface", "features": [] } ] },
-
-
编译生成
./build.sh --product-name PRODUCT_NAME //看到success则为编译成功,可以通过find out/[PRODUCT_NAME] -name *napitest.z.so查看生成文件,比如我的文件路径如下: ./out/rk3568/lib.unstripped/napitest/napitest_interface/libnapitest.z.so ./out/rk3568/napitest/napitest_interface/libnapitest.z.so ./out/rk3568/innerkits/ohos-arm/napitest_interface/napitest/libnapitest.z.so ./out/rk3568/packages/phone/system/lib/module/libnapitest.z.so //最后一个路径就是系统镜像的路径,所以两种办法 //1,直接copy到板子的/system/lib路径;参考《#跟着小白一起学鸿蒙# [二]第一个OpenHarmony程序》 //2,烧录镜像;参考《#跟着小白一起学鸿蒙# [一]运行OpenHarmony》
总结
这样我们就有了自己的subsystem和napi接口,后面的章节我们会讲如何在hap应用里调用系统库
参考链接:https://gitee.com/openharmony/napi_generator/tree/master
附件链接:https://ost.51cto.com/resource/2308
https://ost.51cto.com/#bkwz