首页 > 其他分享 >鸿蒙(HarmonyOS)实战开发篇——基于Napi调用ArkTS/系统接口

鸿蒙(HarmonyOS)实战开发篇——基于Napi调用ArkTS/系统接口

时间:2024-09-27 21:24:14浏览次数:9  
标签:ArkTS 接口 nullptr value HarmonyOS Napi env callbackData napi

场景描述:

app应用在native侧调用 系统库/arkts模块的方法。

应用经常会遇到如下的业务诉求:

场景一:系统提供了ArkTS 接口,但未提供对应的NDK接口,当伙伴使用C++ 代码实现业务逻辑时,部分系统能力需要依赖系统ArkTS接口;

场景二: 系统仅提供了ArkTS 异步接口,未提供对应的NDK接口,当伙伴使用C++ 代码实现业务逻辑时,部分系统能力需要依赖系统ArkTS 异步接口;

场景三:伙伴在 TS 侧已定义接口,未实现对应的NDK接口,当伙伴使用C++ 代码实现业务逻辑时,想直接使用已有的TS 接口;

方案描述:

场景一: 系统提供了ArkTS 接口,但未提供对应的NDK接口,当伙伴使用C++ 代码实现业务逻辑时,部分系统能力需要依赖系统ArkTS接口;

例如: 获取设备的屏幕宽高。

方案:

通过napi_load_module 的方式调用系统模块接口。

核心代码

static napi_value GetDisplaySize(napi_env env, napi_callback_info info) {

  // 获取arkts侧的系统库路径

  char path[64] = "@ohos.display";

  size_t typeLen = 0;

  napi_value string;

  napi_create_string_utf8(env, path,  typeLen, &string);

  // 加载系统库

  napi_value sysModule;

  napi_load_module(env, path, &sysModule);

  // 获取系统库中的"getDefaultDisplaySync"方法

  napi_value func = nullptr;

  napi_get_named_property(env, sysModule, "getDefaultDisplaySync", &func);

  napi_value funcResult;

  napi_call_function(env, sysModule, func, 0, nullptr, &funcResult);

  napi_value widthValue = nullptr;

  napi_get_named_property(env, funcResult, "width", &widthValue);

  double width;

  napi_get_value_double(env, widthValue, &width);

  OH_LOG_INFO( LOG_APP,  "width: %{public}f", width);

  napi_value heightValue = nullptr;

  napi_get_named_property(env, funcResult, "height", &heightValue);

  double height;

  napi_get_value_double(env, heightValue, &height);

  OH_LOG_INFO(LOG_APP, "height: %{public}f", height);

  // TODO: 业务拿到width 和 height,可以进一步处理具体业务逻辑

  return nullptr;

}

运行结果:

场景二:

系统仅提供了ArkTS 异步接口,未提供对应的NDK接口,当伙伴使用C++ 代码实现业务逻辑时,部分系统能力需要依赖系统ArkTS 异步接口;

例如: 如何访问系统定义的异步ArkTS方法。

方案

通过创建线程安全函数的方式 调用系统的异步接口

核心代码: 回调到JS层

static void CallJs(napi_env env, napi_value jsCb, void *context, void *data) {

  if (env == nullptr) {

    return;

  }

  napi_value undefined = nullptr;

  napi_value promise = nullptr;

  char str[] = "wlan0";

  napi_value sysModule;

  napi_load_module(env, "@ohos.net.statistics", &sysModule);

  napi_value param;

  napi_create_string_utf8(env, str, NAPI_AUTO_LENGTH, &param);

  napi_call_function(env, sysModule, jsCb, 1, &param, &promise);

  napi_value thenFunc = nullptr;

  if (napi_get_named_property(env, promise, "then", &thenFunc) != napi_ok) {

    return;

  }

  napi_value resolvedCallback;

  napi_value rejectedCallback;

  napi_create_function(env, "resolvedCallback", NAPI_AUTO_LENGTH, ResolvedCallback, data, &resolvedCallback);

  napi_create_function(env, "rejectedCallback", NAPI_AUTO_LENGTH, RejectedCallback, data, &rejectedCallback);

  napi_value argv[2] = {resolvedCallback, rejectedCallback};

  napi_call_function(env, promise, thenFunc, 2, argv, nullptr);

}

// 执行异步任务

