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