1# Establishing a Data Channel Between the Application and the Frontend Page (C/C++) 2 3The following provides native APIs to implement communication between the frontend page and the application, which avoid unnecessary switching to the ArkTS environment and allow callback to be reported in non-UI threads to avoid UI blocking. In addition, messages and callbacks can be reported in non-UI threads to avoid UI blocking. Currently, only the string and buffer can be sent. 4 5## Binding the Native ArkWeb Component 6 7- The ArkWeb component is declared on the ArkTS side. You need to define a **webTag** and pass it to the C++ application through the Node-API. When the ArkWeb native API is called, **webTag** uniquely identifies the corresponding component. 8 9- ArkTS side: 10 11 ```ts 12 import { webview } from '@kit.ArkWeb'; 13 // Define a webTag and pass it to WebviewController when it is created to establish the mapping between controller and webTag. 14 webTag: string = 'ArkWeb1'; 15 controller: webview.WebviewController = new webview.WebviewController(); 16 ... 17 // Use aboutToAppear() to pass the webTag to C++ through the native API. The webTag uniquely identifies the C++ ArkWeb component. 18 aboutToAppear() { 19 console.info("aboutToAppear") 20 // Initialize the NDK API of the Web component. 21 testNapi.nativeWebInit(this.webTag); 22 } 23 ... 24 ``` 25 26## Obtaining the Native API Struct 27 28Obtain the ArkWeb native APIs using [OH_ArkWeb_GetNativeAPI](../reference/apis-arkweb/_ark_web___any_native_a_p_i.md#arkweb_anynativeapi). You can pass different parameters to obtain the corresponding function pointer structs. The following APIs are provided: [ArkWeb_ControllerAPI](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#arkweb_controllerapi), [ArkWeb_WebMessageAPI](../reference/apis-arkweb/_ark_web___web_message_a_p_i.md#arkweb_webmessageapi) and [ArkWeb_WebMessagePortAPI](../reference/apis-arkweb/_ark_web___web_message_port_a_p_i.md#arkweb_webmessageportapi). 29 30 ```c++ 31 static ArkWeb_ControllerAPI *controller = nullptr; 32 static ArkWeb_WebMessagePortAPI *webMessagePort = nullptr; 33 static ArkWeb_WebMessageAPI *webMessage = nullptr; 34 ... 35 controller = reinterpret_cast<ArkWeb_ControllerAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_CONTROLLER)); 36 webMessagePort = 37 reinterpret_cast<ArkWeb_WebMessagePortAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_WEB_MESSAGE_PORT)); 38 webMessage = reinterpret_cast<ArkWeb_WebMessageAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_WEB_MESSAGE)); 39 ``` 40 41## Sample Code 42 43Use [ARKWEB_MEMBER_MISSING](../reference/apis-arkweb/_web.md#arkweb_member_missing) to check whether the function struct has the corresponding pointer before calling an API to avoid crash caused by mismatch between the SDK and the device ROM. [createWebMessagePorts](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#createwebmessageports), [postWebMessage](../reference/apis-arkweb/_ark_web___controller_a_p_i.md#postwebmessage) and [close](../reference/apis-arkweb/_ark_web___web_message_port_a_p_i.md#close) must be used in the UI thread. 44 45* Frontend page code: 46 47 ```html 48 <!-- entry/src/main/resources/rawfile/index.html --> 49 <!-- index.html --> 50 <!DOCTYPE html> 51 <html lang="en-gb"> 52 <body> 53 <h1>etsRunJavaScriptExt test demo</h1>; 54 <h1 id="h1"></h1> 55 <h3 id="msg">Receive string:</h3> 56 <h3 id="msg2">Receive arraybuffer:</h3> 57 58 </body> 59 <script type="text/javascript"> 60 var h5Port; 61 62 window.addEventListener('message', function (event) { 63 if (event.data == 'init_web_messageport') { 64 const port = event.ports.at(0); // 1. Save the port sent from the application. 65 if (port) { 66 console.log("hwd In html got message"); 67 h5Port = port; 68 port.onmessage = function (event) { 69 console.log("hwd In html got message"); 70 // 2. Receive the message sent from the application. 71 var result = event.data; 72 var type_s = typeof (result) 73 switch (type_s) { 74 case "object": 75 if (result instanceof ArrayBuffer) { 76 type_s = "ArrayBuffer"; 77 var view = new Uint8Array(result); 78 const decoder = new TextDecoder('utf-8'); 79 result = decoder.decode(result); 80 } else if (result instanceof Error) { 81 type_s = "Error"; 82 } else if (result instanceof Array) { 83 type_s = "Array"; 84 } 85 break; 86 default: 87 break; 88 } 89 console.log("H5 recv type: " + type_s + "\nH5 recv result: " + result) 90 document.getElementById("msg").innerHTML = "recv type: " + type_s; 91 document.getElementById("msg2").innerHTML = "recv value: " + result; 92 } 93 h5Port.onmessageerror = (event) => { 94 console.error(`hwd In html Error receiving message: ${event}`); 95 }; 96 } 97 } 98 }) 99 window.onerror = function(message, url, line, column, error) { 100 console.log("JavaScript Error: " + message + " on line " + line + " in " + url); 101 document.getElementById("h1").innerHTML = "Failed to execute the function." 102 }; 103 104 // 3. Use h5Port to send messages to the application. 105 function postStringToApp() { 106 if (h5Port) { 107 h5Port.postMessage("send string from H5"); 108 } else { 109 console.error("In html h5port is null, please init first"); 110 } 111 } 112 function postBufferToApp() { 113 if (h5Port) { 114 const str = "Hello, World!"; 115 const encoder = new TextEncoder(); 116 const uint8Array = encoder.encode(str); 117 h5Port.postMessage(uint8Array.buffer); 118 } else { 119 console.error("In html h5port is null, please init first"); 120 } 121 } 122 123 function postJsonToApp() { 124 if (h5Port) { 125 var e = {"json": "json"}; 126 h5Port.postMessage(e); 127 } else { 128 console.error("In html h5port is null, please init first"); 129 } 130 } 131 132 function postArrayStringToApp() { 133 if (h5Port) { 134 h5Port.postMessage(["1", "2", "3"]); 135 } else { 136 console.error("In html h5port is null, please init first"); 137 } 138 } 139 140 function postNumberToApp() { 141 if (h5Port) { 142 h5Port.postMessage(123); 143 } else { 144 console.error("In html h5port is null, please init first"); 145 } 146 } 147 class MyClass { 148 constructor() { 149 // Constructor. 150 this.myProperty = 'Hello, World!'; 151 } 152 153 myMethod() { 154 // Instance method. 155 console.log(this.myProperty); 156 } 157 158 static myStaticMethod() { 159 // Static method. 160 console.log('This is a static method.'); 161 } 162 } 163 function postObjectToApp() { 164 if (h5Port) { 165 h5Port.postMessage(new MyClass()); 166 } else { 167 console.error("In html h5port is null, please init first"); 168 } 169 } 170 171 </script> 172 </html> 173 ``` 174 175* ArkTS code: 176 177 ```javascript 178 // entry/src/main/ets/pages/Index.ets 179 import testNapi from 'libentry.so' 180 import web_webview from '@ohos.web.webview'; 181 import { BusinessError } from '@ohos.base'; 182 183 @Entry 184 @Component 185 struct Index { 186 @State webTag: string = 'postMessage'; 187 controller: web_webview.WebviewController = new web_webview.WebviewController(this.webTag); 188 @State h5Log: string = 'Display received message send from HTML'; 189 190 aboutToAppear() { 191 web_webview.WebviewController.setWebDebuggingAccess(true); 192 // Initialize the NDK API of the Web component. 193 testNapi.nativeWebInit(this.webTag); 194 } 195 196 aboutToDisAppear() { 197 console.error("aboutToDisAppear") 198 } 199 200 build() { 201 Scroll() { 202 Column({ space: 10 }) { 203 // Display the content received by the HTML5 page. 204 Text ("The message received by the HTML5 page from the application") 205 TextArea({text: this.h5Log}) 206 .id("log_area") 207 .width("100%") 208 .height(100) 209 .border({ width: 1 }) 210 Text ("Button on the application") 211 Row() { 212 Button('createNoControllerTagPort') 213 .id("create_no_tag_btn") 214 .onClick(() => { 215 try { 216 testNapi.createWebMessagePorts("noTag"); 217 } catch (error) { 218 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 219 } 220 }) 221 Button('createPort') 222 .id("create_port_btn") 223 .onClick(() => { 224 try { 225 testNapi.createWebMessagePorts(this.webTag); 226 } catch (error) { 227 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 228 } 229 }) 230 } 231 232 Row({ space: 10 }) { 233 234 Button('setHandler') 235 .id("set_handler_btn") 236 .onClick(() => { 237 try { 238 testNapi.setMessageEventHandler(this.webTag); 239 } catch (error) { 240 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 241 } 242 }) 243 244 Button('setHandlerThread') 245 .id("set_handler_thread_btn") 246 .onClick(() => { 247 try { 248 testNapi.setMessageEventHandlerThread(this.webTag); 249 } catch (error) { 250 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 251 } 252 }) 253 } 254 255 Row({ space: 10 }) { 256 Button('SendString') 257 .id("send_string_btn") 258 .onClick(() => { 259 try { 260 this.h5Log = "" 261 testNapi.postMessage(this.webTag); 262 } catch (error) { 263 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 264 } 265 }) 266 Button('SendStringThread') 267 .id("send_string_thread_btn") 268 .onClick(() => { 269 try { 270 this.h5Log = "" 271 testNapi.postMessageThread(this.webTag); 272 } catch (error) { 273 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 274 } 275 }) 276 } 277 278 Row({ space: 10 }) { 279 Button('SendBuffer') 280 .id("send_buffer_btn") 281 .onClick(() => { 282 try { 283 this.h5Log = "" 284 testNapi.postBufferMessage(this.webTag); 285 } catch (error) { 286 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 287 } 288 }) 289 Button('SendNone') 290 .id("send_none_btn") 291 .onClick(() => { 292 try { 293 this.h5Log = "" 294 testNapi.postNoneMessage(this.webTag); 295 } catch (error) { 296 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 297 } 298 }) 299 } 300 301 Row({ space: 10 }) { 302 303 Button('closePort') 304 .id("close_port_btn") 305 .onClick(() => { 306 try { 307 testNapi.closeMessagePort(this.webTag); 308 } catch (error) { 309 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 310 } 311 }) 312 Button('destroyNullPort') 313 .id("destroy_null_btn") 314 .onClick(() => { 315 try { 316 testNapi.destroyNullMessagePort(this.webTag); 317 } catch (error) { 318 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 319 } 320 }) 321 Button('destroyPort') 322 .id("destroy_port_btn") 323 .onClick(() => { 324 try { 325 testNapi.destroyMessagePort(this.webTag); 326 } catch (error) { 327 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 328 } 329 }) 330 } 331 .width("100%") 332 .padding(10) 333 .border({ width: 1 }) 334 335 Column({ space: 10 }) { 336 Text ("The Send button on the HTML5 page") 337 Row({ space: 10 }) { 338 Button('H5String') 339 .id("h5_send_string_btn") 340 .onClick(() => { 341 try { 342 this.controller.runJavaScript("for(var i = 0; i < 2000; i++) postStringToApp()") 343 } catch (error) { 344 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 345 } 346 }) 347 Button('H5Buffer') 348 .id("h5_send_buffer_btn") 349 .onClick(() => { 350 try { 351 this.controller.runJavaScript("postBufferToApp()") 352 } catch (error) { 353 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 354 } 355 }) 356 Button('H5Number') 357 .id("h5_send_number_btn") 358 .onClick(() => { 359 try { 360 this.controller.runJavaScript("postNumberToApp()") 361 } catch (error) { 362 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 363 } 364 }) 365 } 366 367 Row({ space: 10 }) { 368 Button('H5Json') 369 .id("h5_send_json_btn") 370 .onClick(() => { 371 try { 372 this.controller.runJavaScript("postJsonToApp()") 373 } catch (error) { 374 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 375 } 376 }) 377 Button('H5Array') 378 .id("h5_send_array_btn") 379 .onClick(() => { 380 try { 381 this.controller.runJavaScript("postArrayStringToApp()") 382 } catch (error) { 383 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 384 } 385 }) 386 Button('H5Object') 387 .id("h5_send_object_btn") 388 .onClick(() => { 389 try { 390 this.controller.runJavaScript("postObjectToApp()") 391 } catch (error) { 392 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 393 } 394 }) 395 } 396 } 397 .width("100%") 398 .margin(10) 399 .padding(10) 400 .border({ width: 1 }) 401 402 Web({ src: $rawfile('index.html'), controller: this.controller }) 403 .onConsole((event) => { 404 if (event) { 405 let msg = event.message.getMessage() 406 if (msg.startsWith("H5")) { 407 this.h5Log = event.message.getMessage() + "\n" + this.h5Log 408 } 409 } 410 return false; 411 }) 412 } 413 }.height('100%') 414 .scrollable(ScrollDirection.Vertical) 415 .scrollBar(BarState.Off) 416 .edgeEffect(EdgeEffect.Spring) 417 } 418 } 419 ``` 420 421* ArkTS APIs exposed on the native APIs: 422 423 ```javascript 424 // entry/src/main/cpp/types/libentry/index.d.ts 425 export const nativeWebInit: (webName: string) => void; 426 export const createWebMessagePorts: (webName: string) => void; 427 export const postMessage: (webName: string) => void; 428 export const postNoneMessage: (webName: string) => void; 429 export const setMessageEventHandler: (webName: string) => void; 430 export const closeMessagePort: (webName: string) => void; 431 export const destroyMessagePort: (webName: string) => void; 432 export const postBufferMessage: (webName: string) => void; 433 export const destroyNullMessagePort: (webName: string) => void; 434 export const setMessageEventHandlerThread: (webName: string) => void; 435 export const postMessageThread: (webName: string) => void; 436 ``` 437 438* Compilation configuration of the native APIs: 439 440 ```c++ 441 # entry/src/main/cpp/CMakeLists.txt 442 # the minimum version of CMake. 443 cmake_minimum_required(VERSION 3.4.1) 444 project(NDKPostMessage) 445 446 set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 447 448 if(DEFINED PACKAGE_FIND_FILE) 449 include(${PACKAGE_FIND_FILE}) 450 endif() 451 452 include_directories(${NATIVERENDER_ROOT_PATH} 453 ${NATIVERENDER_ROOT_PATH}/include) 454 455 add_library(entry SHARED hello.cpp) 456 457 find_library( 458 # Sets the name of the path variable. 459 hilog-lib 460 # Specifies the name of the NDK library that 461 # you want CMake to locate. 462 hilog_ndk.z 463 ) 464 465 target_link_libraries(entry PUBLIC libace_napi.z.so ${hilog-lib} libohweb.so) 466 ``` 467 468* Native API code: 469 470 ```c++ 471 // entry/src/main/cpp/hello.cpp 472 #include "napi/native_api.h" 473 #include <bits/alltypes.h> 474 #include <memory> 475 #include <string> 476 #include <sys/types.h> 477 #include <iostream> 478 #include <map> 479 #include "hilog/log.h" 480 #include "web/arkweb_interface.h" 481 #include <thread> 482 483 constexpr unsigned int LOG_PRINT_DOMAIN = 0xFF00; 484 ArkWeb_ControllerAPI *controller = nullptr; 485 486 ArkWeb_WebMessagePortAPI *webMessagePort = nullptr; 487 ArkWeb_WebMessageAPI *webMessage = nullptr; 488 size_t web_message_port_size = 0; 489 ArkWeb_WebMessagePortPtr *g_web_message_port_arr = nullptr; 490 491 static void WebMessagePortCallback(const char *webTag, const ArkWeb_WebMessagePortPtr port, 492 const ArkWeb_WebMessagePtr message, void *userData) { 493 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 494 "ndk WebMesagePortCallback webTag:%{public}s,messageType:%{public}d", webTag, 495 webMessage->getType(message)); 496 size_t len = 0; 497 void *back = webMessage->getData(message, &len); 498 if (webMessage->getType(message) == ArkWeb_WebMessageType::ARKWEB_STRING) { 499 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 500 "ndk WebMesagePortCallback message:%{public}s,messageSize:%{public}d", back, len); 501 } else if (webMessage->getType(message) == ArkWeb_WebMessageType::ARKWEB_BUFFER) { 502 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 503 "ndk WebMesagePortCallback messageSize:%{public}d", len); 504 } 505 } 506 507 static napi_value NativeWebInit(napi_env env, napi_callback_info info) { 508 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit start"); 509 size_t argc = 1; 510 napi_value args[1] = {nullptr}; 511 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 512 // Obtain the first parameter webTag. 513 size_t webTagSize = 0; 514 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 515 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 516 size_t webTagLength = 0; 517 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 518 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit webTag:%{public}s", webTagValue); 519 520 controller = reinterpret_cast<ArkWeb_ControllerAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_CONTROLLER)); 521 if (controller) 522 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "get ArkWeb_ControllerAPI success"); 523 524 webMessagePort = 525 reinterpret_cast<ArkWeb_WebMessagePortAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_WEB_MESSAGE_PORT)); 526 if (webMessagePort) 527 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "get ArkWeb_WebMessagePortAPI success"); 528 529 webMessage = reinterpret_cast<ArkWeb_WebMessageAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_WEB_MESSAGE)); 530 if (webMessage) 531 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "get ArkWeb_WebMessageAPI success"); 532 533 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk NativeWebInit end"); 534 535 return nullptr; 536 } 537 538 static napi_value createWebMessagePorts(napi_env env, napi_callback_info info) { 539 size_t argc = 2; 540 napi_value args[2] = {nullptr}; 541 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 542 543 // Obtain the first parameter webTag. 544 size_t webTagSize = 0; 545 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 546 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 547 size_t webTagLength = 0; 548 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 549 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk Refresh webTag:%{public}s", webTagValue); 550 551 // Initialize the ports. 552 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk createWebMessagePorts begin"); 553 g_web_message_port_arr = controller->createWebMessagePorts(webTagValue, &web_message_port_size); 554 // Send one of the ports to the HTML page. 555 ArkWeb_ErrorCode code = 556 controller->postWebMessage(webTagValue, "init_web_messageport", g_web_message_port_arr, 1, "*"); 557 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk postWebMessage ArkWeb_ErrorCode:%{public}d", code); 558 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 559 "ndk createWebMessagePorts end, web message port size:%{public}d", web_message_port_size); 560 return nullptr; 561 } 562 563 static napi_value postMessage(napi_env env, napi_callback_info info) { 564 size_t argc = 2; 565 napi_value args[2] = {nullptr}; 566 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 567 568 // Obtain the first parameter webTag. 569 size_t webTagSize = 0; 570 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 571 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 572 size_t webTagLength = 0; 573 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 574 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk Refresh webTag:%{public}s", webTagValue); 575 576 // Send a message. 577 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk postMessage begin"); 578 579 if (g_web_message_port_arr == nullptr) { 580 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "webMessagePort is nullptr"); 581 return nullptr; 582 } 583 ArkWeb_WebMessagePtr message = webMessage->createWebMessage(); 584 webMessage->setType(message, ArkWeb_WebMessageType::ARKWEB_STRING); 585 std::string str = "send string from native"; 586 webMessage->setData(message, (void *)str.c_str(), str.length() + 1); 587 ArkWeb_ErrorCode code = webMessagePort->postMessage(g_web_message_port_arr[1], webTagValue, message); 588 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk postMessage ArkWeb_ErrorCode:%{public}d", code); 589 webMessage->destroyWebMessage(&message); 590 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk postMessage end, web message port size:%{public}d", 591 web_message_port_size); 592 return nullptr; 593 } 594 595 // Send a message in the thread. 596 void sendMessage(const char *webTag, const ArkWeb_WebMessagePtr message) { 597 // Send the message for 1000 times. 598 for (int i = 0; i < 1000; i++) { 599 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "sendMessage in thread %{public}d", i); 600 if (g_web_message_port_arr && webTag && message) { 601 webMessagePort->postMessage(g_web_message_port_arr[1], webTag, message); 602 } 603 } 604 } 605 static napi_value postMessageThread(napi_env env, napi_callback_info info) { 606 size_t argc = 2; 607 napi_value args[2] = {nullptr}; 608 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 609 610 // Obtain the first parameter webTag. 611 size_t webTagSize = 0; 612 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 613 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 614 size_t webTagLength = 0; 615 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 616 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk Refresh webTag:%{public}s", webTagValue); 617 618 // Construct a message. 619 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk postMessage begin"); 620 621 if (g_web_message_port_arr == nullptr) { 622 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "webMessagePort is nullptr"); 623 return nullptr; 624 } 625 ArkWeb_WebMessagePtr message = webMessage->createWebMessage(); 626 webMessage->setType(message, ArkWeb_WebMessageType::ARKWEB_STRING); 627 std::string str = "thread message"; 628 webMessage->setData(message, (void *)str.c_str(), str.length() + 1); 629 const int numThreads = 5; 630 std::thread threads[numThreads]; 631 632 // Create the threads. 633 for (int i = 0; i < numThreads; ++i) { 634 threads[i] = std::thread(sendMessage, webTagValue, message); 635 } 636 637 // Wait until all threads are detached. 638 for (int i = 0; i < numThreads; ++i) { 639 threads[i].detach(); 640 } 641 return nullptr; 642 } 643 644 // Register a callback in the thread. 645 void setHandler(const char *webTag) { 646 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "setMessageEventHandler in thread"); 647 webMessagePort->setMessageEventHandler(g_web_message_port_arr[1], webTag, WebMessagePortCallback, NULL); 648 } 649 650 static napi_value setMessageEventHandlerThread(napi_env env, napi_callback_info info) { 651 size_t argc = 2; 652 napi_value args[2] = {nullptr}; 653 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 654 655 // Obtain the first parameter webTag. 656 size_t webTagSize = 0; 657 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 658 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 659 size_t webTagLength = 0; 660 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 661 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk Refresh webTag:%{public}s", webTagValue); 662 663 // Register a callback. 664 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk SetMessageEventHandler begin"); 665 if (g_web_message_port_arr == nullptr) { 666 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "webMessagePort is nullptr"); 667 return nullptr; 668 } 669 std::thread thread(setHandler, webTagValue); 670 thread.detach(); 671 webMessagePort->setMessageEventHandler(g_web_message_port_arr[1], webTagValue, WebMessagePortCallback, NULL); 672 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 673 "ndk SetMessageEventHandler end, web message port size:%{public}d", web_message_port_size); 674 return nullptr; 675 } 676 static napi_value postNoneMessage(napi_env env, napi_callback_info info) { 677 size_t argc = 2; 678 napi_value args[2] = {nullptr}; 679 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 680 681 // Obtain the first parameter webTag. 682 size_t webTagSize = 0; 683 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 684 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 685 size_t webTagLength = 0; 686 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 687 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk Refresh webTag:%{public}s", webTagValue); 688 689 // Send a message. 690 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk postMessage begin"); 691 692 if (g_web_message_port_arr == nullptr) { 693 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "webMessagePort is nullptr"); 694 return nullptr; 695 } 696 ArkWeb_WebMessagePtr message = webMessage->createWebMessage(); 697 webMessage->setType(message, ArkWeb_WebMessageType::ARKWEB_NONE); 698 std::string str = "send string from native"; 699 webMessage->setData(message, (void *)str.c_str(), str.length() + 1); 700 webMessagePort->postMessage(g_web_message_port_arr[1], webTagValue, message); 701 webMessage->destroyWebMessage(&message); 702 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk postMessage end, web message port size:%{public}d", 703 web_message_port_size); 704 return nullptr; 705 } 706 707 static napi_value postBufferMessage(napi_env env, napi_callback_info info) { 708 size_t argc = 2; 709 napi_value args[2] = {nullptr}; 710 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 711 712 // Obtain the first parameter webTag. 713 size_t webTagSize = 0; 714 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 715 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 716 size_t webTagLength = 0; 717 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 718 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk Refresh webTag:%{public}s", webTagValue); 719 720 // Send a message. 721 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk postMessage begin"); 722 723 if (g_web_message_port_arr == nullptr) { 724 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "webMessagePort is nullptr"); 725 return nullptr; 726 } 727 ArkWeb_WebMessagePtr message1 = webMessage->createWebMessage(); 728 webMessage->setType(message1, ArkWeb_WebMessageType::ARKWEB_BUFFER); 729 std::string str1 = "send buffer from native"; 730 webMessage->setData(message1, (void *)str1.c_str(), str1.length()); 731 webMessagePort->postMessage(g_web_message_port_arr[1], webTagValue, message1); 732 webMessage->destroyWebMessage(&message1); 733 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk postMessage end, web message port size:%{public}d", 734 web_message_port_size); 735 return nullptr; 736 } 737 738 static napi_value setMessageEventHandler(napi_env env, napi_callback_info info) { 739 size_t argc = 2; 740 napi_value args[2] = {nullptr}; 741 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 742 743 // Obtain the first parameter webTag. 744 size_t webTagSize = 0; 745 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 746 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 747 size_t webTagLength = 0; 748 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 749 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk Refresh webTag:%{public}s", webTagValue); 750 751 // Register a callback. 752 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk SetMessageEventHandler begin"); 753 if (g_web_message_port_arr == nullptr) { 754 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "webMessagePort is nullptr"); 755 return nullptr; 756 } 757 webMessagePort->setMessageEventHandler(g_web_message_port_arr[1], webTagValue, WebMessagePortCallback, NULL); 758 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 759 "ndk SetMessageEventHandler end, web message port size:%{public}d", web_message_port_size); 760 return nullptr; 761 } 762 763 static napi_value closeMessagePort(napi_env env, napi_callback_info info) { 764 size_t argc = 2; 765 napi_value args[2] = {nullptr}; 766 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 767 768 // Obtain the first parameter webTag. 769 size_t webTagSize = 0; 770 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 771 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 772 size_t webTagLength = 0; 773 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 774 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk Refresh webTag:%{public}s", webTagValue); 775 776 // Disable the port by calling close() and then destroyWebMessagePorts(). 777 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk SetMessageEventHandler begin"); 778 if (g_web_message_port_arr == nullptr) { 779 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "webMessagePort is nullptr"); 780 return nullptr; 781 } 782 webMessagePort->close(g_web_message_port_arr[0], webTagValue); 783 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 784 "ndk SetMessageEventHandler end, web message port size:%{public}d", web_message_port_size); 785 controller->refresh(webTagValue); 786 return nullptr; 787 } 788 789 static napi_value destroyMessagePort(napi_env env, napi_callback_info info) { 790 size_t argc = 2; 791 napi_value args[2] = {nullptr}; 792 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 793 794 // Obtain the first parameter webTag. 795 size_t webTagSize = 0; 796 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 797 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 798 size_t webTagLength = 0; 799 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 800 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk Refresh webTag:%{public}s", webTagValue); 801 802 // Release the memory by calling close() and then destroyWebMessagePorts(). 803 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk SetMessageEventHandler begin"); 804 if (g_web_message_port_arr == nullptr) { 805 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ArkWeb", "webMessagePort is nullptr"); 806 return nullptr; 807 } 808 controller->destroyWebMessagePorts(&g_web_message_port_arr, web_message_port_size); 809 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 810 "ndk SetMessageEventHandler end, web message port size:%{public}d", web_message_port_size); 811 return nullptr; 812 } 813 814 static napi_value destroyNullMessagePort(napi_env env, napi_callback_info info) { 815 size_t argc = 2; 816 napi_value args[2] = {nullptr}; 817 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 818 819 // Obtain the first parameter webTag. 820 size_t webTagSize = 0; 821 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize); 822 char *webTagValue = new (std::nothrow) char[webTagSize + 1]; 823 size_t webTagLength = 0; 824 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength); 825 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk Refresh webTag:%{public}s", webTagValue); 826 827 // Release the memory by calling close() and then destroyWebMessagePorts(). 828 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ndk SetMessageEventHandler begin"); 829 830 controller->destroyWebMessagePorts(&g_web_message_port_arr, web_message_port_size); 831 832 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", 833 "ndk SetMessageEventHandler end, web message port size:%{public}d", web_message_port_size); 834 return nullptr; 835 } 836 837 EXTERN_C_START 838 static napi_value Init(napi_env env, napi_value exports) { 839 napi_property_descriptor desc[] = { 840 {"nativeWebInit", nullptr, NativeWebInit, nullptr, nullptr, nullptr, napi_default, nullptr}, 841 {"createWebMessagePorts", nullptr, createWebMessagePorts, nullptr, nullptr, nullptr, napi_default, nullptr}, 842 {"postMessage", nullptr, postMessage, nullptr, nullptr, nullptr, napi_default, nullptr}, 843 {"postNoneMessage", nullptr, postNoneMessage, nullptr, nullptr, nullptr, napi_default, nullptr}, 844 {"postBufferMessage", nullptr, postBufferMessage, nullptr, nullptr, nullptr, napi_default, nullptr}, 845 {"setMessageEventHandler", nullptr, setMessageEventHandler, nullptr, nullptr, nullptr, napi_default, nullptr}, 846 {"closeMessagePort", nullptr, closeMessagePort, nullptr, nullptr, nullptr, napi_default, nullptr}, 847 {"destroyMessagePort", nullptr, destroyMessagePort, nullptr, nullptr, nullptr, napi_default, nullptr}, 848 {"postMessageThread", nullptr, postMessageThread, nullptr, nullptr, nullptr, napi_default, nullptr}, 849 {"setMessageEventHandlerThread", nullptr, setMessageEventHandlerThread, nullptr, nullptr, nullptr, napi_default, 850 nullptr}, 851 {"destroyNullMessagePort", nullptr, destroyNullMessagePort, nullptr, nullptr, nullptr, napi_default, nullptr}, 852 }; 853 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 854 return exports; 855 } 856 EXTERN_C_END 857 858 static napi_module demoModule = { 859 .nm_version = 1, 860 .nm_flags = 0, 861 .nm_filename = nullptr, 862 .nm_register_func = Init, 863 .nm_modname = "entry", 864 .nm_priv = ((void *)0), 865 .reserved = {0}, 866 }; 867 868 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } 869 ``` 870 871<!--no_check-->