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![image5](figures/image5.png)
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-->