1# Web Development 2 3 4## How do HTML5 pages interact with ArkTS? (API version 10) 5 6**Problem** 7 8Currently, **javaScriptProxy** supports only synchronous invoking. This means that no execution results can be obtained for asynchronous invoking. 9 10**Solution** 11 12Encapsulate **javaScriptProxy** and **runJavaScript** to implement the JSBridge communication scheme. This method is applicable to the scenario where HTML5 calls native functions. Use the **Web** component **javaScriptProxy** to inject the native API to the window object of HTML5 pages, use the **runJavaScript** API to execute the JS script on HTML5 pages, and obtain the script execution result from the callback. The following figure shows the invoking process. 13 14 15 16- Use the **javaScriptProxy** attribute of the **Web** component to register the **JSBridgeHandle** object with the HTML5 window as the native channel for HTML5 to call. When the HTML5 page starts to be loaded, the **initJSBridge()** method is called in the **onPageBegin** callback to initialize the JSBridge. 17 ``` 18 // javaScriptProxy object 19 public get javaScriptProxy() { 20 return { 21 object: { 22 call: this.call 23 }, 24 name: "JSBridgeHandle", 25 methodList: ['call'], 26 controller: this.controller, 27 } 28 } 29 ``` 30 31 ``` 32 // Use the <Web> component to load the HTML5 page. 33 @Component 34 struct JsProxy { 35 private controller: WebviewController = new WebView.WebviewController() 36 private jsBridge: JSBridge = new JSBridge(this.controller) 37 build() { 38 Column(){ 39 Web({ src: $rawfile('index.html'), controller: this.controller }) 40 .javaScriptProxy(this.jsBridge.javaScriptProxy) 41 .onPageBegin(() => { 42 this.jsBridge.initJSBridge() 43 }) 44 } 45 } 46 } 47 ``` 48 49- In the **initJSBridge** method, use **webviewControll.runJavaScript()** to inject the JSBridge initialization script into the HTML5 page for execution. When HTML5 is called, the **window.callID** is generated to identify the callback function, and then the callID and request parameters are transferred to the native side using **JSBridgeHandle.call**. Use **JSBridgeCallback** to receive the execution result from the native side, find the callback based on the ID and execute it, and then free the memory. 50 ``` 51 // bridgeKey and bridgeMethod dynamically generate the entry for invoking on the HTML5 side. 52 bridgeKey: string = 'JSBridge' 53 bridgeMethod: string = 'call' 54 // Inject the initialization script to the HTML5 side. 55 public initJSBridge() { 56 try { 57 this.controller.runJavaScript(` 58 // Receive the result from the native side and execute callback. 59 function JSBridgeCallback(id, params){ 60 window.JSBridgeMap[id](params) 61 }; 62 // Declare the invoking entry. 63 window.${this.bridgeKey} = { 64 ${this.bridgeMethod}(method, params, callback){ 65 window.JSBridgeMap[id] = callback || (() => {}); 66 JSBridgeHandle.call(method, JSON.stringify(paramsObj)); 67 }, 68 }`) 69 } 70 } 71 ``` 72 73- **JSBridgeHandle.call()** is the unified entry for HTML5 to call native APIs. In this method, find the matching API to call based on the name of the method called by HTML5. After the call is complete, use the **this.callback()** method to return the result to HTML5. In the callback, use **webviewControll.runJavaScript()** to call **JSBridgeCallback** of HTML5 to return the **callID** and result. 74 ``` 75 // The call method calls the native method and receives the result. 76 private call = (fun, params) => { 77 try { 78 const paramsObj = JSON.parse(params) 79 const events = this.exposeManage.methodMap.get(fun) 80 const results = [] 81 events.forEach(callFun => { 82 results.push(callFun(paramsObj.data)) 83 }) 84 Promise.all(results.filter(i => !!i)).then(res => { 85 this.callback(paramsObj.callID, res.length > 1 ? res : res[0]) 86 }) 87 } 88 } 89 90 // Use runJavaScript to call JSBridgeCallback to execute the callback. 91 private callback(id, data) { 92 this.controller.runJavaScript(`__JSBridgeCallback__("${id}", ${JSON.stringify(data)})`); 93 } 94 ``` 95 96 97## How does the return result of onUrlLoadIntercept affect onInterceptRequest in the Web component? (API version 9) 98 99**Solution** 100 101The operation that follows **onUrlLoadIntercept** is subject to its return result. 102 103- If **true** is returned, the URL request is intercepted. 104 105- If **false** is returned , the **onInterceptRequest** callback is performed. 106 107**Reference** 108 109[onUrlloadIntercept](../reference/apis-arkweb/ts-basic-components-web.md#onurlloadinterceptdeprecated) 110 111 112## What should I do if the onKeyEvent event of the Web component is not triggered as expected? (API version 9) 113 114**Problem** 115 116The **onKeyEvent** event is set for the **Web** component to listen for keyboard events. However, it is not triggered when a key is pressed or lifted. 117 118**Solution** 119 120Currently, the **Web** component does not support the **onKeyEvent** event. To listen for keyboard events for the **Web** component, you can use the **onInterceptKeyEvent** callback function. 121 122**Reference** 123 124[onInterceptKeyEvent](../reference/apis-arkweb/ts-basic-components-web.md#oninterceptkeyevent9) 125 126 127## What should I do if page loading fails when onInterceptRequest is called? (API version 9) 128 129**Problem** 130 131The **onInterceptRequest** API intercepts URLs specified by **src** and returns the custom HTML file. However, the content in the **script** tag in the HTML file is not loaded. 132 133**Solution** 134 135If only **setResponseData** is set for the interceptor, the kernel cannot identify the HTML file. You must also set parameters such as **setResponseEncoding**, **setResponseMimeType**, and **setResponseHeader** for the kernel to identify the HTML file. 136 137**Example** 138 139``` 140Web({ src: 'www.example.com', controller: this.controller }) 141 .onInterceptRequest((event) => { 142 console.log('url:' + event.request.getRequestUrl()) 143 this.responseweb = new WebResourceResponse(); 144 var head1:Header = { 145 headerKey:"Connection", 146 headerValue:"keep-alive" 147 } 148 var length = this.heads.push(head1) 149 this.responseweb.setResponseHeader(this.heads) 150 this.responseweb.setResponseData(this.webdata) 151 this.responseweb.setResponseEncoding('utf-8') 152 this.responseweb.setResponseMimeType('text/html') 153 this.responseweb.setResponseCode(200) 154 this.responseweb.setReasonMessage('OK') 155 return this.responseweb 156}) 157``` 158 159**Reference** 160 161[WebResourceResponse](../reference/apis-arkweb/ts-basic-components-web.md#webresourceresponse) 162 163 164## How do I execute JS functions in HTML in ArkTS code? (API version 9) 165 166**Solution** 167 168Use the **runJavaScript** API in **WebviewController** to asynchronously execute JavaScript scripts and obtain the execution result in a callback. 169 170> **NOTE** 171> **runJavaScript** can be invoked only after **loadUrl** is executed. For example, it can be invoked in **onPageEnd**. 172 173**Reference** 174 175[runJavaScript](../reference/apis-arkweb/js-apis-webview.md#runjavascript) 176 177 178## How do I invoke an ArkTS method on a local web page? (API version 9) 179 180**Solution** 181 1821. Prepare an HTML file. Below is the sample code: 183 184 ``` 185 <!DOCTYPE html> 186 <html lang="en"> 187 <head> 188 <meta charset="UTF-8"> 189 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 190 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 191 <title>Document</title> 192 </head> 193 <body> 194 <h1>Title</h1> 195 <h5 id="h5"></h5> 196 <h5 id = "h6"></h5> 197 <button onclick="handleFromH5">Invoke ArkTS method </button> 198 <script type="text/javascript"> 199 function handleFromH5(){ 200 let result = window.objName.test(); 201 document.getElementById('h6').innerHTML = result; 202 } 203 </script> 204 </body> 205 </html> 206 ``` 207 2082. Use the **JavaScriptProxy** API in ArkTs to register the object in ArkTS with the window object of HTML5, and then use the window object to call the method in HTML5. In the following example, the **testObj** object in ArkTS is registered with the HTML5 window object under the alias **objName**. In HTML5, **window.objName** can then be used to access the object. 209 210 ``` 211 // xxx.ets 212 import web_webview from '@ohos.web.webview' 213 @Entry 214 @Component 215 struct Index { 216 @State message: string = 'Hello World' 217 controller: web_webview.WebviewController = new web_webview.WebviewController() 218 testObj = { 219 test: (data1, data2, data3) => { 220 console.log("data1:" + data1); 221 console.log("data2:" + data2); 222 console.log("data3:" + data3); 223 return "AceString"; 224 }, 225 toString: () => { 226 console.log('toString' + "interface instead."); 227 } 228 } 229 build() { 230 Row() { 231 Column() { 232 Web({ src:$rawfile('index.html'), controller:this.controller }) 233 .javaScriptAccess(true) 234 .javaScriptProxy({ 235 object: this.testObj, 236 name: "objName", 237 methodList: ["test", "toString"], 238 controller: this.controller, 239 }) 240 } 241 .width('100%') 242 } 243 .height('100%') 244 } 245 } 246 ``` 247 248**Reference** 249 250[javaScriptProxy](../reference/apis-arkweb/ts-basic-components-web.md#javascriptproxy) 251 252 253## How do I set the domStorageAccess attribute of the Web component? (API version 9) 254 255**Solution** 256 257The **domStorageAccess** attribute sets whether to enable the DOM Storage API. By default, this feature is disabled. 258 259**Reference** 260 261[domStorageAccess](../reference/apis-arkweb/ts-basic-components-web.md#domstorageaccess) 262 263 264## What should I do if the network status fails to be detected on the loaded HTML page? (API version 9) 265 266**Problem** 267 268When **window.navigator.onLine** is used on the HTML page to obtain the network status, the value is **false** no matter the network connection is set up or not. 269 270**Solution** 271 272Configure the permission for the application to obtain network information: ohos.permission.GET_NETWORK_INFO 273 274**Reference** 275 276[GET\_NETWORK\_INFO](../security/AccessToken/permissions-for-all.md#ohospermissionget_network_info) 277 278 279## How do I set the UserAgent parameter through string concatenation? (API version 9) 280 281**Solution** 282 283By default, the value of **UserAgent** needs to be obtained through the WebviewController. Specifically, it is obtained by calling the **getUserAgent** API in a **WebviewController** object after it is bound to the **Web** component. Therefore, to set **UserAgent** through string concatenation before page loading: 284 2851. Use @State to define the initial **UserAgent** and bind it to the **Web** component. 286 2872. In the **onUrlLoadIntercept** callback of the **Web** component, use **WebviewController.getUserAgent()** to obtain the default **UserAgent** and update the bound **UserAgent**. 288 289**Example** 290 291``` 292import web_webview from '@ohos.web.webview' 293@Entry 294@Component 295struct Index { 296 private controller: web_webview.WebviewController = new web_webview.WebviewController() 297 @State userAgentPa: string = '' 298 build() { 299 Row() { 300 Column() { 301 Web({ src: 'http://www.example.com', controller: this.controller }) // Replace the URL with the actual URL. 302 .width('100%') 303 .userAgent(this.userAgentPa) 304 .onUrlLoadIntercept((event) => { 305 let userAgent = this.controller.getUserAgent(); 306 this.userAgentPa = userAgent + ' 111111111' 307 return false; 308 }) 309 } 310 .width('100%') 311 } 312 .height('100%') 313 } 314} 315``` 316 317**Reference** 318 319[userAgent](../reference/apis-arkweb/ts-basic-components-web.md#useragentdeprecated), [getUserAgent](../reference/apis-arkweb/js-apis-webview.md#getuseragent) 320 321 322## How do I enable the Web component to return to the previous web page following a swipe gesture? (API version 9) 323 324**Solution** 325 326Override the **onBackPress** API to define the return logic and use **WebviewController** to determine whether to return to the previous web page. 327 328**Example** 329 330``` 331import web_webview from '@ohos.web.webview'; 332@Entry 333@Component 334struct Index { 335 controller: web_webview.WebviewController = new web_webview.WebviewController(); 336 build() { 337 Column() { 338 Web({ src: 'http://www.example.com', controller: this.controller })// Replace the URL with the actual URL. 339 } 340 } 341 onBackPress() { 342 // Check whether a specific number of steps forward or backward can be performed on the current page. A positive number indicates forward, and a negative number indicates backward. 343 if (this.controller.accessStep(-1)) { 344 this.controller.backward(); // Return to the previous web page. 345 // Execute the custom return logic. 346 return true 347 } else { 348 // Execute the default return logic to return to the previous page. 349 return false 350 } 351 } 352} 353``` 354 355**Reference** 356 357[accessStep](../reference/apis-arkweb/js-apis-webview.md#accessstep) 358 359 360## Does WebView support same-layer rendering (API version 10)? 361 362**Solution** 363 3641. **WebView**, **Video**, **Map**, **Camera**, **Canvas**, and **WebGL** all support same-layer rendering. 3652. The **id**, **type**, **src**, **width**, **height**, and **url** attributes of web embedded tags can be transferred to native components. 366 367 368## What debugging tools does WebView provide? How do I use them? (API version 10) 369 370**Solution** 371 372The **Web** component supports debugging of web frontend pages by using DevTools, a web frontend development and debugging tool that allows you to debug an application's frontend pages on a PC. Before you do this, use **setWebDebuggingAccess()** to enable frontend page debugging for the **Web** component and make sure the test device connected to the 2-in-1 device runs 4.1.0 or a later version. 373 374**Reference** 375 376[Debugging Frontend Pages by Using DevTools](../web/web-debugging-with-devtools.md) 377 378 379## How do I use WebView to implement request interception? (API version 10) 380 381**Solution** 382 383You can call **onInterceptRequest()** to customize web page responses, file resource responses, and more. When a resource loading request is initiated on a web page, the application layer will receive the request. The application layer then constructs a local resource response and sends it to the web kernel. On receiving the response, the web kernel parses the response and loads page resources accordingly. 384 385**Reference** 386 387[Customizing Page Request Responses](../web/web-resource-interception-request-mgmt.md) 388 389 390## How does WebView communicate with the native side? (API version 10) 391 392**Solution** 393 3941. For communication from the native side to the HTML5 side, use the **runJavaScript** API. For communication from the HTML5 side to the native side, use the **registerJavaScriptProy** API. Register the native method with the HTML5 side, and then from the HTML5 side call the frontend method to communicate with the native side. 3952. Both **runJavaScript** and **registerJavaScriptProy** are exposed in the C API on the NDK side. 3963. The **onInterceptrequest** API is used to intercept requests from the HTML5 side and return native data as a response to the HTML5 side. In this way, the implement communication between the native side and HTML5 side is implemented. 397 398**Reference** 399 400[runJavaScript](../reference/apis-arkweb/js-apis-webview.md#runjavascriptext10), [registerJavaScriptProxy](../reference/apis-arkweb/js-apis-webview.md#registerjavascriptproxy), [javaScriptProxy](../reference/apis-arkweb/ts-basic-components-web.md#javascriptproxy), [onInterceptRequest](../reference/apis-arkweb/ts-basic-components-web.md#oninterceptrequest9) 401 402 403## What are the WebView process model and rendering mechanism? (API version 11) 404 405**Solution** 406 4071. Process model: one main process and multiple render processes 4082. Rendering mechanism: web self-rendering 409 410 411## Does the system support WebRTC? What WebRTC features are provided? 412 413**Solution** 414 4151. WebView provides the peer-to-peer (P2P) and audio and video streaming features in WebRTC. 4162. When WebView is not used, the system provides technical support for adaptation, but not direct support for WebRTC. For example, the following are provided to work with WebRTC (RR-30030985): 417 * GN + Ninja cross compilation mode in the SDK 418 * Compilation samples 419 420 421## How do I set the mixed content policy in WebView to load HTTP and HTTPS mixed content? 422 423**Solution** 424 425WebView provides the **mixedMode(mixedMode: MixedMode)** API for specifying whether to enable loading of HTTP and HTTPS mixed content. By default, loading of mixed content is disabled. 426 427**Reference** 428 429[mixedmode](../reference/apis-arkweb/ts-basic-components-web.md#mixedmode) 430 431 432## In addition to setting the cache, is there any other way to speed up rendering in WebView? 433 434**Solution** 435 436You can use the **prepareForPageLoad** API to preconnect to a URL. 437 438**Reference** 439 440[prepareforpageload](../reference/apis-arkweb/js-apis-webview.md#prepareforpageload10) 441 442 443## How do I create a Web component? How do I reuse one? 444 445**Solution** 446 447**Web** components can be pre-created, reclaimed, and reused through dynamic component tree mount and unmount capability provided by ArkUI. 448 449**Reference** 450 451[Dynamically Creating Web Components](../web/web-page-loading-with-web-components.md#dynamically-creating-web-components) 452 453 454## Does OpenHarmony provide JavaScript engine capabilities as other systems? 455 456**Solution** 457 458Yes. For details, see the reference. 459 460**Reference** 461 462[JSVM](../reference/common/_j_s_v_m.md) 463<!--no_check-->