1# OHWebJSBridge 2 3 4## 概述 5 6该模块主要提供Web组件下runJavaScript和registerJavaScirptProxy的NDK接口。 7 8**起始版本:** 11 9 10**相关模块:**[OHWebJSBridge](native_interface_arkweb.md) 11 12 13## 汇总 14 15### 文件 16 17| 名称 | 描述 | 18| -------- | -------- | 19| [native_interface_arkweb.h](native_interface_arkweb.md) | 该文件主要提供Web组件下runJavaScript和registerJavaScirptProxy的NDK接口。 | 20 21 22### 类型定义 23 24| 名称 | 描述 | 25| -------- | -------- | 26| NativeArkWeb_OnJavaScriptCallback | runJavaScript接口的结果回调函数类型。当H5侧执行完后返回结果时通过该接口通知开发者。 | 27| NativeArkWeb_OnJavaScriptProxyCallback | registerJavaScirptProxy接口的回调函数类型。当H5侧主动调用注册的对象下的函数时通过该接口通知开发者。 | 28| NativeArkWeb_OnValidCallback | Web组件可注册对象时的回调函数类型。 | 29| NativeArkWeb_OnDestroyCallback | Web组件销毁时的回调函数类型。 | 30 31### 函数 32 33| 名称 | 描述 | 34| -------- | -------- | 35|OH_NativeArkWeb_RunJavaScript(const char* webTag, const char* jsCode, NativeArkWeb_OnJavaScriptCallback callback)|加载一段JS脚本,并通过回调返回脚本的执行结果。 | 36|OH_NativeArkWeb_RegisterJavaScriptProxy(const char* webTag, const char* objName, const char** methodList, NativeArkWeb_OnJavaScriptProxyCallback* callback, int32_t size, bool needRefresh)|注册应用侧的对象及回调函数。 | 37|OH_NativeArkWeb_UnregisterJavaScriptProxy(const char* webTag, const char* objName)|删除已注册的对象及回调函数。 | 38|OH_NativeArkWeb_SetJavaScriptProxyValidCallback(const char* webTag, NativeArkWeb_OnValidCallback callback)|设置对象可注册的回调函数。 | 39|NativeArkWeb_OnValidCallback OH_NativeArkWeb_GetJavaScriptProxyValidCallback(const char* webTag)|获取对象可注册的回调函数。 | 40|OH_NativeArkWeb_SetDestroyCallback(const char* webTag, NativeArkWeb_OnDestroyCallback callback)|设置组件销毁的回调函数。 | 41|NativeArkWeb_OnDestroyCallback OH_NativeArkWeb_GetDestroyCallback(const char* webTag)|获取组件销毁的回调函数。 | 42 43## 函数说明 44 45 46### OH_NativeArkWeb_RunJavaScript 47 48``` 49OH_NativeArkWeb_RunJavaScript(const char* webTag, const char* jsCode, NativeArkWeb_OnJavaScriptCallback callback) 50``` 51 52**描述** 53 54加载一段JS脚本,并通过回调返回脚本的执行结果。 55 56**系统能力:** SystemCapability.Web.Webview.Core 57 58**起始版本:** 11 59 60**参数:** 61 62| 名称 | 描述 | 63| -------- | -------- | 64| webTag | Web组件的标签名称,用于标识某个唯一组件,由开发者来保证名称唯一性。 | 65| jsCode | 一段JavaScript脚本代码,其会被发送到H5侧执行,并返回执行结果。 | 66| callback | 开发者注册的结果回调函数,当JavaScript脚本代码执行完毕后通过该回调函数返回执行的结果。 | 67 68### OH_NativeArkWeb_RegisterJavaScriptProxy 69 70``` 71OH_NativeArkWeb_RegisterJavaScriptProxy(const char* webTag, const char* objName, const char** methodList, NativeArkWeb_OnJavaScriptProxyCallback* callback, int32_t size, bool needRefresh) 72``` 73 74**描述** 75 76注册应用侧的对象及回调函数。 77 78**系统能力:** SystemCapability.Web.Webview.Core 79 80**起始版本:** 11 81 82**参数:** 83 84| 名称 | 描述 | 85| -------- | -------- | 86| webTag | Web组件的标签名称,用于标识某个唯一组件,由开发者来保证名称唯一性。 | 87| objName | 注入对象的名称,该对象会注册到H5侧window对象下面。 | 88| methodList | 注入对象下函数的名称列表。 | 89| callback | 注入对象下的回调函数,与medhotList函数名称保持一致即可。 | 90| size | 注入对象下函数名称列表的个数。 | 91| needRefresh | 注入对象后是否需要刷新。 | 92 93### OH_NativeArkWeb_UnregisterJavaScriptProxy 94 95``` 96OH_NativeArkWeb_UnregisterJavaScriptProxy(const char* webTag, const char* objName) 97``` 98 99**描述** 100 101删除已注册的对象及回调函数。 102 103**系统能力:** SystemCapability.Web.Webview.Core 104 105**起始版本:** 11 106 107**参数:** 108 109| 名称 | 描述 | 110| -------- | -------- | 111| webTag | Web组件的标签名称,用于标识某个唯一组件,由开发者来保证名称唯一性。 | 112| objName | 注入对象的名称,该对象会注册到H5侧window对象下面。 | 113 114### OH_NativeArkWeb_SetJavaScriptProxyValidCallback 115 116``` 117OH_NativeArkWeb_SetJavaScriptProxyValidCallback(const char* webTag, NativeArkWeb_OnValidCallback callback); 118``` 119 120**描述** 121 122设置对象可注册的回调函数。 123 124**系统能力:** SystemCapability.Web.Webview.Core 125 126**起始版本:** 11 127 128**参数:** 129 130| 名称 | 描述 | 131| -------- | -------- | 132| webTag | Web组件的标签名称,用于标识某个唯一组件,由开发者来保证名称唯一性。 | 133| callback | 对象可注册时的回调函数,当Web组件创建后对象可注册时 通过该回调通知开发者去注册对象。 | 134 135### OH_NativeArkWeb_GetJavaScriptProxyValidCallback 136 137``` 138NativeArkWeb_OnValidCallback OH_NativeArkWeb_GetJavaScriptProxyValidCallback(const char* webTag) 139``` 140 141**描述** 142 143根据标签名称获取对象可注册的回调函数。 144 145**系统能力:** SystemCapability.Web.Webview.Core 146 147**起始版本:** 11 148 149**参数:** 150 151| 名称 | 描述 | 152| -------- | -------- | 153| webTag | Web组件的标签名称,用于标识某个唯一组件,由开发者来保证名称唯一性。 | 154| callback | 对象可注册时的回调函数,当Web组件创建后对象可注册时 通过该回调通知开发者去注册对象。 | 155 156**返回:** 157 158根据标签名称返回已注册的回调函数。 159 160### OH_NativeArkWeb_SetDestroyCallback 161 162``` 163OH_NativeArkWeb_SetDestroyCallback(const char* webTag, NativeArkWeb_OnDestroyCallback callback) 164``` 165 166**描述** 167 168设置组件销毁的回调函数。 169 170**系统能力:** SystemCapability.Web.Webview.Core 171 172**起始版本:** 11 173 174**参数:** 175 176| 名称 | 描述 | 177| -------- | -------- | 178| webTag | Web组件的标签名称,用于标识某个唯一组件,由开发者来保证名称唯一性。 | 179| callback | 对象销毁时的回调函数,当Web组件销毁时 通过该回调通知开发者。 | 180 181### OH_NativeArkWeb_GetDestroyCallback 182 183``` 184NativeArkWeb_OnDestroyCallback OH_NativeArkWeb_GetDestroyCallback(const char* webTag) 185``` 186 187**描述** 188 189根据标签名称获取组件销毁的回调函数。 190 191**系统能力:** SystemCapability.Web.Webview.Core 192 193**起始版本:** 11 194 195**参数:** 196 197| 名称 | 描述 | 198| -------- | -------- | 199| webTag | Web组件的标签名称,用于标识某个唯一组件,由开发者来保证名称唯一性。 | 200 201**返回:** 202 203根据标签名称返回已注册的回调函数。 204 205## 示例代码 206 207 208index.html 209```html 210<!DOCTYPE html> 211<html lang="en-gb"> 212<head> 213 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 214 <title>run javascript demo</title> 215</head> 216<body> 217<h1>run JavaScript Ext demo</h1> 218<p id="webDemo"></p> 219<br> 220<button type="button" style="height:30px;width:200px" onclick="testNdkProxyObjMethod1()">test ndk method1 ! </button> 221<br> 222<br> 223<button type="button" style="height:30px;width:200px" onclick="testNdkProxyObjMethod2()">test ndk method2 ! </button> 224<br> 225 226</body> 227<script type="text/javascript"> 228 229function testNdkProxyObjMethod1() { 230 if (window.ndkProxy == undefined) { 231 document.getElementById("webDemo").innerHTML = "m114 ndkProxy undefined" 232 return "m114 objName undefined" 233 } 234 235 if (window.ndkProxy.method1 == undefined) { 236 document.getElementById("webDemo").innerHTML = "m114 ndkProxy method1 undefined" 237 return "m114 objName test undefined" 238 } 239 240 if (window.ndkProxy.method2 == undefined) { 241 document.getElementById("webDemo").innerHTML = "m114 ndkProxy method2 undefined" 242 return "m114 objName test undefined" 243 } 244 var retStr = window.ndkProxy.method1("hello", "world", [1.2, -3.4, 123.456], ["Saab", "Volvo", "BMW", undefined], 1.23456, 123789, true, false, 0, undefined); 245 document.getElementById("webDemo").innerHTML = "ndkProxy and method1 is ok, " + retStr; 246} 247 248function testNdkProxyObjMethod2() { 249 if (window.ndkProxy == undefined) { 250 document.getElementById("webDemo").innerHTML = "m114 ndkProxy undefined" 251 return "m114 objName undefined" 252 } 253 254 if (window.ndkProxy.method1 == undefined) { 255 document.getElementById("webDemo").innerHTML = "m114 ndkProxy method1 undefined" 256 return "m114 objName test undefined" 257 } 258 259 if (window.ndkProxy.method2 == undefined) { 260 document.getElementById("webDemo").innerHTML = "m114 ndkProxy method2 undefined" 261 return "m114 objName test undefined" 262 } 263 264 var student = { 265 name:"zhang", 266 sex:"man", 267 age:25 268 }; 269 var cars = [student, 456, false, 4.567]; 270 271 var retStr = window.ndkProxy.method2("hello", "world", false, cars); 272 document.getElementById("webDemo").innerHTML = "ndkProxy and method2 is ok, " + retStr; 273} 274 275function runJSRetStr(data) { 276 const d = new Date(); 277 let time = d.getTime(); 278 return JSON.stringify(time) 279} 280</script> 281</html> 282``` 283 284index.ets 285 286```ts 287import testNapi from 'libentry.so' 288import web_webview from '@ohos.web.webview'; 289 290class testObj { 291 constructor() { 292 } 293 294 test(): string { 295 console.log('hwd ArkUI Web Component'); 296 return "m114 ArkUI Web Component"; 297 } 298 299 toString(): void { 300 console.log('Web Component toString'); 301 } 302} 303 304@Entry 305@Component 306struct Index { 307 webTag: string = 'web1211'; 308 controller: web_webview.WebviewController = new web_webview.WebviewController(this.webTag); 309 310 @State testObjtest: testObj = new testObj(); 311 312 aboutToAppear() { 313 console.error("aboutToAppear") 314 web_webview.WebviewController.setWebDebuggingAccess(true); 315 //初始化web ndk 316 testNapi.nativeWebInit(this.webTag); 317 } 318 319 aboutToDisAppear() { 320 console.error("aboutToDisAppear") 321 } 322 323 build() { 324 Column() { 325 Row() { 326 Button('runJS hello') 327 .fontSize(12) 328 .onClick(() => { 329 testNapi.runJavaScript(this.webTag, "runJSRetStr(\"" + "hello" + "\")"); 330 }) 331 }.height('20%') 332 333 Row() { 334 Web({ src: $rawfile('index.html'), controller: this.controller }) 335 .javaScriptAccess(true) 336 .fileAccess(true) 337 .onControllerAttached(() => { 338 console.error("ndk onControllerAttached webId: " + this.controller.getWebId()); 339 // 设置回调函数 340 testNapi.nativeSetDestroy(this.webTag); 341 }) 342 }.height('80%') 343 } 344 } 345} 346``` 347 348hello.cpp 349 350```cpp 351 352#include "napi/native_api.h" 353#include <chrono> 354#include <string> 355 356#include "hilog/log.h" 357#include "web/native_interface_arkweb.h" 358 359constexpr unsigned int LOG_PRINT_DOMAIN = 0xFF00; 360 361std::chrono::time_point<std::chrono::high_resolution_clock> start; 362// 发送JS脚本到H5侧执行,执行结果的回调。 363static void RunJavaScriptCallback(const char *result) { 364 std::chrono::duration<double, std::milli> elapsed_ms = std::chrono::high_resolution_clock::now() - start; 365 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 366 "ndk OH_NativeArkWeb_RunJavaScript end, cost time: %{public}f ms", elapsed_ms.count()); 367 368 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk OH_NativeArkWeb_RunJavaScript result:%{public}s", 369 result); 370} 371 372// 示例代码 ,注册了1个对象,2个方法 373static char *ProxyMethod1(const char **argv, int argc) { 374 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 argc:%{public}d", argc); 375 for (int i = 0; i < argc; i++) { 376 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod1 argv[%{public}d]:%{public}s", i, 377 argv[i]); 378 } 379 char *ret = (char *)"ArkWeb hello from native ProxyMethod1"; 380 return ret; 381} 382 383static char *ProxyMethod2(const char **argv, int argc) { 384 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 argc:%{public}d", argc); 385 for (int i = 0; i < argc; i++) { 386 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ProxyMethod2 argv[%{public}d]:%{public}s", i, 387 argv[i]); 388 } 389 char *ret = (char *)"ArkWeb hello from native ProxyMethod2"; 390 return ret; 391} 392 393void ValidCallback(const char *webName) { 394 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk ValidCallback webName: %{public}s", webName); 395 // 注册对象 396 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RegisterJavaScriptProxy begin"); 397 const char *methodName[2] = {"method1", "method2"}; 398 NativeArkWeb_OnJavaScriptProxyCallback callback[2] = {ProxyMethod1, ProxyMethod2}; 399 400 // 调用ndk接口 注册对象 401 // 如此注册的情况下,在H5页面就可以使用proxy.method1、proxy.method1调用此文件下的ProxyMethod1和ProxyMethod2方法了 402 OH_NativeArkWeb_RegisterJavaScriptProxy(webName, "ndkProxy", methodName, callback, 2, false); 403 404 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk RegisterJavaScriptProxy end"); 405} 406 407void DestroyCallback(const char *webName) { 408 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk DestoryCallback webName: %{public}s", webName); 409 // do what you need, eg: some clean-up work 410} 411 412static napi_value NativeWebInit(napi_env env, napi_callback_info info) { 413 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit start"); 414 size_t argc = 1; 415 napi_value args[1] = {nullptr}; 416 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 417 // 获取第一个参数 webName 418 size_t webNameSize = 0; 419 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webNameSize); 420 char *webNameValue = new (std::nothrow) char[webNameSize + 1]; 421 size_t webNameLength = 0; 422 napi_get_value_string_utf8(env, args[0], webNameValue, webNameSize + 1, &webNameLength); 423 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit webName:%{public}s", webNameValue); 424 425 // 注js proxy册回调函数 426 NativeArkWeb_OnValidCallback ptr = ValidCallback; 427 OH_NativeArkWeb_SetJavaScriptProxyValidCallback(webNameValue, ptr); 428 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit ValidCallback set:%{public}p", ptr); 429 NativeArkWeb_OnValidCallback retValidCallback = OH_NativeArkWeb_GetJavaScriptProxyValidCallback(webNameValue); 430 if (retValidCallback) { 431 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit ValidCallback get:%{public}p", 432 retValidCallback); 433 } else { 434 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk retValidCallback null"); 435 } 436 437 // 注册destroy回调函数 438 OH_NativeArkWeb_SetDestroyCallback(webNameValue, DestroyCallback); 439 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit DestroyCallback:%{public}p", 440 DestroyCallback); 441 auto retDestroyCallback1 = OH_NativeArkWeb_GetDestroyCallback(webNameValue); 442 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit DestroyCallback get:%{public}p", 443 retDestroyCallback1); 444 445 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit end"); 446 447 return nullptr; 448} 449 450static napi_value NativeSetDestroy(napi_env env, napi_callback_info info) { 451 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeSetDestroy start"); 452 size_t argc = 1; 453 napi_value args[1] = {nullptr}; 454 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 455 // 获取第一个参数 webTag 456 size_t webTagSize = 0; 457 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 458 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 459 size_t webTagLength = 0; 460 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 461 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeSetDestroy webTag:%{public}s", webTagValue); 462 463 // 注册destroy回调函数 464 OH_NativeArkWeb_SetDestroyCallback(webTagValue, DestroyCallback); 465 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeSetDestroy DestroyCallback:%{public}p", 466 DestroyCallback); 467 auto retDestroyCallback1 = OH_NativeArkWeb_GetDestroyCallback(webTagValue); 468 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeSetDestroy DestroyCallback get:%{public}p", 469 retDestroyCallback1); 470 471 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeSetDestroy end"); 472 return nullptr; 473} 474 475// 发送JS脚本到H5侧执行 476static napi_value RunJavaScript(napi_env env, napi_callback_info info) { 477 size_t argc = 2; 478 napi_value args[2] = {nullptr}; 479 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 480 481 // 获取第一个参数 webName 482 size_t webNameSize = 0; 483 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webNameSize); 484 char *webNameValue = new (std::nothrow) char[webNameSize + 1]; 485 size_t webNameLength = 0; 486 napi_get_value_string_utf8(env, args[0], webNameValue, webNameSize + 1, &webNameLength); 487 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk OH_NativeArkWeb_RunJavaScript webName:%{public}s", 488 webNameValue); 489 490 // 获取第二个参数 jsCode 491 size_t bufferSize = 0; 492 napi_get_value_string_utf8(env, args[1], nullptr, 0, &bufferSize); 493 char *jsCode = new (std::nothrow) char[bufferSize + 1]; 494 size_t byteLength = 0; 495 napi_get_value_string_utf8(env, args[1], jsCode, bufferSize + 1, &byteLength); 496 497 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 498 "ndk OH_NativeArkWeb_RunJavaScript jsCode len:%{public}d", strlen(jsCode)); 499 500 start = std::chrono::high_resolution_clock::now(); 501 502 // 调用ndk接口 503 OH_NativeArkWeb_RunJavaScript(webNameValue, jsCode, RunJavaScriptCallback); 504 return nullptr; 505} 506 507EXTERN_C_START 508static napi_value Init(napi_env env, napi_value exports) { 509 napi_property_descriptor desc[] = { 510 {"nativeWebInit", nullptr, NativeWebInit, nullptr, nullptr, nullptr, napi_default, nullptr}, 511 {"runJavaScript", nullptr, RunJavaScript, nullptr, nullptr, nullptr, napi_default, nullptr}, 512 {"nativeSetDestroy", nullptr, NativeSetDestroy, nullptr, nullptr, nullptr, napi_default, nullptr}, 513 }; 514 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 515 return exports; 516} 517EXTERN_C_END 518 519static napi_module demoModule = { 520 .nm_version = 1, 521 .nm_flags = 0, 522 .nm_filename = nullptr, 523 .nm_register_func = Init, 524 .nm_modname = "entry", 525 .nm_priv = ((void *)0), 526 .reserved = {0}, 527}; 528 529extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } 530``` 531 532index.d.ts 533```ts 534export const nativeWebInit: (webName: string) => void; 535export const runJavaScript: (webName: string, jsCode: string) => void; 536export const nativeSetDestroy: (webTag: string) => void; 537``` 538