• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  ![arkweb_jsbridge_arch](figures/arkweb_jsbridge_arch.png)
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  ![arkweb_jsbridge_diff](figures/arkweb_jsbridge_diff.png)
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-->