static void ExecuteWork(napi_env env, void *data) {

  CallbackData *callbackData = reinterpret_cast<CallbackData *>(data);

  std::promise<double> promise;

  auto future = promise.get_future();

  // 调用线程安全函数

  napi_call_threadsafe_function(callbackData->tsfn, &promise, napi_tsfn_nonblocking);

  try {

    auto result = future.get();

    OH_LOG_INFO(LOG_APP, "getIfaceRxBytes Result from JS %{public}f", result);

  } catch (const std::exception &e) {

    // OH_LOG_INFO(LOG_APP, "XXX, Result from JS %{public}s", e.what());

  }

}

// 异步任务完成回调

static void WorkComplete(napi_env env, napi_status status, void *data) {

  CallbackData *callbackData = reinterpret_cast<CallbackData *>(data);

  napi_release_threadsafe_function(callbackData->tsfn, napi_tsfn_release);

  napi_delete_async_work(env, callbackData->work);

  callbackData->tsfn = nullptr;

  callbackData->work = nullptr;

}

static napi_value CallAsyncFunc(napi_env env, napi_callback_info info) {

  size_t argc = 1;

  napi_value jsCb = nullptr;

  CallbackData *callbackData = nullptr;

  napi_get_cb_info(env, info, &argc, &jsCb, nullptr, reinterpret_cast<void **>(&callbackData));

  napi_value sysModule;

  napi_load_module(env, "@ohos.net.statistics", &sysModule);

  napi_value getIfaceRxBytesFunc ;

  napi_get_named_property(env, sysModule, "getIfaceRxBytes", &getIfaceRxBytesFunc);

  // 创建一个线程安全函数

  napi_value resourceName = nullptr;

  napi_create_string_utf8(env, "CallAsyncFunc", NAPI_AUTO_LENGTH, &resourceName);

  napi_create_threadsafe_function(env, getIfaceRxBytesFunc, nullptr, resourceName, 0, 1, callbackData, nullptr, callbackData, CallJs,

    &callbackData->tsfn);

  // 创建一个异步任务

  napi_create_async_work(env, nullptr, resourceName, ExecuteWork, WorkComplete, callbackData, &callbackData->work);

  // 将异步任务加入到异步队列中

  napi_queue_async_work(env, callbackData->work);

  return nullptr;

}

运行结果

场景三:

伙伴在 ArkTS/TS 侧已定义接口,当伙伴使用C++ 代码实现业务逻辑时,想直接使用已有的TS 接口;

例如: 如何调用自定义的 ArkTS/TS方法;

方案

核心代码

步骤一: ObjectUtil.ts 导出相关接口

namespace ObjectUtil {

  export function isNull(obj) {

    return obj === null;

  }

  export function isUndefined(obj) {

    return obj === undefined;

  }

  export function isNullOrUndefined(obj) {

    return isNull(obj) || isUndefined(obj);

  }

  export function toString(obj, defaultValue = '') {

    if (this.isNullOrUndefined(obj)) {

      return defaultValue;

    }

    else {

      return obj.toString();

    }

  }

}

export default ObjectUtil;

步骤二:必须在 build-profile.json5添加ets文件配置

// 必须在build-profile.json5添加配置

"arkOptions": {

  "runtimeOnly": {

    "sources": [

    './src/main/ets/common/ObjectUtil.ts',

    ],

    "packages": [

    ]

  }

},

步骤三: 在native 获取ets 模块导出的变量

/*

* 获取某个TS/JS模块导出变量

* 入参:

* path - 在工程文件夹下从ets开始的绝对路径名

* key - 待加载TS/JS模块导出变量的属性名

* 返回值:获取的TS/JS模块导出变量

*/

static napi_value GetNativeModule(napi_env env, const char *modulePath, const char *key)

{

  napi_value module;

  // 通过modulePath获取对应TS/JS模块的导出对象

  napi_load_module(env, modulePath, &module);

  napi_value outputObject = nullptr;

  // 通过对象属性名key,从导出模块变量

  napi_get_named_property(env, module, key, &outputObject );

  return outputObject ;

}

步骤四:获取方法并调用demo示例(获取/ets/common/ObjectUtil 的isNull方法,并调用isNull方法判断一个对象是否为null)

/*

* 调用系统库/ets/common/ObjectUtil模块导出方法 /ets/common/ObjectUtil 的isNull方法

* 返回值:标志是否加载成功的布尔值

*/

static napi_status CallIsNullFun(napi_env env, napi_value inputObject)

{

  const char moduleName[] = "/ets/common/ObjectUtil";

  const char funcName[] = "isNull";

  napi_value isNullFun = GetNativeModule(env, moduleName, funcName);

  

  napi_value inputArgs[1] = inputObject;

  napi_value result;

  // infoFun为"/ets/common/ObjectUtil"模块中获取的函数方法

  // inputArgs为待执行方法的入参,result为出参

  napi_call_function(env, undefined, isNullFun , 1, inputArgs, result);

  

  return result ;

}

