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