移動端最常用&最重要組件之一:WebView(HarmonyOS版)使用指南
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
現(xiàn)在很多APP里都內(nèi)置了Web頁面(比如社交APP、新聞瀏覽類APP),即從APP中跳轉(zhuǎn)到網(wǎng)絡(luò)Web頁面或本地Web頁面,這種方法便于擴展APP應用體驗和更新維護內(nèi)置Web頁面。在HarmonyOS中,開發(fā)者可以通過WebView組件實現(xiàn)上述功能。
WebView組件可用于加載網(wǎng)頁內(nèi)容、獲取頁面詳細信息和控制頁面跳轉(zhuǎn),并實現(xiàn)APP應用與內(nèi)置Web頁面間的交互和通信。
本期Codelab我們將用一個Demo來詳細介紹WebView組件的使用,包括UI界面的創(chuàng)建、WebView組件創(chuàng)建、Web頁面加載方式、APP應用與Web頁面間的交互與通信四個方面內(nèi)容。
在開始敲代碼之前,開發(fā)者們需要先下載安裝Huawei DevEco Studio,可參照官網(wǎng)的指南進行操作:
·Huawei DevEco Studio安裝指南:
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/software_install-0000001053582415
接下來我們來解析本次Demo的代碼結(jié)構(gòu),方便大家做一個初步的了解:
● MainAbilitySlice文件
“MainAbilitySlice”文件在slice文件夾中,主要用于實現(xiàn)Demo邏輯,包括獲取WebView對象,加載頁面和實現(xiàn)Web頁面間的通信及交互。
● DataAbility文件
“DataAbility”文件主要是通過DataAbility訪問WebView加載的本地文件。
● background_button.xml文件
“background_button.xml”文件在graphic文件夾中,主要用于實現(xiàn)Demo中按鈕的背景設(shè)置。
● ability_main.xml文件
“ability_main.xml”文件在layout文件夾中,主要實現(xiàn)WebView組件的創(chuàng)建,同時也進行諸如文本輸入框和按鈕等其他UI界面內(nèi)容的創(chuàng)建。
● text.html文件
“text.html”文件在rawfile文件夾中,是新增本地Web頁面的HTML文件,用于模擬WebView需要加載的本地Web頁面。
● config.json文件
config.json文件是工程相關(guān)配置文件,這里主要用于添加WebView加載Web頁面所需的網(wǎng)絡(luò)權(quán)限申請和DataAbility的聲明。
了解完基本的代碼結(jié)構(gòu),我們正式進入WebView組件的使用。
UI頁面的創(chuàng)建
我們先來創(chuàng)建一個UI界面(如圖1 Demo的UI界面),該界面將包含:
◆ TextField組件,用于接收用戶輸入的網(wǎng)址信息,本Demo中默認網(wǎng)址為
https://www.huawei.com/cn/;
◆ WebView組件,本Demo的重點組件,我們將在“WebView組件創(chuàng)建”中詳細描述;
◆ Button組件,即按鈕組件,本次Demo主界面中涉及5個按鈕組件將實現(xiàn)以下功能:加載Web頁面(Load URL)、Web網(wǎng)頁向后預覽(Go Back)、向前瀏覽(GO Forward)、加載本地HTML頁面(Load Local HTML)和給本地網(wǎng)頁發(fā)信息(Send Message to Local HTML)。
WebView組件創(chuàng)建
WebView派生于通用組件Component,包含基本組件的所有功能,可以像普通組件一樣使用。也就是說,WebView組件同樣可以采用XML形式和代碼形式創(chuàng)建,本次Demo使用的是XML形式:
1. 在"ability_main.xml"文件中創(chuàng)建WebView,示例代碼如下:
- <ohos.agp.components.webengine.WebView
- ohos:id="$+id:webview"
- ohos:height="match_parent"
- ohos:width="match_parent">
- </WebView>
2.在"slice/MainAbilitySlice.java"文件中通過如下方式獲取WebView對象,示例代碼如下:
- WebView webview = (WebView)
- findComponentById(ResourceTable.Id_webview);
當然,開發(fā)者也可以使用代碼形式創(chuàng)建,詳情請參考官網(wǎng):
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ui-java-component-webview-0000001092715158
Web頁面加載
WebView如何加載網(wǎng)絡(luò)Web頁面和本地Web頁面呢?接下來我們將分別進行介紹。
1.WebView加載網(wǎng)絡(luò)Web頁面
加載網(wǎng)絡(luò)Web頁面需要申請網(wǎng)絡(luò)權(quán)限ohos.permission.INTERNET。
我們在config.json中添加如下代碼進行申請:
- module": {
- ……
- "reqPermissions": [
- {
- "name": "ohos.permission.INTERNET"
- }
- ]
- }
完成網(wǎng)絡(luò)申請后,在"MainAbilitySlice.java"文件中通過webview.load(String url)方法訪問具體的網(wǎng)絡(luò)Web頁面,通過WebConfig類對WebView組件進行配置,示例代碼如下:
- WebConfig webConfig = webview.getWebConfig();
- // WebView加載URL,其中urlTextField為輸入URL的TextField組件
- webview.load(urlTextField.getText());
在Web頁面進行鏈接跳轉(zhuǎn)時,WebView默認會打開目標網(wǎng)址,通過WebAgent對象可以捕獲該行為,這里僅使用isNeedLoadUrl根據(jù)當前WebView請求檢查是否加載請求,當URL以"http:"或"https:"開頭,則執(zhí)行加載,示例代碼如下:
- webview.setWebAgent(new WebAgent() {
- @Override
- public boolean isNeedLoadUrl(WebView webView, ResourceRequest request) {
- if (request == null || request.getRequestUrl() == null) {
- LogUtil.info(TAG,"WebAgent isNeedLoadUrl:request is null.");
- return false;
- }
- String url = request.getRequestUrl().toString();
- if (url.startsWith("http:") || url.startsWith("https:")) {
- webView.load(url);
- return false;
- } else {
- return super.isNeedLoadUrl(webView, request);
- }
- }
- });
除此之外,WebAgent對象還提供了相關(guān)的回調(diào)函數(shù)以觀測頁面狀態(tài)的變更,如onLoadingPage、onPageLoaded、onError等方法,用于頁面“開始加載”、“停止加載”、“加載錯誤”時的調(diào)用,詳情可見官網(wǎng)WebAgent參考。
·官網(wǎng):WebAgent參考
https://developer.harmonyos.com/cn/docs/documentation/doc-references/webagent-0000001078160526
同時,WebView提供Navigator類進行歷史記錄的瀏覽和處理,開發(fā)者可通過getNavigator()方法獲取該類的對象,使用canGoBack()或canGoForward()方法檢查是否可以向后或向前瀏覽,使用goBack()或goForward()方法實現(xiàn)向后或向前瀏覽,示例代碼如下:
- Navigator navigator = webView.getNavigator();
- if (navigator.canGoBack()) {
- navigator.goBack();
- }
- if (navigator.canGoForward()) {
- navigator.goForward();
- }
2.WebView加載本地Web頁面
出于安全考慮,WebView不支持直接通過File協(xié)議加載資源文件或本地文件。如開發(fā)者需實現(xiàn)相關(guān)業(yè)務,HarmonyOS提供兩種方式:通過processResourceRequest方法訪問文件和通過Data Ability訪問文件。
在本Demo中,我們將重點講述Data Ability訪問文件的形式,大家可以通過官網(wǎng)了解processResourceRequest方法的實現(xiàn)~
·官網(wǎng):加載資源文件或本地文件
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ui-java-component-webview-0000001092715158
本次Demo中,我們將自行創(chuàng)建一個HTML文件,放在"resources/rawfile/"目錄下并將其命名為text.html。除了HTML文件常見的固定內(nèi)容,我們還將在其中加入<button>標簽,用于生成按鈕“調(diào)用Java方法”和添加<script >插入一段JavaScript內(nèi)容,示例代碼如下:
- <!DOCTYPE html>
- <html>
- <meta charset="UTF-8">
- <title>本地html</title>
- <body onload="hello">
- <br>
- <h1 id="helloName">這是一個本地HTML頁面</h1>
- <br>
- <button id="button" onclick="sendData()" style="background-color:#70DBDB;height:30px;">調(diào)用Java方法</button>
- <script type="text/javascript">
- …….// 省略部分為應用調(diào)用Web頁面及/ Web頁面調(diào)用應用內(nèi)容,我們將在后續(xù)講解
- </script>
- </body>
- </html>
創(chuàng)建完本地Web頁面,我們來看看WebView如何通過DataAbility加載本地Web頁面。如果不了解DataAbility的具體使用方法,可以參考官網(wǎng)鏈接。
·官網(wǎng):DataAbility
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ability-data-concept-0000000000043058
1)我們新建一個DataAbility。注意使用DataAbility之前需要先完成聲明,我們在"entry\src\main\config.json"中完成,示例代碼如下:
- module": {
- ……
- "abilities": [
- {
- "name": "com.huawei.codelab.DataAbility",
- "type": "data",
- "uri": "dataability://com.huawei.codelab.DataAbility"
- }
- ]
- }
2)通過openRawFile(Uri uri, String mode)方法,完成WebView對本地Web頁面的訪問,示例代碼如下:
- public class DataAbility extends Ability {
- ...
- @Override
- public RawFileDescriptor openRawFile(Uri uri, String mode) throws FileNotFoundException {
- if (uri == null) {;
- return super.openRawFile(uri, mode);
- }
- String path = uri.getEncodedPath();
- int splitIndex = path.indexOf('/', 1);
- String providerName = Uri.decode(path.substring(1, splitIndex));
- String rawFilePath = Uri.decode(path.substring(splitIndex + 1));
- RawFileDescriptor rawFileDescriptor = null;
- try {
- rawFileDescriptor = getResourceManager().getRawFileEntry(rawFilePath).openRawFileDescriptor();
- } catch (IOException e) {
- // 異常處理
- }
- return rawFileDescriptor;
- }
- }
3)在"slice/MainAbilitySlice.java"中聲明需要訪問的文件路徑,通過webview.load(String url)方法加載本地Web頁面,可以通過WebConfig類的對象對WebView訪問DataAbility的能力進行配置,示例代碼如下:
- private static final String URL_LOCAL = "dataability://com.huawei.codelab.DataAbility/resources/rawfile/test.html";
- // 配置是否支持訪問DataAbility資源,默認為true
- webConfig.setDataAbilityPermit(true);
- webview.load(URL_LOCAL);
APP應用與Web頁面間的通信與交互
APP應用和內(nèi)置Web頁面其實是相互獨立的,彼此之間是相互隔斷的,它們需要通過WebVeiw組件實現(xiàn)相互調(diào)用,來完成諸如獲取信息、接收彈窗、關(guān)閉彈窗等功能。
這個時候需要APP應用和Web頁面之間進行通信與交互,那具體是如何實現(xiàn)的,讓我們以本地Web頁面"text.html"為例來介紹一下。
首先我們需要對WebView組件中的WebConfig對象進行配置,使APP應用能與Web頁面中的JavaScript腳本交互,在MainAbilitySlice中實現(xiàn),示例代碼如下:
- // 配置是否支持JavaScript,默認值為false
- webConfig.setJavaScriptPermit(true);
1.APP應用調(diào)用本地Web頁面
我們先來介紹一下APP應用調(diào)用Web頁面的情況。在" text.html"文件中編寫callJS方法,待APP應用調(diào)用,示例代碼如下
- <script type="text/javascript">
- // 應用調(diào)用Web頁面
- function callJS(message) {
- alert(message);
- }
- </script>
在"slice/MainAbilitySlice.java"中實現(xiàn)APP應用對Web頁面JavaScript的調(diào)用,示例代碼如下:
- webview.executeJs("javascript:callJS('這是來自JavaSlice的消息')", msg -> {
- // 在這里處理Js方法的返回值
- });
當我們點擊“Send Message to Local HTML”按鈕時呈現(xiàn)效果如圖2所示:
我們還可以通過setBrowserAgent方法設(shè)置自定義BrowserAgent對象,以觀測JavaScript事件及通知等,通過復寫onJsMessageShow方法來接管Web頁面彈出Alert對話框的事件,示例代碼如下:
- webview.setBrowserAgent(new BrowserAgent(this) {
- @Override
- public boolean onJsMessageShow(WebView webView, String url, String message, boolean isAlert, JsMessageResult result) {
- LogUtil.info(TAG,"BrowserAgent onJsMessageShow : " + message);
- if (isAlert) {
- // 將Web頁面的alert對話框改為ToastDialog方式提示
- new ToastDialog(getApplicationContext()).setText(message).setAlignment(LayoutAlignment.CENTER).show();
- // 對彈框進行確認處理
- result.confirm();
- return true;
- } else {
- return super.onJsMessageShow(webView, url, message, isAlert, result);
- }
- }
- });
2.本地Web頁面使用JavaScript調(diào)用App應用
在" text.html"中編寫按鈕,實現(xiàn)Web頁面JavaScript對App應用的調(diào)用,示例代碼如下:
- <body>
- ......
- <button id="button" onclick="sendData()" style="background-color:#70DBDB;height:30px;">調(diào)用Java方法</button>
- <script type="text/javascript">
- function sendData() {
- if (window.JsCallJava && window.JsCallJava.call) {
- // Web頁面調(diào)用應用
- var rst = window.JsCallJava.call("這個是來自本地Web頁面的消息");
- } else {
- alert('發(fā)送消息給WebviewSlice失敗');
- }
- }
- </script>
- </body>
在"slice/MainAbilitySlice.java"中實現(xiàn)APP應用對JavaScript發(fā)起的調(diào)用的響應,示例代碼如下:
- private static final String JS_NAME = "JsCallJava";
- webview.addJsCallback(JS_NAME, str -> {
- // 處理接收到的JavaScript發(fā)送來的消息,本教程通過ToastDialog提示確認收到Web頁面發(fā)來的消息
- new ToastDialog(this).setText(str).setAlignment(LayoutAlignment.CENTER).show();
- // 返回給JavaScript
- return "Js Call Java Success";
- });
當" text.html"頁面中的“調(diào)用Java方法”按鈕被點擊時,呈現(xiàn)效果如圖3:
至此,我們通過一個Demo學習了如何使用WebView組件創(chuàng)建UI界面、Web頁面加載方式、APP應用與Web頁面間的通信及交互。當然以上只是基礎(chǔ)操作,更多場景應用及創(chuàng)新需要開發(fā)者們的奇思妙想,期待你的腦洞大開~
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)