标签:ArkTS,接口,nullptr,value,HarmonyOS,Napi,env,callbackData,napi
From: https://blog.csdn.net/lc748258/article/details/142522641

相关文章

  • 鸿蒙(HarmonyOS)实战开发篇——基于子窗口实现应用内悬浮窗
    推荐看点鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总【OpenHarmony】鸿蒙南向开发保姆级知识点汇总~持续更新中……场景描述app应用会使用悬浮窗/悬浮球的方式来给用户展示一些应用重要&便捷功能的入口,类似android和iOS应用中常见的应用内可拖拽的悬浮球和小窗口视频悬浮......
  • 鸿蒙(HarmonyOS)实战开发篇——基于ArkUI现有能力实现自定义弹窗封装方案
    推荐看点鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总【OpenHarmony】鸿蒙南向开发保姆级知识点汇总~持续更新中……场景描述自定义弹窗是应用开发需要实现的基础功能,包括但不限于HarmonyOS开发者文档中定义的模态、半模态、Toast等形式,封装一个好用且和UI组件解耦的弹窗组......
  • HarmonyOS NEXT-CoreVision Kit-FaceDetector-实现人脸识别,获取人脸数据
    效果演示图,右边的是人脸数据,可用来比对人脸注意这里只有真机才能测试是否成功,测试机型pce-w30实现这个效果很简洁:打开相册、选取图片、打开文件、创建imageSource、创建PixelMap、喂给faceDetector拿到结果在这里我简单封装了两个工具类方便后续使用,分别是:照片选择类、......
  • HarmonyOS开发之WaterFlow组件
    在HarmonyOS应用开发中,瀑布流布局因其灵活性和美观性而广受欢迎。HarmonyOSNEXT提供了强大的WaterFlow组件,可以帮助开发者轻松实现瀑布流布局,并支持多种自定义布局和性能优化特性。本文将通过两个具体场景,详细介绍如何使用WaterFlow组件实现页面滑动加载和吸顶效果。场景一:瀑......
  • 在 ArkTS 中,如何有效地进行内存管理和避免内存泄漏?
    ArkTS是鸿蒙生态的应用开发语言,它在TypeScript的基础上进行了优化和定制,以适应鸿蒙系统的需求。以下是在ArkTS中进行有效的内存管理和避免内存泄漏:1.使用const和let合理声明变量:使用const声明那些不会重新赋值的变量,这有助于确保变量的不变性,并可能让编译器进行更......
  • 鸿蒙(HarmonyOS)--声明式UI、自定义组件
    目录1.基础语法概述2.声明式UI描述2.1创建组件2.1.1无参数2.1.2有参数2.2配置属性2.3配置事件 2.4配置子组件3.自定义组件3.1创建自定义组件3.1.1基本使用3.1.2组件属性、方法3.1.3通用样式事件 3.2页面和自定义组件生命周期3.2.1自定义组件的创建......
  • 鸿蒙(HarmonyOS) - 实现省市区三级联动
    电商App在填写收货地址时,需要用户选择省市区,今天我们使用鸿蒙自带的TextPicker组件实现省市区三级联动。效果图如下:数据准备Github上有一个开源项目,支持中华人民共和国行政区划(五级):省级、地级、县级、乡级和村级,数据很全,并且很新,支持不同的组合,json数据格式跟sqlite3数据库格......
  • 鸿蒙HarmonyOS HCIP认证题库
    鸿蒙HarmonyOSHCIP认证题库学习分享,本题库一共409道。反复刷考场得来,手打不易。记住不要光背选项,考试时可能打乱顺序,主要还是记住内容。一、单选题和填空题1.某开发者想要使用类Web开发范式的属性样式动画设置text组件的颜色变化动效,以下代码空白处应该填写什么?text......
  • 关于HarmonyOS的学习
    day35一、回调地狱  //比如我们发送三个ajax请求  //-第一个正常发送  //-第二个请求需要第一个请求的结果中的某一个值作为参数  //-第三个请求需要第二个请求的结果中的某一个值作为参数  ajax_get({    url:'http://localhost......
  • 关于HarmonyOS的学习
    day36一、可选链和空集合并符1.?  //?作用:1、三目运算符2、可选链  constobj={    id:1,    //info:{    //  name:'张',    //  age:18    //} }  console.log(obj.id)  cons......