1# 应用侧与前端页面的相互调用(C/C++) 2<!--Kit: ArkWeb--> 3<!--Subsystem: Web--> 4<!--Owner: @aohui--> 5<!--Designer: @yaomingliu--> 6<!--Tester: @ghiker--> 7<!--Adviser: @HelloCrease--> 8 9本指导适用于ArkWeb应用侧与前端网页通信场景,开发者可根据应用架构选择使用ArkWeb Native接口完成业务通信机制(以下简称Native JSBridge)。 10针对JSBridge进行性能优化可参考[JSBridge优化解决方案](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-web-develop-optimization#section58781855115017) 11 12## 适用的应用架构 13 14应用使用ArkTS、C++语言混合开发,或本身应用架构较贴近于小程序架构,自带C++侧环境,推荐使用ArkWeb在Native侧提供的[ArkWeb_ControllerAPI](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md)、[ArkWeb_ComponentAPI](../reference/apis-arkweb/capi-web-arkweb-componentapi.md)实现JSBridge功能。 15 16  17 18 上图展示了具有普遍适用性的小程序的通用架构。在这一架构中,逻辑层依赖于应用程序自带的JavaScript运行时,该运行时在一个已有的C++环境中运行。通过Native接口,逻辑层能够直接在C++环境中与视图层(其中ArkWeb充当渲染器)进行通信,无需回退至ArkTS环境使用ArkTS JSBridge接口。 19 20 左图是使用ArkTS JSBridge接口构建小程序的方案,如红框所示,应用需要先调用到ArkTS环境,再调用到C++环境。右图是使用Native JSBridge接口构建小程序的方案,不需要ArkTS环境和C++环境的切换,执行效率更高。 21 22  23 24 Native JSBridge方案解决了ArkTS环境的冗余切换,同时允许回调在非UI线程上运行,避免造成UI阻塞。 25 26## 使用Native接口实现JSBridge通信(推荐) 27原先,Native同步接口不支持返回值,其返回类型固定为void。然而,为满足业务扩展需求,自API version 18起,引入了替代接口,支持bool、string和buffer类型的返回值。 28 29另外针对同步接口[registerJavaScriptProxyEx](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md#registerjavascriptproxyex)和异步接口[registerAsyncJavaScriptProxyEx](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md#registerasyncjavascriptproxyex),新增了参数[permission](#前端页面调用应用侧函数)字段,用于调用权限控制。 30 31### 接口替代关系 32 33| 不推荐的接口 | 替代接口 | 说明 | 34| :-----------------------------------: | :-----------------------------------: | :------------------------: | 35| ArkWeb_OnJavaScriptProxyCallback | ArkWeb_OnJavaScriptProxyCallbackWithResult | Proxy方法被执行的回调。 | 36| ArkWeb_ProxyMethod | ArkWeb_ProxyMethodWithResult | 注入的Proxy方法通用结构体。 | 37| ArkWeb_ProxyObject | ArkWeb_ProxyObjectWithResult | 注入的Proxy对象通用结构体。 | 38| registerJavaScriptProxy | registerJavaScriptProxyEx | 注入JavaScript对象到window对象中,并在window对象中调用该对象的同步方法。 | 39| registerAsyncJavaScriptProxy | registerAsyncJavaScriptProxyEx | 注入JavaScript对象到window对象中,并在window对象中调用该对象的异步方法。 | 40 41### 使用Native接口绑定ArkWeb 42 43* ArkWeb组件声明在ArkTS侧,需要用户自定义一个标识webTag,并将webTag通过Node-API传至应用Native侧,后续ArkWeb Native接口使用,均需webTag作为对应组件的唯一标识。 44 45* ArkTS侧 46 47 ```js 48 // 自定义webTag,在WebviewController创建时作为入参传入,建立controller与webTag的映射关系 49 webTag: string = 'ArkWeb1'; 50 controller: webview.WebviewController = new webview.WebviewController(this.webTag); 51 52 // 在aboutToAppear方法中,通过Node-API接口将webTag传入C++侧,C++侧使用webTag作为ArkWeb组件的唯一标识 53 aboutToAppear() { 54 console.info("aboutToAppear") 55 //初始化web ndk 56 testNapi.nativeWebInit(this.webTag); 57 } 58 ``` 59 60* C++侧 61 62 ```c++ 63 // 解析存储webTag 64 static napi_value NativeWebInit(napi_env env, napi_callback_info info) { 65 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit start"); 66 size_t argc = 1; 67 napi_value args[1] = {nullptr}; 68 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 69 // 获取第一个参数webTag 70 size_t webTagSize = 0; 71 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 72 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 73 size_t webTagLength = 0; 74 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 75 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit webTag:%{public}s", webTagValue); 76 77 // 将webTag保存在实例对象中 78 jsbridge_object_ptr = std::make_shared<JSBridgeObject>(webTagValue); 79 // ... 80 } 81 ``` 82 83### 使用Native接口获取API结构体 84 85在ArkWeb Native侧,需要先获取API结构体,才能调用结构体里的Native API。ArkWeb Native侧API通过函数[OH_ArkWeb_GetNativeAPI](../reference/apis-arkweb/capi-arkweb-interface-h.md#oh_arkweb_getnativeapi)获取,根据入参type不同,可分别获取[ArkWeb_ControllerAPI](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md)、[ArkWeb_ComponentAPI](../reference/apis-arkweb/capi-web-arkweb-componentapi.md)结构体。其中,[ArkWeb_ControllerAPI](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md)对应ArkTS侧[web_webview.WebviewController API](../reference/apis-arkweb/arkts-apis-webview-WebviewController.md),[ArkWeb_ComponentAPI](../reference/apis-arkweb/capi-web-arkweb-componentapi.md)对应ArkTS侧[ArkWeb组件API](../reference/apis-arkweb/arkts-basic-components-web.md)。 86 87 ```c++ 88 static ArkWeb_ControllerAPI *controller = nullptr; 89 static ArkWeb_ComponentAPI *component = nullptr; 90 // ... 91 controller = reinterpret_cast<ArkWeb_ControllerAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_CONTROLLER)); 92 component = reinterpret_cast<ArkWeb_ComponentAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_COMPONENT)); 93 ``` 94 95### Native侧注册组件生命周期回调 96 97通过[ArkWeb_ComponentAPI](../reference/apis-arkweb/capi-web-arkweb-componentapi.md)注册组件生命周期回调,调用接口前,建议通过[ARKWEB_MEMBER_MISSING](../reference/apis-arkweb/capi-arkweb-type-h.md#宏定义)校验该函数结构体中是否存在对应函数指针,以避免SDK与设备ROM不匹配导致crash问题。 98 99 ```c++ 100 if (!ARKWEB_MEMBER_MISSING(component, onControllerAttached)) { 101 component->onControllerAttached(webTagValue, ValidCallback, 102 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 103 } else { 104 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onControllerAttached func not exist"); 105 } 106 107 if (!ARKWEB_MEMBER_MISSING(component, onPageBegin)) { 108 component->onPageBegin(webTagValue, LoadStartCallback, 109 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 110 } else { 111 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageBegin func not exist"); 112 } 113 114 if (!ARKWEB_MEMBER_MISSING(component, onPageEnd)) { 115 component->onPageEnd(webTagValue, LoadEndCallback, 116 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 117 } else { 118 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageEnd func not exist"); 119 } 120 121 if (!ARKWEB_MEMBER_MISSING(component, onDestroy)) { 122 component->onDestroy(webTagValue, DestroyCallback, 123 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 124 } else { 125 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onDestroy func not exist"); 126 } 127 ``` 128 129### 前端页面调用应用侧函数 130 131通过[registerJavaScriptProxyEx](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md#registerjavascriptproxyex)将应用侧函数注册至前端页面,推荐在[onControllerAttached](../reference/apis-arkweb/capi-web-arkweb-componentapi.md#oncontrollerattached)回调中注册应用侧函数,如果在其它时机注册,需要手动调用[refresh](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md#refresh)才能生效。 132 133 ```c++ 134 // 注册对象 135 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk registerJavaScriptProxyEx begin"); 136 ArkWeb_ProxyMethodWithResult method1 = {"method1", ProxyMethod1, static_cast<void *>(jsbridge_object_ptr->GetWeakPt ())}; 137 ArkWeb_ProxyMethodWithResult method2 = {"method2", ProxyMethod2, static_cast<void *>(jsbridge_object_ptr->GetWeakPt ())}; 138 ArkWeb_ProxyMethodWithResult methodList[2] = {method1, method2}; 139 // 调用ndk接口注册对象 140 // 如此注册的情况下,在H5页面就可以使用proxy.method1、proxy.method2调用此文件下的ProxyMethod1和ProxyMethod2方法了 141 ArkWeb_ProxyObjectWithResult proxyObject = {"ndkProxy", methodList, 2}; 142 // 参数permission为空,表示不进行权限管控 143 controller->registerJavaScriptProxyEx(webTag, &proxyObject, /*permission*/""); 144 ``` 145 146 - 参数permission是一个JSON字符串,示例如下: 147 ```json 148 { 149 "javascriptProxyPermission": { 150 "urlPermissionList": [ // Object级权限,如果匹配,所有Method都授权 151 { 152 "scheme": "resource", // 精确匹配,不能为空 153 "host": "rawfile", // 精确匹配,不能为空 154 "port": "", // 精确匹配,为空不检查 155 "path": "" // 前缀匹配,为空不检查 156 }, 157 { 158 "scheme": "https", // 精确匹配,不能为空 159 "host": "xxx.com", // 精确匹配,不能为空 160 "port": "8080", // 精确匹配,为空不检查 161 "path": "a/b/c" // 前缀匹配,为空不检查 162 } 163 ], 164 "methodList": [ 165 { 166 "methodName": "test", 167 "urlPermissionList": [ // Method级权限 168 { 169 "scheme": "https", // 精确匹配,不能为空 170 "host": "xxx.com", // 精确匹配,不能为空 171 "port": "", // 精确匹配,为空不检查 172 "path": "" // 前缀匹配,为空不检查 173 }, 174 { 175 "scheme": "resource",// 精确匹配,不能为空 176 "host": "rawfile", // 精确匹配,不能为空 177 "port": "", // 精确匹配,为空不检查 178 "path": "" // 前缀匹配,为空不检查 179 } 180 ] 181 }, 182 { 183 "methodName": "test11", 184 "urlPermissionList": [ // Method级权限 185 { 186 "scheme": "q", // 精确匹配,不能为空 187 "host": "r", // 精确匹配,不能为空 188 "port": "", // 精确匹配,为空不检查 189 "path": "t" // 前缀匹配,为空不检查 190 }, 191 { 192 "scheme": "u", // 精确匹配,不能为空 193 "host": "v", // 精确匹配,不能为空 194 "port": "", // 精确匹配,为空不检查 195 "path": "" // 前缀匹配,为空不检查 196 } 197 ] 198 } 199 ] 200 } 201 } 202 ``` 203 204### 应用侧调用前端页面函数 205 206使用[runJavaScript](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md#runjavascript)调用前端页面函数。 207 208 ```c++ 209 // 构造runJS执行的结构体 210 char* jsCode = "runJSRetStr()"; 211 ArkWeb_JavaScriptObject object = {(uint8_t *)jsCode, bufferSize, &JSBridgeObject::StaticRunJavaScriptCallback, 212 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 213 // 调用前端页面runJSRetStr()函数 214 controller->runJavaScript(webTagValue, &object); 215 ``` 216 217### 完整示例 218 219* 前端页面代码 220 221 ```html 222 <!-- entry/src/main/resources/rawfile/runJS.html --> 223 <!-- runJS.html --> 224 <!DOCTYPE html> 225 <html lang="en-gb"> 226 <head> 227 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 228 <title>run javascript demo</title> 229 </head> 230 <body> 231 <h1>run JavaScript Ext demo</h1> 232 <p id="webDemo"></p> 233 <br> 234 <button type="button" style="height:30px;width:200px" onclick="testNdkProxyObjMethod1()">test ndk method1 ! </button> 235 <br> 236 <br> 237 <button type="button" style="height:30px;width:200px" onclick="testNdkProxyObjMethod2()">test ndk method2 ! </button> 238 <br> 239 240 </body> 241 <script type="text/javascript"> 242 243 function testNdkProxyObjMethod1() { 244 if (window.ndkProxy == undefined) { 245 document.getElementById("webDemo").innerHTML = "ndkProxy undefined" 246 return "objName undefined" 247 } 248 249 if (window.ndkProxy.method1 == undefined) { 250 document.getElementById("webDemo").innerHTML = "ndkProxy method1 undefined" 251 return "objName test undefined" 252 } 253 254 let retStr = window.ndkProxy.method1("hello", "world", [1.2, -3.4, 123.456], ["Saab", "Volvo", "BMW", undefined], 1.23456, 123789, true, false, 0, undefined); 255 console.log("ndkProxy and method1 is ok, " + retStr + ", type:" + typeof(retStr)); 256 } 257 258 function testNdkProxyObjMethod2() { 259 if (window.ndkProxy == undefined) { 260 document.getElementById("webDemo").innerHTML = "ndkProxy undefined" 261 return "objName undefined" 262 } 263 264 if (window.ndkProxy.method2 == undefined) { 265 document.getElementById("webDemo").innerHTML = "ndkProxy method2 undefined" 266 return "objName test undefined" 267 } 268 269 var student = { 270 name:"zhang", 271 sex:"man", 272 age:25 273 }; 274 var cars = [student, 456, false, 4.567]; 275 let params = "[\"{\\\"scope\\\"]"; 276 277 let retStr = window.ndkProxy.method2("hello", "world", false, cars, params); 278 console.log("ndkProxy and method2 is ok, " + retStr + ", type:" + typeof(retStr)); 279 } 280 281 function runJSRetStr(data) { 282 const d = new Date(); 283 let time = d.getTime(); 284 return JSON.stringify(time) 285 } 286 </script> 287 </html> 288 ``` 289 290* ArkTS侧代码 291 292 ```javascript 293 // entry/src/main/ets/pages/Index.ets 294 import testNapi from 'libentry.so'; 295 import { webview } from '@kit.ArkWeb'; 296 297 class testObj { 298 constructor() { 299 } 300 301 test(): string { 302 console.log('ArkUI Web Component'); 303 return "ArkUI Web Component"; 304 } 305 306 toString(): void { 307 console.log('Web Component toString'); 308 } 309 } 310 311 @Entry 312 @Component 313 struct Index { 314 webTag: string = 'ArkWeb1'; 315 controller: webview.WebviewController = new webview.WebviewController(this.webTag); 316 @State testObjtest: testObj = new testObj(); 317 318 aboutToAppear() { 319 console.info("aboutToAppear") 320 //初始化web ndk 321 testNapi.nativeWebInit(this.webTag); 322 } 323 324 build() { 325 Column() { 326 Row() { 327 Button('runJS hello') 328 .fontSize(12) 329 .onClick(() => { 330 testNapi.runJavaScript(this.webTag, "runJSRetStr(\"" + "hello" + "\")"); 331 }) 332 }.height('20%') 333 334 Row() { 335 Web({ src: $rawfile('runJS.html'), controller: this.controller }) 336 .javaScriptAccess(true) 337 .fileAccess(true) 338 .onControllerAttached(() => { 339 console.error("ndk onControllerAttached webId: " + this.controller.getWebId()); 340 }) 341 }.height('80%') 342 } 343 } 344 } 345 ``` 346 347* Node-API侧暴露ArkTS接口 348 349 ```javascript 350 // entry/src/main/cpp/types/libentry/index.d.ts 351 export const nativeWebInit: (webName: string) => void; 352 export const runJavaScript: (webName: string, jsCode: string) => void; 353 ``` 354 355* Node-API侧编译配置`entry/src/main/cpp/CMakeLists.txt` 356 357 ```c++ 358 # the minimum version of CMake. 359 cmake_minimum_required(VERSION 3.4.1) 360 project(NDKJSBridg) 361 362 set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 363 364 if(DEFINED PACKAGE_FIND_FILE) 365 include(${PACKAGE_FIND_FILE}) 366 endif() 367 368 include_directories(${NATIVERENDER_ROOT_PATH} 369 ${NATIVERENDER_ROOT_PATH}/include) 370 371 add_library(entry SHARED hello.cpp jsbridge_object.cpp) 372 373 find_library( 374 # Sets the name of the path variable. 375 hilog-lib 376 # Specifies the name of the NDK library that 377 # you want CMake to locate. 378 hilog_ndk.z 379 ) 380 381 target_link_libraries(entry PUBLIC libace_napi.z.so ${hilog-lib} libohweb.so) 382 ``` 383 384* Node-API层代码 385 386 ```c++ 387 // entry/src/main/cpp/hello.cpp 388 #include "napi/native_api.h" 389 #include <bits/alltypes.h> 390 #include <memory> 391 #include <string> 392 #include <sys/types.h> 393 #include <thread> 394 395 #include "hilog/log.h" 396 #include "web/arkweb_interface.h" 397 #include "jsbridge_object.h" 398 399 constexpr unsigned int LOG_PRINT_DOMAIN = 0xFF00; 400 std::shared_ptr<JSBridgeObject> jsbridge_object_ptr = nullptr; 401 static ArkWeb_ControllerAPI *controller = nullptr; 402 static ArkWeb_ComponentAPI *component = nullptr; 403 ArkWeb_JavaScriptValueAPI *javaScriptValueApi = nullptr; 404 405 // 发送JS脚本到H5侧执行,该方法为执行结果的回调。 406 static void RunJavaScriptCallback(const char *webTag, const char *result, void *userData) { 407 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RunJavaScriptCallback webTag:%{public}s", webTag); 408 if (!userData) { 409 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RunJavaScriptCallback userData is nullptr"); 410 return; 411 } 412 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 413 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 414 jsb_ptr->RunJavaScriptCallback(result); 415 } else { 416 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 417 "ndk RunJavaScriptCallback jsb_weak_ptr lock failed"); 418 } 419 } 420 421 // 示例代码 ,注册了1个对象,2个方法 422 static ArkWeb_JavaScriptValuePtr ProxyMethod1(const char *webTag, const ArkWeb_JavaScriptBridgeData *dataArray, size_t arraySize, void *userData) { 423 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 webTag:%{public}s", webTag); 424 if (!userData) { 425 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 userData is nullptr"); 426 return nullptr; 427 } 428 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 429 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 430 jsb_ptr->ProxyMethod1(dataArray, arraySize); 431 } else { 432 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 jsb_weak_ptr lock failed"); 433 } 434 435 bool boolValue = true; 436 return javaScriptValueApi->createJavaScriptValue(ArkWeb_JavaScriptValueType::ARKWEB_JAVASCRIPT_BOOL, (void*)(&boolValue), 1); 437 } 438 439 static ArkWeb_JavaScriptValuePtr ProxyMethod2(const char *webTag, const ArkWeb_JavaScriptBridgeData *dataArray, size_t arraySize, void *userData) { 440 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 webTag:%{public}s", webTag); 441 if (!userData) { 442 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 userData is nullptr"); 443 return nullptr; 444 } 445 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 446 447 std::string jsCode = "runJSRetStr()"; 448 ArkWeb_JavaScriptObject object = {(uint8_t *)jsCode.c_str(), jsCode.size(), 449 &JSBridgeObject::StaticRunJavaScriptCallback, 450 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 451 controller->runJavaScript(webTag, &object); 452 453 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 454 jsb_ptr->ProxyMethod2(dataArray, arraySize); 455 } else { 456 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 jsb_weak_ptr lock failed"); 457 } 458 459 std::string str = "this is a string"; 460 return javaScriptValueApi->createJavaScriptValue(ArkWeb_JavaScriptValueType::ARKWEB_JAVASCRIPT_STRING, (void*)str.c_str(), str.length() + 1); 461 } 462 463 void ValidCallback(const char *webTag, void *userData) { 464 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback webTag: %{public}s", webTag); 465 if (!userData) { 466 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback userData is nullptr"); 467 return; 468 } 469 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 470 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 471 jsb_ptr->SaySomething("ValidCallback"); 472 } else { 473 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback jsb_weak_ptr lock failed"); 474 } 475 476 // 注册对象 477 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk registerJavaScriptProxyEx begin"); 478 ArkWeb_ProxyMethodWithResult method1 = {"method1", ProxyMethod1, static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 479 ArkWeb_ProxyMethodWithResult method2 = {"method2", ProxyMethod2, static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 480 ArkWeb_ProxyMethodWithResult methodList[2] = {method1, method2}; 481 // 调用ndk接口注册对象 482 // 如此注册的情况下,在H5页面就可以使用proxy.method1、proxy.method2调用此文件下的ProxyMethod1和ProxyMethod2方法了 483 ArkWeb_ProxyObjectWithResult proxyObject = {"ndkProxy", methodList, 2}; 484 controller->registerJavaScriptProxyEx(webTag, &proxyObject, ""); 485 486 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk registerJavaScriptProxyEx end"); 487 } 488 489 void LoadStartCallback(const char *webTag, void *userData) { 490 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadStartCallback webTag: %{public}s", webTag); 491 if (!userData) { 492 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadStartCallback userData is nullptr"); 493 return; 494 } 495 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 496 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 497 jsb_ptr->SaySomething("LoadStartCallback"); 498 } else { 499 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadStartCallback jsb_weak_ptr lock failed"); 500 } 501 } 502 503 void LoadEndCallback(const char *webTag, void *userData) { 504 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadEndCallback webTag: %{public}s", webTag); 505 if (!userData) { 506 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadEndCallback userData is nullptr"); 507 return; 508 } 509 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 510 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 511 jsb_ptr->SaySomething("LoadEndCallback"); 512 } else { 513 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadEndCallback jsb_weak_ptr lock failed"); 514 } 515 } 516 517 void DestroyCallback(const char *webTag, void *userData) { 518 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestoryCallback webTag: %{public}s", webTag); 519 if (!userData) { 520 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestroyCallback userData is nullptr"); 521 return; 522 } 523 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 524 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 525 jsb_ptr->SaySomething("DestroyCallback"); 526 } else { 527 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestroyCallback jsb_weak_ptr lock failed"); 528 } 529 } 530 531 void SetComponentCallback(ArkWeb_ComponentAPI * component, const char* webTagValue) { 532 if (!ARKWEB_MEMBER_MISSING(component, onControllerAttached)) { 533 component->onControllerAttached(webTagValue, ValidCallback, 534 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 535 } else { 536 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onControllerAttached func not exist"); 537 } 538 539 if (!ARKWEB_MEMBER_MISSING(component, onPageBegin)) { 540 component->onPageBegin(webTagValue, LoadStartCallback, 541 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 542 } else { 543 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageBegin func not exist"); 544 } 545 546 if (!ARKWEB_MEMBER_MISSING(component, onPageEnd)) { 547 component->onPageEnd(webTagValue, LoadEndCallback, 548 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 549 } else { 550 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageEnd func not exist"); 551 } 552 553 if (!ARKWEB_MEMBER_MISSING(component, onDestroy)) { 554 component->onDestroy(webTagValue, DestroyCallback, 555 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 556 } else { 557 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onDestroy func not exist"); 558 } 559 } 560 561 // 解析存储webTag 562 static napi_value NativeWebInit(napi_env env, napi_callback_info info) { 563 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit start"); 564 size_t argc = 1; 565 napi_value args[1] = {nullptr}; 566 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 567 // 获取第一个参数 webTag 568 size_t webTagSize = 0; 569 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 570 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 571 size_t webTagLength = 0; 572 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 573 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit webTag:%{public}s", webTagValue); 574 575 jsbridge_object_ptr = std::make_shared<JSBridgeObject>(webTagValue); 576 if (jsbridge_object_ptr) 577 jsbridge_object_ptr->Init(); 578 579 controller = reinterpret_cast<ArkWeb_ControllerAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_CONTROLLER)); 580 if (controller) 581 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "get ArkWeb_ControllerAPI success"); 582 583 component = reinterpret_cast<ArkWeb_ComponentAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_COMPONENT)); 584 if (component) 585 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "get ArkWeb_ComponentAPI success"); 586 587 javaScriptValueApi = 588 reinterpret_cast<ArkWeb_JavaScriptValueAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_JAVASCRIPT_VALUE)); 589 if (javaScriptValueApi) 590 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "get ArkWeb_JavaScriptValueAPI success"); 591 else 592 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "get ArkWeb_JavaScriptValueAPI failed"); 593 594 SetComponentCallback(component, webTagValue); 595 596 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit end"); 597 598 delete[] webTagValue; 599 600 return nullptr; 601 } 602 603 // 发送JS脚本到H5侧执行 604 static napi_value RunJavaScript(napi_env env, napi_callback_info info) { 605 size_t argc = 2; 606 napi_value args[2] = {nullptr}; 607 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 608 609 // 获取第一个参数webTag 610 size_t webTagSize = 0; 611 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 612 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 613 size_t webTagLength = 0; 614 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 615 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk OH_NativeArkWeb_RunJavaScript webTag:%{public}s", 616 webTagValue); 617 618 // 获取第二个参数 jsCode 619 size_t bufferSize = 0; 620 napi_get_value_string_utf8(env, args[1], nullptr, 0, &bufferSize); 621 char *jsCode = new (std::nothrow) char[bufferSize + 1]; 622 size_t byteLength = 0; 623 napi_get_value_string_utf8(env, args[1], jsCode, bufferSize + 1, &byteLength); 624 625 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 626 "ndk OH_NativeArkWeb_RunJavaScript jsCode len:%{public}zu", strlen(jsCode)); 627 628 // 构造runJS执行的结构体 629 ArkWeb_JavaScriptObject object = {(uint8_t *)jsCode, bufferSize, &JSBridgeObject::StaticRunJavaScriptCallback, 630 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 631 controller->runJavaScript(webTagValue, &object); 632 633 delete[] webTagValue; 634 635 delete[] jsCode; 636 637 return nullptr; 638 } 639 640 EXTERN_C_START 641 static napi_value Init(napi_env env, napi_value exports) { 642 napi_property_descriptor desc[] = { 643 {"nativeWebInit", nullptr, NativeWebInit, nullptr, nullptr, nullptr, napi_default, nullptr}, 644 {"runJavaScript", nullptr, RunJavaScript, nullptr, nullptr, nullptr, napi_default, nullptr}, 645 }; 646 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 647 return exports; 648 } 649 EXTERN_C_END 650 651 static napi_module demoModule = { 652 .nm_version = 1, 653 .nm_flags = 0, 654 .nm_filename = nullptr, 655 .nm_register_func = Init, 656 .nm_modname = "entry", 657 .nm_priv = ((void *)0), 658 .reserved = {0}, 659 }; 660 661 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } 662 ``` 663 664* Native侧业务代码 665 666 ```c++ 667 // entry/src/main/cpp/jsbridge_object.h 668 #include "web/arkweb_type.h" 669 #include <string> 670 671 class JSBridgeObject : public std::enable_shared_from_this<JSBridgeObject> { 672 public: 673 JSBridgeObject(const char* webTag); 674 ~JSBridgeObject() = default; 675 void Init(); 676 std::weak_ptr<JSBridgeObject>* GetWeakPtr(); 677 static void StaticRunJavaScriptCallback(const char *webTag, const ArkWeb_JavaScriptBridgeData *data, void *userData); 678 void RunJavaScriptCallback(const char *result); 679 void ProxyMethod1(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize); 680 void ProxyMethod2(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize); 681 void SaySomething(const char* say); 682 683 private: 684 std::string webTag_; 685 std::weak_ptr<JSBridgeObject> weak_ptr_; 686 }; 687 ``` 688 689 ```c++ 690 // entry/src/main/cpp/jsbridge_object.cpp 691 #include "jsbridge_object.h" 692 693 #include "hilog/log.h" 694 695 constexpr unsigned int LOG_PRINT_DOMAIN = 0xFF00; 696 697 JSBridgeObject::JSBridgeObject(const char *webTag) : webTag_(webTag) {} 698 699 void JSBridgeObject::Init() { weak_ptr_ = shared_from_this(); } 700 701 std::weak_ptr<JSBridgeObject> *JSBridgeObject::GetWeakPtr() { return &weak_ptr_; } 702 703 void JSBridgeObject::StaticRunJavaScriptCallback(const char *webTag, const ArkWeb_JavaScriptBridgeData *data, 704 void *userData) { 705 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 706 "JSBridgeObject StaticRunJavaScriptCallback webTag:%{public}s", webTag); 707 if (!userData) { 708 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 709 "JSBridgeObject StaticRunJavaScriptCallback userData is nullptr"); 710 return; 711 } 712 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 713 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 714 std::string result((char *)data->buffer, data->size); 715 jsb_ptr->RunJavaScriptCallback(result.c_str()); 716 } else { 717 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 718 "JSBridgeObject StaticRunJavaScriptCallback jsb_weak_ptr lock failed"); 719 } 720 } 721 722 void JSBridgeObject::RunJavaScriptCallback(const char *result) { 723 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 724 "JSBridgeObject OH_NativeArkWeb_RunJavaScript result:%{public}s", result); 725 } 726 727 void JSBridgeObject::ProxyMethod1(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize) { 728 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "JSBridgeObject ProxyMethod1 argc:%{public}d", 729 arraySize); 730 for (int i = 0; i < arraySize; i++) { 731 std::string result((char *)dataArray[i].buffer, dataArray[i].size); 732 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 733 "JSBridgeObject ProxyMethod1 argv[%{public}d]:%{public}s, size:%{public}d", i, result.c_str(), 734 dataArray[i].size); 735 } 736 } 737 738 void JSBridgeObject::ProxyMethod2(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize) { 739 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "JSBridgeObject ProxyMethod2 argc:%{public}d", 740 arraySize); 741 for (int i = 0; i < arraySize; i++) { 742 std::string result((char *)dataArray[i].buffer, dataArray[i].size); 743 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 744 "JSBridgeObject ProxyMethod2 argv[%{public}d]:%{public}s, size:%{public}d", i, result.c_str(), 745 dataArray[i].size); 746 } 747 } 748 749 void JSBridgeObject::SaySomething(const char *say) { 750 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "JSBridgeObject SaySomething argc:%{public}s", say); 751 } 752 ``` 753 754## 使用Native接口实现JSBridge通信 755 756### 使用Native接口绑定ArkWeb 757 758* ArkWeb组件声明在ArkTS侧,需要用户自定义一个标识webTag,并将webTag通过Node-API传至应用Native侧,后续ArkWeb Native接口使用,均需webTag作为对应组件的唯一标识。 759 760* ArkTS侧 761 762 ```js 763 // 自定义webTag,在WebviewController创建时作为入参传入,建立controller与webTag的映射关系 764 webTag: string = 'ArkWeb1'; 765 controller: webview.WebviewController = new webview.WebviewController(this.webTag); 766 // ... 767 // aboutToAppear中将webTag通过Node-API接口传入C++侧,作为C++侧ArkWeb组件的唯一标识 768 aboutToAppear() { 769 console.info("aboutToAppear") 770 //初始化web ndk 771 testNapi.nativeWebInit(this.webTag); 772 } 773 // ... 774 ``` 775 776* C++侧 777 778 ```c++ 779 // 解析存储webTag 780 static napi_value NativeWebInit(napi_env env, napi_callback_info info) { 781 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit start"); 782 size_t argc = 1; 783 napi_value args[1] = {nullptr}; 784 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 785 // 获取第一个参数webTag 786 size_t webTagSize = 0; 787 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 788 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 789 size_t webTagLength = 0; 790 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 791 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit webTag:%{public}s", webTagValue); 792 793 // 将webTag保存在实例对象中 794 jsbridge_object_ptr = std::make_shared<JSBridgeObject>(webTagValue); 795 // ... 796 } 797 ``` 798 799### 使用Native接口获取API结构体 800 801ArkWeb Native侧得先获取API结构体,才能调用结构体里的Native API。ArkWeb Native侧API通过函数[OH_ArkWeb_GetNativeAPI](../reference/apis-arkweb/capi-arkweb-interface-h.md#oh_arkweb_getnativeapi)获取,根据入参type不同,可分别获取[ArkWeb_ControllerAPI](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md)、[ArkWeb_ComponentAPI](../reference/apis-arkweb/capi-web-arkweb-componentapi.md)函数指针结构体。其中,[ArkWeb_ControllerAPI](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md)对应ArkTS侧[web_webview.WebviewController API](../reference/apis-arkweb/arkts-apis-webview-WebviewController.md),[ArkWeb_ComponentAPI](../reference/apis-arkweb/capi-web-arkweb-componentapi.md)对应ArkTS侧[ArkWeb组件API](../reference/apis-arkweb/arkts-basic-components-web.md)。 802 803 ```c++ 804 static ArkWeb_ControllerAPI *controller = nullptr; 805 static ArkWeb_ComponentAPI *component = nullptr; 806 // ... 807 controller = reinterpret_cast<ArkWeb_ControllerAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_CONTROLLER)); 808 component = reinterpret_cast<ArkWeb_ComponentAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_COMPONENT)); 809 ``` 810 811### Native侧注册组件生命周期回调 812 813通过[ArkWeb_ComponentAPI](../reference/apis-arkweb/capi-web-arkweb-componentapi.md)注册组件生命周期回调,在调用接口前建议通过[ARKWEB_MEMBER_MISSING](../reference/apis-arkweb/capi-arkweb-type-h.md#宏定义)校验该函数结构体是否有对应函数指针,避免SDK与设备ROM不匹配导致crash问题。 814 815 ```c++ 816 if (!ARKWEB_MEMBER_MISSING(component, onControllerAttached)) { 817 component->onControllerAttached(webTagValue, ValidCallback, 818 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 819 } else { 820 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onControllerAttached func not exist"); 821 } 822 823 if (!ARKWEB_MEMBER_MISSING(component, onPageBegin)) { 824 component->onPageBegin(webTagValue, LoadStartCallback, 825 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 826 } else { 827 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageBegin func not exist"); 828 } 829 830 if (!ARKWEB_MEMBER_MISSING(component, onPageEnd)) { 831 component->onPageEnd(webTagValue, LoadEndCallback, 832 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 833 } else { 834 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageEnd func not exist"); 835 } 836 837 if (!ARKWEB_MEMBER_MISSING(component, onDestroy)) { 838 component->onDestroy(webTagValue, DestroyCallback, 839 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 840 } else { 841 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onDestroy func not exist"); 842 } 843 ``` 844 845### 前端页面调用应用侧函数 846 847通过[registerJavaScriptProxy](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md#registerjavascriptproxy)将应用侧函数注册至前端页面,推荐在[onControllerAttached](../reference/apis-arkweb/capi-web-arkweb-componentapi.md#oncontrollerattached)回调中注册,其它时机注册需要手动调用[refresh](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md#refresh)才能生效。 848 849 ```c++ 850 // 注册对象 851 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RegisterJavaScriptProxy begin"); 852 ArkWeb_ProxyMethod method1 = {"method1", ProxyMethod1, static_cast<void *>(jsbridge_object_ptr->GetWeakPt ())}; 853 ArkWeb_ProxyMethod method2 = {"method2", ProxyMethod2, static_cast<void *>(jsbridge_object_ptr->GetWeakPt ())}; 854 ArkWeb_ProxyMethod methodList[2] = {method1, method2}; 855 // 调用ndk接口注册对象 856 // 如此注册的情况下,在H5页面就可以使用proxy.method1、proxy.method2调用此文件下的ProxyMethod1和ProxyMethod2方法了 857 ArkWeb_ProxyObject proxyObject = {"ndkProxy", methodList, 2}; 858 controller->registerJavaScriptProxy(webTag, &proxyObject); 859 ``` 860 861### 应用侧调用前端页面函数 862 863通过[runJavaScript](../reference/apis-arkweb/capi-web-arkweb-controllerapi.md#runjavascript)调用前端页面函数。 864 865 ```c++ 866 // 构造runJS执行的结构体 867 const char* jsCode = "runJSRetStr()"; 868 ArkWeb_JavaScriptObject object = {(uint8_t *)jsCode, bufferSize, &JSBridgeObject::StaticRunJavaScriptCallback, 869 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 870 // 调用前端页面runJSRetStr()函数 871 controller->runJavaScript(webTagValue, &object); 872 ``` 873 874### 完整示例 875 876* 前端页面代码 877 878 ```html 879 <!-- entry/src/main/resources/rawfile/runJS.html --> 880 <!-- runJS.html --> 881 <!DOCTYPE html> 882 <html lang="en-gb"> 883 <head> 884 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 885 <title>run javascript demo</title> 886 </head> 887 <body> 888 <h1>run JavaScript Ext demo</h1> 889 <p id="webDemo"></p> 890 <br> 891 <button type="button" style="height:30px;width:200px" onclick="testNdkProxyObjMethod1()">test ndk method1 ! </button> 892 <br> 893 <br> 894 <button type="button" style="height:30px;width:200px" onclick="testNdkProxyObjMethod2()">test ndk method2 ! </button> 895 <br> 896 897 </body> 898 <script type="text/javascript"> 899 900 function testNdkProxyObjMethod1() { 901 if (window.ndkProxy == undefined) { 902 document.getElementById("webDemo").innerHTML = "ndkProxy undefined" 903 return "objName undefined" 904 } 905 906 if (window.ndkProxy.method1 == undefined) { 907 document.getElementById("webDemo").innerHTML = "ndkProxy method1 undefined" 908 return "objName test undefined" 909 } 910 911 window.ndkProxy.method1("hello", "world", [1.2, -3.4, 123.456], ["Saab", "Volvo", "BMW", undefined], 1.23456, 123789, true, false, 0, undefined); 912 } 913 914 function testNdkProxyObjMethod2() { 915 if (window.ndkProxy == undefined) { 916 document.getElementById("webDemo").innerHTML = "ndkProxy undefined" 917 return "objName undefined" 918 } 919 920 if (window.ndkProxy.method2 == undefined) { 921 document.getElementById("webDemo").innerHTML = "ndkProxy method2 undefined" 922 return "objName test undefined" 923 } 924 925 var student = { 926 name:"zhang", 927 sex:"man", 928 age:25 929 }; 930 var cars = [student, 456, false, 4.567]; 931 let params = "[\"{\\\"scope\\\"]"; 932 933 window.ndkProxy.method2("hello", "world", false, cars, params); 934 } 935 936 function runJSRetStr(data) { 937 const d = new Date(); 938 let time = d.getTime(); 939 return JSON.stringify(time) 940 } 941 </script> 942 </html> 943 ``` 944 945* ArkTS侧代码 946 947 ```javascript 948 // entry/src/main/ets/pages/Index.ets 949 import testNapi from 'libentry.so'; 950 import { webview } from '@kit.ArkWeb'; 951 952 class testObj { 953 constructor() { 954 } 955 956 test(): string { 957 console.log('ArkUI Web Component'); 958 return "ArkUI Web Component"; 959 } 960 961 toString(): void { 962 console.log('Web Component toString'); 963 } 964 } 965 966 @Entry 967 @Component 968 struct Index { 969 webTag: string = 'ArkWeb1'; 970 controller: webview.WebviewController = new webview.WebviewController(this.webTag); 971 @State testObjtest: testObj = new testObj(); 972 973 aboutToAppear() { 974 console.info("aboutToAppear") 975 //初始化web ndk 976 testNapi.nativeWebInit(this.webTag); 977 } 978 979 build() { 980 Column() { 981 Row() { 982 Button('runJS hello') 983 .fontSize(12) 984 .onClick(() => { 985 testNapi.runJavaScript(this.webTag, "runJSRetStr(\"" + "hello" + "\")"); 986 }) 987 }.height('20%') 988 989 Row() { 990 Web({ src: $rawfile('runJS.html'), controller: this.controller }) 991 .javaScriptAccess(true) 992 .fileAccess(true) 993 .onControllerAttached(() => { 994 console.error("ndk onControllerAttached webId: " + this.controller.getWebId()); 995 }) 996 }.height('80%') 997 } 998 } 999 } 1000 ``` 1001 1002* Node-API侧暴露ArkTS接口 1003 1004 ```javascript 1005 // entry/src/main/cpp/types/libentry/index.d.ts 1006 export const nativeWebInit: (webName: string) => void; 1007 export const runJavaScript: (webName: string, jsCode: string) => void; 1008 ``` 1009 1010* Node-API侧编译配置`entry/src/main/cpp/CMakeLists.txt` 1011 1012 ```c++ 1013 # the minimum version of CMake. 1014 cmake_minimum_required(VERSION 3.4.1) 1015 project(NDKJSBridg) 1016 1017 set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 1018 1019 if(DEFINED PACKAGE_FIND_FILE) 1020 include(${PACKAGE_FIND_FILE}) 1021 endif() 1022 1023 include_directories(${NATIVERENDER_ROOT_PATH} 1024 ${NATIVERENDER_ROOT_PATH}/include) 1025 1026 add_library(entry SHARED hello.cpp jsbridge_object.cpp) 1027 1028 find_library( 1029 # Sets the name of the path variable. 1030 hilog-lib 1031 # Specifies the name of the NDK library that 1032 # you want CMake to locate. 1033 hilog_ndk.z 1034 ) 1035 1036 target_link_libraries(entry PUBLIC libace_napi.z.so ${hilog-lib} libohweb.so) 1037 ``` 1038 1039* Node-API层代码 1040 1041 ```c++ 1042 // entry/src/main/cpp/hello.cpp 1043 #include "napi/native_api.h" 1044 #include <bits/alltypes.h> 1045 #include <memory> 1046 #include <string> 1047 #include <sys/types.h> 1048 #include <thread> 1049 1050 #include "hilog/log.h" 1051 #include "web/arkweb_interface.h" 1052 #include "jsbridge_object.h" 1053 1054 constexpr unsigned int LOG_PRINT_DOMAIN = 0xFF00; 1055 std::shared_ptr<JSBridgeObject> jsbridge_object_ptr = nullptr; 1056 static ArkWeb_ControllerAPI *controller = nullptr; 1057 static ArkWeb_ComponentAPI *component = nullptr; 1058 1059 // 发送JS脚本到H5侧执行,该方法为执行结果的回调。 1060 static void RunJavaScriptCallback(const char *webTag, const char *result, void *userData) { 1061 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RunJavaScriptCallback webTag:%{public}s", webTag); 1062 if (!userData) { 1063 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RunJavaScriptCallback userData is nullptr"); 1064 return; 1065 } 1066 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1067 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1068 jsb_ptr->RunJavaScriptCallback(result); 1069 } else { 1070 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1071 "ndk RunJavaScriptCallback jsb_weak_ptr lock failed"); 1072 } 1073 } 1074 1075 // 示例代码 ,注册了1个对象,2个方法 1076 static void ProxyMethod1(const char *webTag, const ArkWeb_JavaScriptBridgeData *dataArray, size_t arraySize, void *userData) { 1077 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 webTag:%{public}s", webTag); 1078 if (!userData) { 1079 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 userData is nullptr"); 1080 return; 1081 } 1082 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1083 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1084 jsb_ptr->ProxyMethod1(dataArray, arraySize); 1085 } else { 1086 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 jsb_weak_ptr lock failed"); 1087 } 1088 } 1089 1090 static void ProxyMethod2(const char *webTag, const ArkWeb_JavaScriptBridgeData *dataArray, size_t arraySize, void *userData) { 1091 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 webTag:%{public}s", webTag); 1092 if (!userData) { 1093 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 userData is nullptr"); 1094 return; 1095 } 1096 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1097 1098 std::string jsCode = "runJSRetStr()"; 1099 ArkWeb_JavaScriptObject object = {(uint8_t *)jsCode.c_str(), jsCode.size(), 1100 &JSBridgeObject::StaticRunJavaScriptCallback, 1101 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 1102 controller->runJavaScript(webTag, &object); 1103 1104 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1105 jsb_ptr->ProxyMethod2(dataArray, arraySize); 1106 } else { 1107 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 jsb_weak_ptr lock failed"); 1108 } 1109 } 1110 1111 void ValidCallback(const char *webTag, void *userData) { 1112 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback webTag: %{public}s", webTag); 1113 if (!userData) { 1114 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback userData is nullptr"); 1115 return; 1116 } 1117 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1118 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1119 jsb_ptr->SaySomething("ValidCallback"); 1120 } else { 1121 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback jsb_weak_ptr lock failed"); 1122 } 1123 1124 // 注册对象 1125 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RegisterJavaScriptProxy begin"); 1126 ArkWeb_ProxyMethod method1 = {"method1", ProxyMethod1, static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 1127 ArkWeb_ProxyMethod method2 = {"method2", ProxyMethod2, static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 1128 ArkWeb_ProxyMethod methodList[2] = {method1, method2}; 1129 // 调用ndk接口注册对象 1130 // 如此注册的情况下,在H5页面就可以使用proxy.method1、proxy.method2调用此文件下的ProxyMethod1和ProxyMethod2方法了 1131 ArkWeb_ProxyObject proxyObject = {"ndkProxy", methodList, 2}; 1132 controller->registerJavaScriptProxy(webTag, &proxyObject); 1133 1134 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RegisterJavaScriptProxy end"); 1135 } 1136 1137 void LoadStartCallback(const char *webTag, void *userData) { 1138 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadStartCallback webTag: %{public}s", webTag); 1139 if (!userData) { 1140 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadStartCallback userData is nullptr"); 1141 return; 1142 } 1143 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1144 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1145 jsb_ptr->SaySomething("LoadStartCallback"); 1146 } else { 1147 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadStartCallback jsb_weak_ptr lock failed"); 1148 } 1149 } 1150 1151 void LoadEndCallback(const char *webTag, void *userData) { 1152 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadEndCallback webTag: %{public}s", webTag); 1153 if (!userData) { 1154 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadEndCallback userData is nullptr"); 1155 return; 1156 } 1157 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1158 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1159 jsb_ptr->SaySomething("LoadEndCallback"); 1160 } else { 1161 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadEndCallback jsb_weak_ptr lock failed"); 1162 } 1163 } 1164 1165 void DestroyCallback(const char *webTag, void *userData) { 1166 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestoryCallback webTag: %{public}s", webTag); 1167 if (!userData) { 1168 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestroyCallback userData is nullptr"); 1169 return; 1170 } 1171 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1172 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1173 jsb_ptr->SaySomething("DestroyCallback"); 1174 } else { 1175 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestroyCallback jsb_weak_ptr lock failed"); 1176 } 1177 } 1178 1179 void SetComponentCallback(ArkWeb_ComponentAPI * component, const char* webTagValue) { 1180 if (!ARKWEB_MEMBER_MISSING(component, onControllerAttached)) { 1181 component->onControllerAttached(webTagValue, ValidCallback, 1182 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 1183 } else { 1184 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onControllerAttached func not exist"); 1185 } 1186 1187 if (!ARKWEB_MEMBER_MISSING(component, onPageBegin)) { 1188 component->onPageBegin(webTagValue, LoadStartCallback, 1189 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 1190 } else { 1191 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageBegin func not exist"); 1192 } 1193 1194 if (!ARKWEB_MEMBER_MISSING(component, onPageEnd)) { 1195 component->onPageEnd(webTagValue, LoadEndCallback, 1196 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 1197 } else { 1198 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageEnd func not exist"); 1199 } 1200 1201 if (!ARKWEB_MEMBER_MISSING(component, onDestroy)) { 1202 component->onDestroy(webTagValue, DestroyCallback, 1203 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 1204 } else { 1205 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onDestroy func not exist"); 1206 } 1207 } 1208 1209 // 解析存储webTag 1210 static napi_value NativeWebInit(napi_env env, napi_callback_info info) { 1211 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit start"); 1212 size_t argc = 1; 1213 napi_value args[1] = {nullptr}; 1214 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 1215 // 获取第一个参数webTag 1216 size_t webTagSize = 0; 1217 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 1218 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 1219 size_t webTagLength = 0; 1220 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 1221 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit webTag:%{public}s", webTagValue); 1222 1223 // 将webTag保存在实例对象中 1224 jsbridge_object_ptr = std::make_shared<JSBridgeObject>(webTagValue); 1225 if (jsbridge_object_ptr) 1226 jsbridge_object_ptr->Init(); 1227 1228 controller = reinterpret_cast<ArkWeb_ControllerAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_CONTROLLER)); 1229 component = reinterpret_cast<ArkWeb_ComponentAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_COMPONENT)); 1230 SetComponentCallback(component, webTagValue); 1231 1232 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit end"); 1233 delete[] webTagValue; 1234 return nullptr; 1235 } 1236 1237 // 发送JS脚本到H5侧执行 1238 static napi_value RunJavaScript(napi_env env, napi_callback_info info) { 1239 size_t argc = 2; 1240 napi_value args[2] = {nullptr}; 1241 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 1242 1243 // 获取第一个参数webTag 1244 size_t webTagSize = 0; 1245 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 1246 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 1247 size_t webTagLength = 0; 1248 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 1249 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk OH_NativeArkWeb_RunJavaScript webTag:%{public}s", 1250 webTagValue); 1251 1252 // 获取第二个参数 jsCode 1253 size_t bufferSize = 0; 1254 napi_get_value_string_utf8(env, args[1], nullptr, 0, &bufferSize); 1255 char *jsCode = new (std::nothrow) char[bufferSize + 1]; 1256 size_t byteLength = 0; 1257 napi_get_value_string_utf8(env, args[1], jsCode, bufferSize + 1, &byteLength); 1258 1259 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1260 "ndk OH_NativeArkWeb_RunJavaScript jsCode len:%{public}zu", strlen(jsCode)); 1261 1262 // 构造runJS执行的结构体 1263 ArkWeb_JavaScriptObject object = {(uint8_t *)jsCode, bufferSize, &JSBridgeObject::StaticRunJavaScriptCallback, 1264 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 1265 controller->runJavaScript(webTagValue, &object); 1266 delete[] webTagValue; 1267 delete[] jsCode; 1268 return nullptr; 1269 } 1270 1271 EXTERN_C_START 1272 static napi_value Init(napi_env env, napi_value exports) { 1273 napi_property_descriptor desc[] = { 1274 {"nativeWebInit", nullptr, NativeWebInit, nullptr, nullptr, nullptr, napi_default, nullptr}, 1275 {"runJavaScript", nullptr, RunJavaScript, nullptr, nullptr, nullptr, napi_default, nullptr}, 1276 }; 1277 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 1278 return exports; 1279 } 1280 EXTERN_C_END 1281 1282 static napi_module demoModule = { 1283 .nm_version = 1, 1284 .nm_flags = 0, 1285 .nm_filename = nullptr, 1286 .nm_register_func = Init, 1287 .nm_modname = "entry", 1288 .nm_priv = ((void *)0), 1289 .reserved = {0}, 1290 }; 1291 1292 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } 1293 ``` 1294 1295* Native侧业务代码 1296 1297 ```c++ 1298 // entry/src/main/cpp/jsbridge_object.h 1299 #include "web/arkweb_type.h" 1300 #include <string> 1301 1302 class JSBridgeObject : public std::enable_shared_from_this<JSBridgeObject> { 1303 public: 1304 JSBridgeObject(const char* webTag); 1305 ~JSBridgeObject() = default; 1306 void Init(); 1307 std::weak_ptr<JSBridgeObject>* GetWeakPtr(); 1308 static void StaticRunJavaScriptCallback(const char *webTag, const ArkWeb_JavaScriptBridgeData *data, void *userData); 1309 void RunJavaScriptCallback(const char *result); 1310 void ProxyMethod1(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize); 1311 void ProxyMethod2(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize); 1312 void SaySomething(const char* say); 1313 1314 private: 1315 std::string webTag_; 1316 std::weak_ptr<JSBridgeObject> weak_ptr_; 1317 }; 1318 ``` 1319 1320 ```c++ 1321 // entry/src/main/cpp/jsbridge_object.cpp 1322 #include "jsbridge_object.h" 1323 1324 #include "hilog/log.h" 1325 1326 constexpr unsigned int LOG_PRINT_DOMAIN = 0xFF00; 1327 1328 JSBridgeObject::JSBridgeObject(const char *webTag) : webTag_(webTag) {} 1329 1330 void JSBridgeObject::Init() { weak_ptr_ = shared_from_this(); } 1331 1332 std::weak_ptr<JSBridgeObject> *JSBridgeObject::GetWeakPtr() { return &weak_ptr_; } 1333 1334 void JSBridgeObject::StaticRunJavaScriptCallback(const char *webTag, const ArkWeb_JavaScriptBridgeData *data, 1335 void *userData) { 1336 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1337 "JSBridgeObject StaticRunJavaScriptCallback webTag:%{public}s", webTag); 1338 if (!userData) { 1339 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1340 "JSBridgeObject StaticRunJavaScriptCallback userData is nullptr"); 1341 return; 1342 } 1343 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1344 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1345 std::string result((char *)data->buffer, data->size); 1346 jsb_ptr->RunJavaScriptCallback(result.c_str()); 1347 } else { 1348 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1349 "JSBridgeObject StaticRunJavaScriptCallback jsb_weak_ptr lock failed"); 1350 } 1351 } 1352 1353 void JSBridgeObject::RunJavaScriptCallback(const char *result) { 1354 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1355 "JSBridgeObject OH_NativeArkWeb_RunJavaScript result:%{public}s", result); 1356 } 1357 1358 void JSBridgeObject::ProxyMethod1(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize) { 1359 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "JSBridgeObject ProxyMethod1 argc:%{public}d", 1360 arraySize); 1361 for (int i = 0; i < arraySize; i++) { 1362 std::string result((char *)dataArray[i].buffer, dataArray[i].size); 1363 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1364 "JSBridgeObject ProxyMethod1 argv[%{public}d]:%{public}s, size:%{public}d", i, result.c_str(), 1365 dataArray[i].size); 1366 } 1367 } 1368 1369 void JSBridgeObject::ProxyMethod2(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize) { 1370 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "JSBridgeObject ProxyMethod2 argc:%{public}d", 1371 arraySize); 1372 for (int i = 0; i < arraySize; i++) { 1373 std::string result((char *)dataArray[i].buffer, dataArray[i].size); 1374 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1375 "JSBridgeObject ProxyMethod2 argv[%{public}d]:%{public}s, size:%{public}d", i, result.c_str(), 1376 dataArray[i].size); 1377 } 1378 } 1379 1380 void JSBridgeObject::SaySomething(const char *say) { 1381 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "JSBridgeObject SaySomething argc:%{public}s", say); 1382 } 1383 ``` 1384