1# Mutual Invoking Between the Application and the Frontend Page (C/C++) 2 3This guide applies to the communication between ArkWeb applications and frontend pages. You can use the ArkWeb native APIs to conduct the service communication mechanism (native JSBridge for short) based on the application architecture. 4 5## Applicable Application Architecture 6 7If an application is developed using ArkTS and C++ language, or if its architecture is close to that of an applet and has a built-in C++ environment, you are advised to use [ArkWeb_ControllerAPI](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#arkweb_controllerapi) and [ArkWeb_ComponentAPI](../reference/apis-arkweb/_ark_web___component_a_p_i.md#arkweb_componentapi) provided by ArkWeb on the native side to implement the JSBridge capabilities. 8 9  10 11 The preceding figure shows a general architecture of applets with universal applicability. In this architecture, the logical layer depends on a JavaScript runtime built in an application, and the runtime runs in an existing C++ environment. The logic layer can communicate with the view layer (in which ArkWeb as the renderer) in the C++ environment through the native API, instead of using the ArkTS **JSBridge** API in the ArkTS environment. 12 13 The figure on the left shows that the application needs to invoke the ArkTS environment and then the C++ environment to build an applet using the ArkTS **JSBridge** API. Using the native **JSBridge** API is more efficient because the switching between the ArkTS and C++ environments is not required, as shown in the figure on the right. 14 15  16 17 The native JSBridge APIs are provided to avoid unnecessary switching to the ArkTS environment and allow callback to run in non-UI threads to avoid UI blocking. 18 19## Using Native APIs to Implement JSBridge Communication (Recommended) 20In the previous version, the return value of native synchronization APIs is fixed to void. With the continuous expansion of services, many service scenarios require APIs to provide return values to support synchronous calls. To meet this requirement, substitute APIs are introduced since API version 16. They support return values of the Boolean, string, and buffer types. 21 22In addition, the [permission](#permission) field is added for the synchronous API [registerJavaScriptProxyEx](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#registerjavascriptproxyex) and asynchronous API [registerAsyncJavaScriptProxyEx](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#registerasyncjavascriptproxyex) to control the calling permission. 23 24### Substitute APIs 25 26| Unrecommended API | Substitute API | Description | 27| :-----------------------------------: | :-----------------------------------: | :------------------------: | 28| ArkWeb_OnJavaScriptProxyCallback | ArkWeb_OnJavaScriptProxyCallbackWithResult | Defines a callback used when the proxy method is executed. | 29| ArkWeb_ProxyMethod | ArkWeb_ProxyMethodWithResult | Defines a proxy method. | 30| ArkWeb_ProxyObject | ArkWeb_ProxyObjectWithResult | Defines a proxy object. | 31| registerJavaScriptProxy | registerJavaScriptProxyEx | Registers a JavaScript object with the window. Synchronous APIs of this object can then be invoked in the window. | 32| registerAsyncJavaScriptProxy | registerAsyncJavaScriptProxyEx | Registers a JavaScript object with the window. Asynchronous APIs of this object can then be invoked in the window. | 33 34### Binding the Native API to ArkWeb 35 36* The **ArkWeb** component is declared on the ArkTS side. You need to define a **webTag** and transfer it to the native application side using Node-API. The **webTag** is used as a unique identifier of the corresponding component when an ArkWeb native API is used. 37 38* ArkTS side: 39 40 ```js 41 // Define a webTag and transfer it as an input parameter when WebviewController is created to establish the mapping between controller and webTag. 42 webTag: string = 'ArkWeb1'; 43 controller: web_webview.WebviewController = new web_webview.WebviewController(this.webTag); 44 45 // Use aboutToAppear() to pass webTag to C++ through Node-API. The webTag uniquely identifies the C++ ArkWeb component. 46 aboutToAppear() { 47 console.info("aboutToAppear") 48 // Initialize the web NDK. 49 testNapi.nativeWebInit(this.webTag); 50 } 51 ``` 52 53* C++ Side: 54 55 ```c++ 56 // Parse and store the webTag. 57 static napi_value NativeWebInit(napi_env env, napi_callback_info info) { 58 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit start"); 59 size_t argc = 1; 60 napi_value args[1] = {nullptr}; 61 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 62 // Obtain the first parameter webTag. 63 size_t webTagSize = 0; 64 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 65 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 66 size_t webTagLength = 0; 67 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 68 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit webTag:%{public}s", webTagValue); 69 70 // Save the webTag in the instance object. 71 jsbridge_object_ptr = std::make_shared<JSBridgeObject>(webTagValue); 72 // ... 73 ``` 74 75### Obtaining API Struct Using the Native API 76 77To invoke the native APIs, obtain the API structs on the ArkWeb native side first. You can use [OH_ArkWeb_GetNativeAPI](../reference/apis-arkweb/_web.md#oh_arkweb_getnativeapi()) to obtain the native ArkWeb API, and use [ArkWeb_ControllerAPI](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#arkweb_controllerapi) and [ArkWeb_ComponentAPI](../reference/apis-arkweb/_ark_web___component_a_p_i.md#arkweb_componentapi) to obtain function pointer structs based on the input parameter type. The [ArkWeb_ControllerAPI](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#arkweb_controllerapi) corresponds to the [web_webview.WebviewController API](../reference/apis-arkweb/js-apis-webview.md) on ArkTS, and the [ArkWeb_ComponentAPI](../reference/apis-arkweb/_ark_web___component_a_p_i.md#arkweb_componentapi) corresponds to the [ArkWeb component API](../reference/apis-arkweb/ts-basic-components-web.md) on ArkTS. 78 79 ```c++ 80 static ArkWeb_ControllerAPI *controller = nullptr; 81 static ArkWeb_ComponentAPI *component = nullptr; 82 // ... 83 controller = reinterpret_cast<ArkWeb_ControllerAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_CONTROLLER)); 84 component = reinterpret_cast<ArkWeb_ComponentAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_COMPONENT)); 85 ``` 86 87### Registering Component Lifecycle Callback on the Native Side 88 89Use [ArkWeb_ComponentAPI](../reference/apis-arkweb/_ark_web___component_a_p_i.md#arkweb_componentapi) to register the component lifecycle callback. To avoid crash caused by mismatch between SDK and device ROM, you are advised to use [ARKWEB_MEMBER_MISSING](../reference/apis-arkweb/_web.md#arkweb_member_missing) to check whether there is a pointer to the function struct before calling an API. 90 91 ```c++ 92 if (!ARKWEB_MEMBER_MISSING(component, onControllerAttached)) { 93 component->onControllerAttached(webTagValue, ValidCallback, 94 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 95 } else { 96 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onControllerAttached func not exist"); 97 } 98 99 if (!ARKWEB_MEMBER_MISSING(component, onPageBegin)) { 100 component->onPageBegin(webTagValue, LoadStartCallback, 101 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 102 } else { 103 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageBegin func not exist"); 104 } 105 106 if (!ARKWEB_MEMBER_MISSING(component, onPageEnd)) { 107 component->onPageEnd(webTagValue, LoadEndCallback, 108 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 109 } else { 110 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageEnd func not exist"); 111 } 112 113 if (!ARKWEB_MEMBER_MISSING(component, onDestroy)) { 114 component->onDestroy(webTagValue, DestroyCallback, 115 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 116 } else { 117 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onDestroy func not exist"); 118 } 119 ``` 120 121### Invoking Application Functions on the Frontend Page 122 123Use [registerJavaScriptProxyEx](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#registerjavascriptproxyex) to register the application function in the frontend page. You are advised to register the function in [onControllerAttached](../reference/apis-arkweb/_ark_web___component_a_p_i.md#oncontrollerattached). In other cases, you need to call [refresh](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#refresh) for the registration. 124 125 ```c++ 126 // Register an object. 127 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk registerJavaScriptProxyEx begin"); 128 ArkWeb_ProxyMethodWithResult method1 = {"method1", ProxyMethod1, static_cast<void *>(jsbridge_object_ptr->GetWeakPt ())}; 129 ArkWeb_ProxyMethodWithResult method2 = {"method2", ProxyMethod2, static_cast<void *>(jsbridge_object_ptr->GetWeakPt ())}; 130 ArkWeb_ProxyMethodWithResult methodList[2] = {method1, method2}; 131 // Call the NDK API to register an object. 132 // In this case, you can use proxy.method1 and proxy.method2 to call ProxyMethod1 and ProxyMethod2 in this file on HTML5 pages. 133 ArkWeb_ProxyObjectWithResult proxyObject = {"ndkProxy", methodList, 2}; 134 // If the permission parameter is empty, permission control is not performed. 135 controller->registerJavaScriptProxyEx(webTag, &proxyObject, /*permission*/""); 136 ``` 137 <a id="permission"></a> 138 - The **permission** parameter is a JSON string as follows: 139 ```json 140 { 141 "javascriptProxyPermission": { 142 "urlPermissionList": [ // Object-level permission. If it is granted, all methods are available. 143 { 144 "scheme": "resource", // Exact match. The value cannot be empty. 145 "host": "rawfile", // Exact match. The value cannot be empty. 146 "port": "", // Exact match. If the value is empty, it is not checked. 147 "path": "" // Prefix match. If the value is empty, it is not checked. 148 }, 149 { 150 "scheme": "https", // Exact match. The value cannot be empty. 151 "host": "xxx.com", // Exact match. The value cannot be empty. 152 "port": "8080", // Exact match. If the value is empty, it is not checked. 153 "path": "a/b/c" // Prefix match. If the value is empty, it is not checked. 154 } 155 ], 156 "methodList": [ 157 { 158 "methodName": "test", 159 "urlPermissionList": [ // Method-level permission. 160 { 161 "scheme": "https", // Exact match. The value cannot be empty. 162 "host": "xxx.com", // Exact match. The value cannot be empty. 163 "port": "", // Exact match. If the value is empty, it is not checked. 164 "path": "" // Prefix match. If the value is empty, it is not checked. 165 }, 166 { 167 "scheme": "resource",// Exact match. The value cannot be empty. 168 "host": "rawfile", // Exact match. The value cannot be empty. 169 "port": "", // Exact match. If the value is empty, it is not checked. 170 "path": "" // Prefix match. If the value is empty, it is not checked. 171 } 172 ] 173 }, 174 { 175 "methodName": "test11", 176 "urlPermissionList": [ // Method-level permission. 177 { 178 "scheme": "q", // Exact match. The value cannot be empty. 179 "host": "r", // Exact match. The value cannot be empty. 180 "port": "", // Exact match. If the value is empty, it is not checked. 181 "path": "t" // Prefix match. If the value is empty, it is not checked. 182 }, 183 { 184 "scheme": "u", // Exact match. The value cannot be empty. 185 "host": "v", // Exact match. The value cannot be empty. 186 "port": "", // Exact match. If the value is empty, it is not checked. 187 "path": "" // Prefix match. If the value is empty, it is not checked. 188 } 189 ] 190 } 191 ] 192 } 193 } 194 ``` 195 196### Invoking Frontend Page Functions on the Application 197 198Use [runJavaScript](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#runjavascript) to invoke frontend page functions. 199 200 ```c++ 201 // Construct a struct executed in runJS. 202 char* jsCode = "runJSRetStr()"; 203 ArkWeb_JavaScriptObject object = {(uint8_t *)jsCode, bufferSize, &JSBridgeObject::StaticRunJavaScriptCallback, 204 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 205 // Call runJSRetStr() of the frontend page. 206 controller->runJavaScript(webTagValue, &object); 207 ``` 208 209### Sample Code 210 211* Frontend page code: 212 213 ```html 214 <!-- entry/src/main/resources/rawfile/runJS.html --> 215 <!-- runJS.html --> 216 <!DOCTYPE html> 217 <html lang="en-gb"> 218 <head> 219 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 220 <title>run javascript demo</title> 221 </head> 222 <body> 223 <h1>run JavaScript Ext demo</h1> 224 <p id="webDemo"></p> 225 <br> 226 <button type="button" style="height:30px;width:200px" onclick="testNdkProxyObjMethod1()">test ndk method1 ! </button> 227 <br> 228 <br> 229 <button type="button" style="height:30px;width:200px" onclick="testNdkProxyObjMethod2()">test ndk method2 ! </button> 230 <br> 231 232 </body> 233 <script type="text/javascript"> 234 235 function testNdkProxyObjMethod1() { 236 if (window.ndkProxy == undefined) { 237 document.getElementById("webDemo").innerHTML = "ndkProxy undefined" 238 return "objName undefined" 239 } 240 241 if (window.ndkProxy.method1 == undefined) { 242 document.getElementById("webDemo").innerHTML = "ndkProxy method1 undefined" 243 return "objName test undefined" 244 } 245 246 if (window.ndkProxy.method2 == undefined) { 247 document.getElementById("webDemo").innerHTML = "ndkProxy method2 undefined" 248 return "objName test undefined" 249 } 250 let retStr = window.ndkProxy.method1("hello", "world", [1.2, -3.4, 123.456], ["Saab", "Volvo", "BMW", undefined], 1.23456, 123789, true, false, 0, undefined); 251 console.log("ndkProxy and method1 is ok, " + retStr + ", type:" + typeof(retStr)); 252 } 253 254 function testNdkProxyObjMethod2() { 255 if (window.ndkProxy == undefined) { 256 document.getElementById("webDemo").innerHTML = "ndkProxy undefined" 257 return "objName undefined" 258 } 259 260 if (window.ndkProxy.method1 == undefined) { 261 document.getElementById("webDemo").innerHTML = "ndkProxy method1 undefined" 262 return "objName test undefined" 263 } 264 265 if (window.ndkProxy.method2 == undefined) { 266 document.getElementById("webDemo").innerHTML = "ndkProxy method2 undefined" 267 return "objName test undefined" 268 } 269 270 var student = { 271 name:"zhang", 272 sex:"man", 273 age:25 274 }; 275 var cars = [student, 456, false, 4.567]; 276 let params = "[\"{\\\"scope\\\"]"; 277 278 let retStr = window.ndkProxy.method2("hello", "world", false, cars, params); 279 console.log("ndkProxy and method2 is ok, " + retStr + ", type:" + typeof(retStr)); 280 } 281 282 function runJSRetStr(data) { 283 const d = new Date(); 284 let time = d.getTime(); 285 return JSON.stringify(time) 286 } 287 </script> 288 </html> 289 ``` 290 291* Code in ArkTS: 292 293 ```javascript 294 // entry/src/main/ets/pages/Index.ets 295 import testNapi from 'libentry.so'; 296 import { webview } from '@kit.ArkWeb'; 297 298 class testObj { 299 constructor() { 300 } 301 302 test(): string { 303 console.log('ArkUI Web Component'); 304 return "ArkUI Web Component"; 305 } 306 307 toString(): void { 308 console.log('Web Component toString'); 309 } 310 } 311 312 @Entry 313 @Component 314 struct Index { 315 webTag: string = 'ArkWeb1'; 316 controller: webview.WebviewController = new webview.WebviewController(this.webTag); 317 @State testObjtest: testObj = new testObj(); 318 319 aboutToAppear() { 320 console.info("aboutToAppear") 321 // Initialize the web NDK. 322 testNapi.nativeWebInit(this.webTag); 323 } 324 325 build() { 326 Column() { 327 Row() { 328 Button('runJS hello') 329 .fontSize(12) 330 .onClick(() => { 331 testNapi.runJavaScript(this.webTag, "runJSRetStr(\"" + "hello" + "\")"); 332 }) 333 }.height('20%') 334 335 Row() { 336 Web({ src: $rawfile('runJS.html'), controller: this.controller }) 337 .javaScriptAccess(true) 338 .fileAccess(true) 339 .onControllerAttached(() => { 340 console.error("ndk onControllerAttached webId: " + this.controller.getWebId()); 341 }) 342 }.height('80%') 343 } 344 } 345 } 346 ``` 347 348* ArkTS APIs exposed on the Node-API side: 349 350 ```javascript 351 // entry/src/main/cpp/types/libentry/index.d.ts 352 export const nativeWebInit: (webName: string) => void; 353 export const runJavaScript: (webName: string, jsCode: string) => void; 354 ``` 355 356* Compilation configuration on the Node-API side in **entry/src/main/cpp/CMakeLists.txt**. 357 358 ```c++ 359 # the minimum version of CMake. 360 cmake_minimum_required(VERSION 3.4.1) 361 project(NDKJSBridg) 362 363 set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 364 365 if(DEFINED PACKAGE_FIND_FILE) 366 include(${PACKAGE_FIND_FILE}) 367 endif() 368 369 include_directories(${NATIVERENDER_ROOT_PATH} 370 ${NATIVERENDER_ROOT_PATH}/include) 371 372 add_library(entry SHARED hello.cpp jsbridge_object.cpp) 373 374 find_library( 375 # Sets the name of the path variable. 376 hilog-lib 377 # Specifies the name of the NDK library that 378 # you want CMake to locate. 379 hilog_ndk.z 380 ) 381 382 target_link_libraries(entry PUBLIC libace_napi.z.so ${hilog-lib} libohweb.so) 383 ``` 384 385* Node-API layer code: 386 387 ```c++ 388 // entry/src/main/cpp/hello.cpp 389 #include "napi/native_api.h" 390 #include <bits/alltypes.h> 391 #include <memory> 392 #include <string> 393 #include <sys/types.h> 394 #include <thread> 395 396 #include "hilog/log.h" 397 #include "web/arkweb_interface.h" 398 #include "jsbridge_object.h" 399 400 constexpr unsigned int LOG_PRINT_DOMAIN = 0xFF00; 401 std::shared_ptr<JSBridgeObject> jsbridge_object_ptr = nullptr; 402 static ArkWeb_ControllerAPI *controller = nullptr; 403 static ArkWeb_ComponentAPI *component = nullptr; 404 ArkWeb_JavaScriptValueAPI *javaScriptValueApi = nullptr; 405 406 // Send the JS script to the HTML5 side for execution. This method is a callback of the execution result. 407 static void RunJavaScriptCallback(const char *webTag, const char *result, void *userData) { 408 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RunJavaScriptCallback webTag:%{public}s", webTag); 409 if (!userData) { 410 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RunJavaScriptCallback userData is nullptr"); 411 return; 412 } 413 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 414 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 415 jsb_ptr->RunJavaScriptCallback(result); 416 } else { 417 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 418 "ndk RunJavaScriptCallback jsb_weak_ptr lock failed"); 419 } 420 } 421 422 // This example registers one object and two methods. 423 static ArkWeb_JavaScriptValuePtr ProxyMethod1(const char *webTag, const ArkWeb_JavaScriptBridgeData *dataArray, size_t arraySize, void *userData) { 424 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 webTag:%{public}s", webTag); 425 if (!userData) { 426 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 userData is nullptr"); 427 return nullptr; 428 } 429 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 430 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 431 jsb_ptr->ProxyMethod1(dataArray, arraySize); 432 } else { 433 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 jsb_weak_ptr lock failed"); 434 } 435 436 bool boolValue = true; 437 return javaScriptValueApi->createJavaScriptValue(ArkWeb_JavaScriptValueType::ARKWEB_JAVASCRIPT_BOOL, (void*)(&boolValue), 1); 438 } 439 440 static ArkWeb_JavaScriptValuePtr ProxyMethod2(const char *webTag, const ArkWeb_JavaScriptBridgeData *dataArray, size_t arraySize, void *userData) { 441 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 webTag:%{public}s", webTag); 442 if (!userData) { 443 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 userData is nullptr"); 444 return nullptr; 445 } 446 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 447 448 std::string jsCode = "runJSRetStr()"; 449 ArkWeb_JavaScriptObject object = {(uint8_t *)jsCode.c_str(), jsCode.size(), 450 &JSBridgeObject::StaticRunJavaScriptCallback, 451 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 452 controller->runJavaScript(webTag, &object); 453 454 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 455 jsb_ptr->ProxyMethod2(dataArray, arraySize); 456 } else { 457 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 jsb_weak_ptr lock failed"); 458 } 459 460 std::string str = "this is a string"; 461 return javaScriptValueApi->createJavaScriptValue(ArkWeb_JavaScriptValueType::ARKWEB_JAVASCRIPT_STRING, (void*)str.c_str(), str.length() + 1); 462 } 463 464 void ValidCallback(const char *webTag, void *userData) { 465 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback webTag: %{public}s", webTag); 466 if (!userData) { 467 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback userData is nullptr"); 468 return; 469 } 470 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 471 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 472 jsb_ptr->SaySomething("ValidCallback"); 473 } else { 474 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback jsb_weak_ptr lock failed"); 475 } 476 477 // Register an object. 478 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk registerJavaScriptProxyEx begin"); 479 ArkWeb_ProxyMethodWithResult method1 = {"method1", ProxyMethod1, static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 480 ArkWeb_ProxyMethodWithResult method2 = {"method2", ProxyMethod2, static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 481 ArkWeb_ProxyMethodWithResult methodList[2] = {method1, method2}; 482 // Call the NDK API to register an object. 483 // In this case, you can use proxy.method1 and proxy.method2 to call ProxyMethod1 and ProxyMethod2 in this file on HTML5 pages. 484 ArkWeb_ProxyObjectWithResult proxyObject = {"ndkProxy", methodList, 2}; 485 controller->registerJavaScriptProxyEx(webTag, &proxyObject, ""); 486 487 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk registerJavaScriptProxyEx end"); 488 } 489 490 void LoadStartCallback(const char *webTag, void *userData) { 491 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadStartCallback webTag: %{public}s", webTag); 492 if (!userData) { 493 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadStartCallback userData is nullptr"); 494 return; 495 } 496 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 497 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 498 jsb_ptr->SaySomething("LoadStartCallback"); 499 } else { 500 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadStartCallback jsb_weak_ptr lock failed"); 501 } 502 } 503 504 void LoadEndCallback(const char *webTag, void *userData) { 505 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadEndCallback webTag: %{public}s", webTag); 506 if (!userData) { 507 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadEndCallback userData is nullptr"); 508 return; 509 } 510 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 511 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 512 jsb_ptr->SaySomething("LoadEndCallback"); 513 } else { 514 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadEndCallback jsb_weak_ptr lock failed"); 515 } 516 } 517 518 void DestroyCallback(const char *webTag, void *userData) { 519 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestoryCallback webTag: %{public}s", webTag); 520 if (!userData) { 521 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestroyCallback userData is nullptr"); 522 return; 523 } 524 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 525 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 526 jsb_ptr->SaySomething("DestroyCallback"); 527 } else { 528 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestroyCallback jsb_weak_ptr lock failed"); 529 } 530 } 531 532 void SetComponentCallback(ArkWeb_ComponentAPI * component, const char* webTagValue) { 533 if (!ARKWEB_MEMBER_MISSING(component, onControllerAttached)) { 534 component->onControllerAttached(webTagValue, ValidCallback, 535 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 536 } else { 537 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onControllerAttached func not exist"); 538 } 539 540 if (!ARKWEB_MEMBER_MISSING(component, onPageBegin)) { 541 component->onPageBegin(webTagValue, LoadStartCallback, 542 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 543 } else { 544 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageBegin func not exist"); 545 } 546 547 if (!ARKWEB_MEMBER_MISSING(component, onPageEnd)) { 548 component->onPageEnd(webTagValue, LoadEndCallback, 549 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 550 } else { 551 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageEnd func not exist"); 552 } 553 554 if (!ARKWEB_MEMBER_MISSING(component, onDestroy)) { 555 component->onDestroy(webTagValue, DestroyCallback, 556 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 557 } else { 558 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onDestroy func not exist"); 559 } 560 } 561 562 // Parse and store the webTag. 563 static napi_value NativeWebInit(napi_env env, napi_callback_info info) { 564 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit start"); 565 size_t argc = 1; 566 napi_value args[1] = {nullptr}; 567 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 568 // Obtain the first parameter webTag. 569 size_t webTagSize = 0; 570 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 571 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 572 size_t webTagLength = 0; 573 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 574 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit webTag:%{public}s", webTagValue); 575 576 jsbridge_object_ptr = std::make_shared<JSBridgeObject>(webTagValue); 577 if (jsbridge_object_ptr) 578 jsbridge_object_ptr->Init(); 579 580 controller = reinterpret_cast<ArkWeb_ControllerAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_CONTROLLER)); 581 if (controller) 582 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "get ArkWeb_ControllerAPI success"); 583 584 component = reinterpret_cast<ArkWeb_ComponentAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_COMPONENT)); 585 if (component) 586 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "get ArkWeb_ComponentAPI success"); 587 588 javaScriptValueApi = 589 reinterpret_cast<ArkWeb_JavaScriptValueAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_JAVASCRIPT_VALUE)); 590 if (javaScriptValueApi) 591 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "get ArkWeb_JavaScriptValueAPI success"); 592 else 593 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "get ArkWeb_JavaScriptValueAPI failed"); 594 595 SetComponentCallback(component, webTagValue); 596 597 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit end"); 598 599 return nullptr; 600 } 601 602 // Send the JS script to the HTML5 side for execution. 603 static napi_value RunJavaScript(napi_env env, napi_callback_info info) { 604 size_t argc = 2; 605 napi_value args[2] = {nullptr}; 606 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 607 608 // Obtain the first parameter webTag. 609 size_t webTagSize = 0; 610 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 611 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 612 size_t webTagLength = 0; 613 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 614 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk OH_NativeArkWeb_RunJavaScript webTag:%{public}s", 615 webTagValue); 616 617 // Obtain the second parameter jsCode. 618 size_t bufferSize = 0; 619 napi_get_value_string_utf8(env, args[1], nullptr, 0, &bufferSize); 620 char *jsCode = new (std::nothrow) char[bufferSize + 1]; 621 size_t byteLength = 0; 622 napi_get_value_string_utf8(env, args[1], jsCode, bufferSize + 1, &byteLength); 623 624 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 625 "ndk OH_NativeArkWeb_RunJavaScript jsCode len:%{public}zu", strlen(jsCode)); 626 627 // Construct a struct executed in runJS. 628 ArkWeb_JavaScriptObject object = {(uint8_t *)jsCode, bufferSize, &JSBridgeObject::StaticRunJavaScriptCallback, 629 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 630 controller->runJavaScript(webTagValue, &object); 631 return nullptr; 632 } 633 634 EXTERN_C_START 635 static napi_value Init(napi_env env, napi_value exports) { 636 napi_property_descriptor desc[] = { 637 {"nativeWebInit", nullptr, NativeWebInit, nullptr, nullptr, nullptr, napi_default, nullptr}, 638 {"runJavaScript", nullptr, RunJavaScript, nullptr, nullptr, nullptr, napi_default, nullptr}, 639 }; 640 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 641 return exports; 642 } 643 EXTERN_C_END 644 645 static napi_module demoModule = { 646 .nm_version = 1, 647 .nm_flags = 0, 648 .nm_filename = nullptr, 649 .nm_register_func = Init, 650 .nm_modname = "entry", 651 .nm_priv = ((void *)0), 652 .reserved = {0}, 653 }; 654 655 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } 656 ``` 657 658* Native service code: 659 660 ```c++ 661 // entry/src/main/cpp/jsbridge_object.h 662 #include "web/arkweb_type.h" 663 #include <string> 664 665 class JSBridgeObject : public std::enable_shared_from_this<JSBridgeObject> { 666 public: 667 JSBridgeObject(const char* webTag); 668 ~JSBridgeObject() = default; 669 void Init(); 670 std::weak_ptr<JSBridgeObject>* GetWeakPtr(); 671 static void StaticRunJavaScriptCallback(const char *webTag, const ArkWeb_JavaScriptBridgeData *data, void *userData); 672 void RunJavaScriptCallback(const char *result); 673 void ProxyMethod1(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize); 674 void ProxyMethod2(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize); 675 void SaySomething(const char* say); 676 677 private: 678 std::string webTag_; 679 std::weak_ptr<JSBridgeObject> weak_ptr_; 680 }; 681 ``` 682 683 ```c++ 684 // entry/src/main/cpp/jsbridge_object.cpp 685 #include "jsbridge_object.h" 686 687 #include "hilog/log.h" 688 689 constexpr unsigned int LOG_PRINT_DOMAIN = 0xFF00; 690 691 JSBridgeObject::JSBridgeObject(const char *webTag) : webTag_(webTag) {} 692 693 void JSBridgeObject::Init() { weak_ptr_ = shared_from_this(); } 694 695 std::weak_ptr<JSBridgeObject> *JSBridgeObject::GetWeakPtr() { return &weak_ptr_; } 696 697 void JSBridgeObject::StaticRunJavaScriptCallback(const char *webTag, const ArkWeb_JavaScriptBridgeData *data, 698 void *userData) { 699 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 700 "JSBridgeObject StaticRunJavaScriptCallback webTag:%{public}s", webTag); 701 if (!userData) { 702 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 703 "JSBridgeObject StaticRunJavaScriptCallback userData is nullptr"); 704 return; 705 } 706 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 707 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 708 std::string result((char *)data->buffer, data->size); 709 jsb_ptr->RunJavaScriptCallback(result.c_str()); 710 } else { 711 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 712 "JSBridgeObject StaticRunJavaScriptCallback jsb_weak_ptr lock failed"); 713 } 714 } 715 716 void JSBridgeObject::RunJavaScriptCallback(const char *result) { 717 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 718 "JSBridgeObject OH_NativeArkWeb_RunJavaScript result:%{public}s", result); 719 } 720 721 void JSBridgeObject::ProxyMethod1(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize) { 722 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "JSBridgeObject ProxyMethod1 argc:%{public}d", 723 arraySize); 724 for (int i = 0; i < arraySize; i++) { 725 std::string result((char *)dataArray[i].buffer, dataArray[i].size); 726 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 727 "JSBridgeObject ProxyMethod1 argv[%{public}d]:%{public}s, size:%{public}d", i, result.c_str(), 728 dataArray[i].size); 729 } 730 } 731 732 void JSBridgeObject::ProxyMethod2(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize) { 733 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "JSBridgeObject ProxyMethod2 argc:%{public}d", 734 arraySize); 735 for (int i = 0; i < arraySize; i++) { 736 std::string result((char *)dataArray[i].buffer, dataArray[i].size); 737 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 738 "JSBridgeObject ProxyMethod2 argv[%{public}d]:%{public}s, size:%{public}d", i, result.c_str(), 739 dataArray[i].size); 740 } 741 } 742 743 void JSBridgeObject::SaySomething(const char *say) { 744 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "JSBridgeObject SaySomething argc:%{public}s", say); 745 } 746 ``` 747 748## Using the Native API to Implement JSBridge 749 750### Binding the Native API to ArkWeb 751 752* The **ArkWeb** component is declared on the ArkTS side. You need to define a **webTag** and transfer it to the native application side using Node-API. The **webTag** is used as a unique identifier of the corresponding component when an ArkWeb native API is used. 753 754* ArkTS side: 755 756 ```js 757 // Define a webTag and transfer it as an input parameter when WebviewController is created to establish the mapping between controller and webTag. 758 webTag: string = 'ArkWeb1'; 759 controller: web_webview.WebviewController = new web_webview.WebviewController(this.webTag); 760 // ... 761 // Use aboutToAppear() to pass webTag to C++ through Node-API. The webTag uniquely identifies the C++ ArkWeb component. 762 aboutToAppear() { 763 console.info("aboutToAppear") 764 // Initialize the web NDK. 765 testNapi.nativeWebInit(this.webTag); 766 } 767 // ... 768 ``` 769 770* C++ Side: 771 772 ```c++ 773 // Parse and store the webTag. 774 static napi_value NativeWebInit(napi_env env, napi_callback_info info) { 775 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit start"); 776 size_t argc = 1; 777 napi_value args[1] = {nullptr}; 778 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 779 // Obtain the first parameter webTag. 780 size_t webTagSize = 0; 781 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 782 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 783 size_t webTagLength = 0; 784 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 785 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit webTag:%{public}s", webTagValue); 786 787 // Save the webTag in the instance object. 788 jsbridge_object_ptr = std::make_shared<JSBridgeObject>(webTagValue); 789 // ... 790 ``` 791 792### Obtaining API Struct Using the Native API 793 794To invoke the native APIs, obtain the API structs on the ArkWeb native side first. You can use [OH_ArkWeb_GetNativeAPI](../reference/apis-arkweb/_web.md#oh_arkweb_getnativeapi()) to obtain the native ArkWeb API, and use [ArkWeb_ControllerAPI](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#arkweb_controllerapi) and [ArkWeb_ComponentAPI](../reference/apis-arkweb/_ark_web___component_a_p_i.md#arkweb_componentapi) to obtain function pointer structs based on the input parameter type. The [ArkWeb_ControllerAPI](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#arkweb_controllerapi) corresponds to the [web_webview.WebviewController API](../reference/apis-arkweb/js-apis-webview.md) on ArkTS, and the [ArkWeb_ComponentAPI](../reference/apis-arkweb/_ark_web___component_a_p_i.md#arkweb_componentapi) corresponds to the [ArkWeb component API](../reference/apis-arkweb/ts-basic-components-web.md) on ArkTS. 795 796 ```c++ 797 static ArkWeb_ControllerAPI *controller = nullptr; 798 static ArkWeb_ComponentAPI *component = nullptr; 799 // ... 800 controller = reinterpret_cast<ArkWeb_ControllerAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_CONTROLLER)); 801 component = reinterpret_cast<ArkWeb_ComponentAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_COMPONENT)); 802 ``` 803 804### Registering Component Lifecycle Callback on the Native Side 805 806Use [ArkWeb_ComponentAPI](../reference/apis-arkweb/_ark_web___component_a_p_i.md#arkweb_componentapi) to register the component lifecycle callback. To avoid crash caused by mismatch between SDK and device ROM, you are advised to use [ARKWEB_MEMBER_MISSING](../reference/apis-arkweb/_web.md#arkweb_member_missing) to check whether there is a pointer to the function struct before calling an API. 807 808 ```c++ 809 if (!ARKWEB_MEMBER_MISSING(component, onControllerAttached)) { 810 component->onControllerAttached(webTagValue, ValidCallback, 811 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 812 } else { 813 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onControllerAttached func not exist"); 814 } 815 816 if (!ARKWEB_MEMBER_MISSING(component, onPageBegin)) { 817 component->onPageBegin(webTagValue, LoadStartCallback, 818 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 819 } else { 820 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageBegin func not exist"); 821 } 822 823 if (!ARKWEB_MEMBER_MISSING(component, onPageEnd)) { 824 component->onPageEnd(webTagValue, LoadEndCallback, 825 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 826 } else { 827 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageEnd func not exist"); 828 } 829 830 if (!ARKWEB_MEMBER_MISSING(component, onDestroy)) { 831 component->onDestroy(webTagValue, DestroyCallback, 832 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 833 } else { 834 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onDestroy func not exist"); 835 } 836 ``` 837 838### Invoking Application Functions on the Frontend Page 839 840Use [registerJavaScriptProxy](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#registerjavascriptproxy) to register the application function in the frontend page. You are advised to register the function in [onControllerAttached](../reference/apis-arkweb/_ark_web___component_a_p_i.md#oncontrollerattached). In other cases, you need to call [refresh](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#refresh) for the registration. 841 842 ```c++ 843 // Register an object. 844 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RegisterJavaScriptProxy begin"); 845 ArkWeb_ProxyMethod method1 = {"method1", ProxyMethod1, static_cast<void *>(jsbridge_object_ptr->GetWeakPt ())}; 846 ArkWeb_ProxyMethod method2 = {"method2", ProxyMethod2, static_cast<void *>(jsbridge_object_ptr->GetWeakPt ())}; 847 ArkWeb_ProxyMethod methodList[2] = {method1, method2}; 848 // Call the NDK API to register an object. 849 // In this case, you can use proxy.method1 and proxy.method2 to call ProxyMethod1 and ProxyMethod2 in this file on HTML5 pages. 850 ArkWeb_ProxyObject proxyObject = {"ndkProxy", methodList, 2}; 851 controller->registerJavaScriptProxy(webTag, &proxyObject); 852 ``` 853 854### Invoking Frontend Page Functions on the Application 855 856Use [runJavaScript](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#runjavascript) to invoke frontend page functions. 857 858 ```c++ 859 // Construct a struct executed in runJS. 860 char* jsCode = "runJSRetStr()"; 861 ArkWeb_JavaScriptObject object = {(uint8_t *)jsCode, bufferSize, &JSBridgeObject::StaticRunJavaScriptCallback, 862 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 863 // Call runJSRetStr() of the frontend page. 864 controller->runJavaScript(webTagValue, &object); 865 ``` 866 867### Sample Code 868 869* Frontend page code: 870 871 ```html 872 <!-- entry/src/main/resources/rawfile/runJS.html --> 873 <!-- runJS.html --> 874 <!DOCTYPE html> 875 <html lang="en-gb"> 876 <head> 877 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 878 <title>run javascript demo</title> 879 </head> 880 <body> 881 <h1>run JavaScript Ext demo</h1> 882 <p id="webDemo"></p> 883 <br> 884 <button type="button" style="height:30px;width:200px" onclick="testNdkProxyObjMethod1()">test ndk method1 ! </button> 885 <br> 886 <br> 887 <button type="button" style="height:30px;width:200px" onclick="testNdkProxyObjMethod2()">test ndk method2 ! </button> 888 <br> 889 890 </body> 891 <script type="text/javascript"> 892 893 function testNdkProxyObjMethod1() { 894 if (window.ndkProxy == undefined) { 895 document.getElementById("webDemo").innerHTML = "ndkProxy undefined" 896 return "objName undefined" 897 } 898 899 if (window.ndkProxy.method1 == undefined) { 900 document.getElementById("webDemo").innerHTML = "ndkProxy method1 undefined" 901 return "objName test undefined" 902 } 903 904 if (window.ndkProxy.method2 == undefined) { 905 document.getElementById("webDemo").innerHTML = "ndkProxy method2 undefined" 906 return "objName test undefined" 907 } 908 window.ndkProxy.method1("hello", "world", [1.2, -3.4, 123.456], ["Saab", "Volvo", "BMW", undefined], 1.23456, 123789, true, false, 0, undefined); 909 } 910 911 function testNdkProxyObjMethod2() { 912 if (window.ndkProxy == undefined) { 913 document.getElementById("webDemo").innerHTML = "ndkProxy undefined" 914 return "objName undefined" 915 } 916 917 if (window.ndkProxy.method1 == undefined) { 918 document.getElementById("webDemo").innerHTML = "ndkProxy method1 undefined" 919 return "objName test undefined" 920 } 921 922 if (window.ndkProxy.method2 == undefined) { 923 document.getElementById("webDemo").innerHTML = "ndkProxy method2 undefined" 924 return "objName test undefined" 925 } 926 927 var student = { 928 name:"zhang", 929 sex:"man", 930 age:25 931 }; 932 var cars = [student, 456, false, 4.567]; 933 let params = "[\"{\\\"scope\\\"]"; 934 935 window.ndkProxy.method2("hello", "world", false, cars, params); 936 } 937 938 function runJSRetStr(data) { 939 const d = new Date(); 940 let time = d.getTime(); 941 return JSON.stringify(time) 942 } 943 </script> 944 </html> 945 ``` 946 947* Code in ArkTS: 948 949 ```javascript 950 // entry/src/main/ets/pages/Index.ets 951 import testNapi from 'libentry.so'; 952 import { webview } from '@kit.ArkWeb'; 953 954 class testObj { 955 constructor() { 956 } 957 958 test(): string { 959 console.log('ArkUI Web Component'); 960 return "ArkUI Web Component"; 961 } 962 963 toString(): void { 964 console.log('Web Component toString'); 965 } 966 } 967 968 @Entry 969 @Component 970 struct Index { 971 webTag: string = 'ArkWeb1'; 972 controller: webview.WebviewController = new webview.WebviewController(this.webTag); 973 @State testObjtest: testObj = new testObj(); 974 975 aboutToAppear() { 976 console.info("aboutToAppear") 977 // Initialize the web NDK. 978 testNapi.nativeWebInit(this.webTag); 979 } 980 981 build() { 982 Column() { 983 Row() { 984 Button('runJS hello') 985 .fontSize(12) 986 .onClick(() => { 987 testNapi.runJavaScript(this.webTag, "runJSRetStr(\"" + "hello" + "\")"); 988 }) 989 }.height('20%') 990 991 Row() { 992 Web({ src: $rawfile('runJS.html'), controller: this.controller }) 993 .javaScriptAccess(true) 994 .fileAccess(true) 995 .onControllerAttached(() => { 996 console.error("ndk onControllerAttached webId: " + this.controller.getWebId()); 997 }) 998 }.height('80%') 999 } 1000 } 1001 } 1002 ``` 1003 1004* ArkTS APIs exposed on the Node-API side: 1005 1006 ```javascript 1007 // entry/src/main/cpp/types/libentry/index.d.ts 1008 export const nativeWebInit: (webName: string) => void; 1009 export const runJavaScript: (webName: string, jsCode: string) => void; 1010 ``` 1011 1012* Compilation configuration on the Node-API side in **entry/src/main/cpp/CMakeLists.txt**. 1013 1014 ```c++ 1015 # the minimum version of CMake. 1016 cmake_minimum_required(VERSION 3.4.1) 1017 project(NDKJSBridg) 1018 1019 set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 1020 1021 if(DEFINED PACKAGE_FIND_FILE) 1022 include(${PACKAGE_FIND_FILE}) 1023 endif() 1024 1025 include_directories(${NATIVERENDER_ROOT_PATH} 1026 ${NATIVERENDER_ROOT_PATH}/include) 1027 1028 add_library(entry SHARED hello.cpp jsbridge_object.cpp) 1029 1030 find_library( 1031 # Sets the name of the path variable. 1032 hilog-lib 1033 # Specifies the name of the NDK library that 1034 # you want CMake to locate. 1035 hilog_ndk.z 1036 ) 1037 1038 target_link_libraries(entry PUBLIC libace_napi.z.so ${hilog-lib} libohweb.so) 1039 ``` 1040 1041* Node-API layer code: 1042 1043 ```c++ 1044 // entry/src/main/cpp/hello.cpp 1045 #include "napi/native_api.h" 1046 #include <bits/alltypes.h> 1047 #include <memory> 1048 #include <string> 1049 #include <sys/types.h> 1050 #include <thread> 1051 1052 #include "hilog/log.h" 1053 #include "web/arkweb_interface.h" 1054 #include "jsbridge_object.h" 1055 1056 constexpr unsigned int LOG_PRINT_DOMAIN = 0xFF00; 1057 std::shared_ptr<JSBridgeObject> jsbridge_object_ptr = nullptr; 1058 static ArkWeb_ControllerAPI *controller = nullptr; 1059 static ArkWeb_ComponentAPI *component = nullptr; 1060 1061 // Send the JS script to the HTML5 side for execution. This method is a callback of the execution result. 1062 static void RunJavaScriptCallback(const char *webTag, const char *result, void *userData) { 1063 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RunJavaScriptCallback webTag:%{public}s", webTag); 1064 if (!userData) { 1065 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RunJavaScriptCallback userData is nullptr"); 1066 return; 1067 } 1068 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1069 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1070 jsb_ptr->RunJavaScriptCallback(result); 1071 } else { 1072 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1073 "ndk RunJavaScriptCallback jsb_weak_ptr lock failed"); 1074 } 1075 } 1076 1077 // This example registers one object and two methods. 1078 static void ProxyMethod1(const char *webTag, const ArkWeb_JavaScriptBridgeData *dataArray, size_t arraySize, void *userData) { 1079 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 webTag:%{public}s", webTag); 1080 if (!userData) { 1081 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 userData is nullptr"); 1082 return; 1083 } 1084 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1085 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1086 jsb_ptr->ProxyMethod1(dataArray, arraySize); 1087 } else { 1088 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 jsb_weak_ptr lock failed"); 1089 } 1090 } 1091 1092 static void ProxyMethod2(const char *webTag, const ArkWeb_JavaScriptBridgeData *dataArray, size_t arraySize, void *userData) { 1093 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 webTag:%{public}s", webTag); 1094 if (!userData) { 1095 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 userData is nullptr"); 1096 return; 1097 } 1098 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1099 1100 std::string jsCode = "runJSRetStr()"; 1101 ArkWeb_JavaScriptObject object = {(uint8_t *)jsCode.c_str(), jsCode.size(), 1102 &JSBridgeObject::StaticRunJavaScriptCallback, 1103 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 1104 controller->runJavaScript(webTag, &object); 1105 1106 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1107 jsb_ptr->ProxyMethod2(dataArray, arraySize); 1108 } else { 1109 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 jsb_weak_ptr lock failed"); 1110 } 1111 } 1112 1113 void ValidCallback(const char *webTag, void *userData) { 1114 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback webTag: %{public}s", webTag); 1115 if (!userData) { 1116 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback userData is nullptr"); 1117 return; 1118 } 1119 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1120 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1121 jsb_ptr->SaySomething("ValidCallback"); 1122 } else { 1123 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback jsb_weak_ptr lock failed"); 1124 } 1125 1126 // Register an object. 1127 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RegisterJavaScriptProxy begin"); 1128 ArkWeb_ProxyMethod method1 = {"method1", ProxyMethod1, static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 1129 ArkWeb_ProxyMethod method2 = {"method2", ProxyMethod2, static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 1130 ArkWeb_ProxyMethod methodList[2] = {method1, method2}; 1131 // Call the NDK API to register an object. 1132 // In this case, you can use proxy.method1 and proxy.method2 to call ProxyMethod1 and ProxyMethod2 in this file on HTML5 pages. 1133 ArkWeb_ProxyObject proxyObject = {"ndkProxy", methodList, 2}; 1134 controller->registerJavaScriptProxy(webTag, &proxyObject); 1135 1136 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RegisterJavaScriptProxy end"); 1137 } 1138 1139 void LoadStartCallback(const char *webTag, void *userData) { 1140 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadStartCallback webTag: %{public}s", webTag); 1141 if (!userData) { 1142 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadStartCallback userData is nullptr"); 1143 return; 1144 } 1145 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1146 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1147 jsb_ptr->SaySomething("LoadStartCallback"); 1148 } else { 1149 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadStartCallback jsb_weak_ptr lock failed"); 1150 } 1151 } 1152 1153 void LoadEndCallback(const char *webTag, void *userData) { 1154 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadEndCallback webTag: %{public}s", webTag); 1155 if (!userData) { 1156 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadEndCallback userData is nullptr"); 1157 return; 1158 } 1159 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1160 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1161 jsb_ptr->SaySomething("LoadEndCallback"); 1162 } else { 1163 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk LoadEndCallback jsb_weak_ptr lock failed"); 1164 } 1165 } 1166 1167 void DestroyCallback(const char *webTag, void *userData) { 1168 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestoryCallback webTag: %{public}s", webTag); 1169 if (!userData) { 1170 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestroyCallback userData is nullptr"); 1171 return; 1172 } 1173 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1174 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1175 jsb_ptr->SaySomething("DestroyCallback"); 1176 } else { 1177 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestroyCallback jsb_weak_ptr lock failed"); 1178 } 1179 } 1180 1181 void SetComponentCallback(ArkWeb_ComponentAPI * component, const char* webTagValue) { 1182 if (!ARKWEB_MEMBER_MISSING(component, onControllerAttached)) { 1183 component->onControllerAttached(webTagValue, ValidCallback, 1184 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 1185 } else { 1186 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onControllerAttached func not exist"); 1187 } 1188 1189 if (!ARKWEB_MEMBER_MISSING(component, onPageBegin)) { 1190 component->onPageBegin(webTagValue, LoadStartCallback, 1191 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 1192 } else { 1193 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageBegin func not exist"); 1194 } 1195 1196 if (!ARKWEB_MEMBER_MISSING(component, onPageEnd)) { 1197 component->onPageEnd(webTagValue, LoadEndCallback, 1198 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 1199 } else { 1200 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onPageEnd func not exist"); 1201 } 1202 1203 if (!ARKWEB_MEMBER_MISSING(component, onDestroy)) { 1204 component->onDestroy(webTagValue, DestroyCallback, 1205 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())); 1206 } else { 1207 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "component onDestroy func not exist"); 1208 } 1209 } 1210 1211 // Parse and store the webTag. 1212 static napi_value NativeWebInit(napi_env env, napi_callback_info info) { 1213 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit start"); 1214 size_t argc = 1; 1215 napi_value args[1] = {nullptr}; 1216 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 1217 // Obtain the first parameter webTag. 1218 size_t webTagSize = 0; 1219 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 1220 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 1221 size_t webTagLength = 0; 1222 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 1223 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit webTag:%{public}s", webTagValue); 1224 1225 // Save the webTag in the instance object. 1226 jsbridge_object_ptr = std::make_shared<JSBridgeObject>(webTagValue); 1227 if (jsbridge_object_ptr) 1228 jsbridge_object_ptr->Init(); 1229 1230 controller = reinterpret_cast<ArkWeb_ControllerAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_CONTROLLER)); 1231 component = reinterpret_cast<ArkWeb_ComponentAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_COMPONENT)); 1232 SetComponentCallback(component, webTagValue); 1233 1234 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit end"); 1235 return nullptr; 1236 } 1237 1238 // Send the JS script to the HTML5 side for execution. 1239 static napi_value RunJavaScript(napi_env env, napi_callback_info info) { 1240 size_t argc = 2; 1241 napi_value args[2] = {nullptr}; 1242 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 1243 1244 // Obtain the first parameter webTag. 1245 size_t webTagSize = 0; 1246 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 1247 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 1248 size_t webTagLength = 0; 1249 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 1250 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk OH_NativeArkWeb_RunJavaScript webTag:%{public}s", 1251 webTagValue); 1252 1253 // Obtain the second parameter jsCode. 1254 size_t bufferSize = 0; 1255 napi_get_value_string_utf8(env, args[1], nullptr, 0, &bufferSize); 1256 char *jsCode = new (std::nothrow) char[bufferSize + 1]; 1257 size_t byteLength = 0; 1258 napi_get_value_string_utf8(env, args[1], jsCode, bufferSize + 1, &byteLength); 1259 1260 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1261 "ndk OH_NativeArkWeb_RunJavaScript jsCode len:%{public}zu", strlen(jsCode)); 1262 1263 // Construct a struct executed in runJS. 1264 ArkWeb_JavaScriptObject object = {(uint8_t *)jsCode, bufferSize, &JSBridgeObject::StaticRunJavaScriptCallback, 1265 static_cast<void *>(jsbridge_object_ptr->GetWeakPtr())}; 1266 controller->runJavaScript(webTagValue, &object); 1267 return nullptr; 1268 } 1269 1270 EXTERN_C_START 1271 static napi_value Init(napi_env env, napi_value exports) { 1272 napi_property_descriptor desc[] = { 1273 {"nativeWebInit", nullptr, NativeWebInit, nullptr, nullptr, nullptr, napi_default, nullptr}, 1274 {"runJavaScript", nullptr, RunJavaScript, nullptr, nullptr, nullptr, napi_default, nullptr}, 1275 }; 1276 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 1277 return exports; 1278 } 1279 EXTERN_C_END 1280 1281 static napi_module demoModule = { 1282 .nm_version = 1, 1283 .nm_flags = 0, 1284 .nm_filename = nullptr, 1285 .nm_register_func = Init, 1286 .nm_modname = "entry", 1287 .nm_priv = ((void *)0), 1288 .reserved = {0}, 1289 }; 1290 1291 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } 1292 ``` 1293 1294* Native service code: 1295 1296 ```c++ 1297 // entry/src/main/cpp/jsbridge_object.h 1298 #include "web/arkweb_type.h" 1299 #include <string> 1300 1301 class JSBridgeObject : public std::enable_shared_from_this<JSBridgeObject> { 1302 public: 1303 JSBridgeObject(const char* webTag); 1304 ~JSBridgeObject() = default; 1305 void Init(); 1306 std::weak_ptr<JSBridgeObject>* GetWeakPtr(); 1307 static void StaticRunJavaScriptCallback(const char *webTag, const ArkWeb_JavaScriptBridgeData *data, void *userData); 1308 void RunJavaScriptCallback(const char *result); 1309 void ProxyMethod1(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize); 1310 void ProxyMethod2(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize); 1311 void SaySomething(const char* say); 1312 1313 private: 1314 std::string webTag_; 1315 std::weak_ptr<JSBridgeObject> weak_ptr_; 1316 }; 1317 ``` 1318 1319 ```c++ 1320 // entry/src/main/cpp/jsbridge_object.cpp 1321 #include "jsbridge_object.h" 1322 1323 #include "hilog/log.h" 1324 1325 constexpr unsigned int LOG_PRINT_DOMAIN = 0xFF00; 1326 1327 JSBridgeObject::JSBridgeObject(const char *webTag) : webTag_(webTag) {} 1328 1329 void JSBridgeObject::Init() { weak_ptr_ = shared_from_this(); } 1330 1331 std::weak_ptr<JSBridgeObject> *JSBridgeObject::GetWeakPtr() { return &weak_ptr_; } 1332 1333 void JSBridgeObject::StaticRunJavaScriptCallback(const char *webTag, const ArkWeb_JavaScriptBridgeData *data, 1334 void *userData) { 1335 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1336 "JSBridgeObject StaticRunJavaScriptCallback webTag:%{public}s", webTag); 1337 if (!userData) { 1338 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1339 "JSBridgeObject StaticRunJavaScriptCallback userData is nullptr"); 1340 return; 1341 } 1342 std::weak_ptr<JSBridgeObject> jsb_weak_ptr = *static_cast<std::weak_ptr<JSBridgeObject> *>(userData); 1343 if (auto jsb_ptr = jsb_weak_ptr.lock()) { 1344 std::string result((char *)data->buffer, data->size); 1345 jsb_ptr->RunJavaScriptCallback(result.c_str()); 1346 } else { 1347 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1348 "JSBridgeObject StaticRunJavaScriptCallback jsb_weak_ptr lock failed"); 1349 } 1350 } 1351 1352 void JSBridgeObject::RunJavaScriptCallback(const char *result) { 1353 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1354 "JSBridgeObject OH_NativeArkWeb_RunJavaScript result:%{public}s", result); 1355 } 1356 1357 void JSBridgeObject::ProxyMethod1(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize) { 1358 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "JSBridgeObject ProxyMethod1 argc:%{public}d", 1359 arraySize); 1360 for (int i = 0; i < arraySize; i++) { 1361 std::string result((char *)dataArray[i].buffer, dataArray[i].size); 1362 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1363 "JSBridgeObject ProxyMethod1 argv[%{public}d]:%{public}s, size:%{public}d", i, result.c_str(), 1364 dataArray[i].size); 1365 } 1366 } 1367 1368 void JSBridgeObject::ProxyMethod2(const ArkWeb_JavaScriptBridgeData *dataArray, int32_t arraySize) { 1369 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "JSBridgeObject ProxyMethod2 argc:%{public}d", 1370 arraySize); 1371 for (int i = 0; i < arraySize; i++) { 1372 std::string result((char *)dataArray[i].buffer, dataArray[i].size); 1373 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 1374 "JSBridgeObject ProxyMethod2 argv[%{public}d]:%{public}s, size:%{public}d", i, result.c_str(), 1375 dataArray[i].size); 1376 } 1377 } 1378 1379 void JSBridgeObject::SaySomething(const char *say) { 1380 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "JSBridgeObject SaySomething argc:%{public}s", say); 1381 } 1382 ``` 1383 1384<!--no_check-->