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