移動端最常用&最重要組件之一:WebView(HarmonyOS版)使用指南
現在很多APP里都內置了Web頁面(比如社交APP、新聞瀏覽類APP),即從APP中跳轉到網絡Web頁面或本地Web頁面,這種方法便于擴展APP應用體驗和更新維護內置Web頁面。在HarmonyOS中,開發者可以通過WebView組件實現上述功能。
WebView組件可用于加載網頁內容、獲取頁面詳細信息和控制頁面跳轉,并實現APP應用與內置Web頁面間的交互和通信。
本期Codelab我們將用一個Demo來詳細介紹WebView組件的使用,包括UI界面的創建、WebView組件創建、Web頁面加載方式、APP應用與Web頁面間的交互與通信四個方面內容。
在開始敲代碼之前,開發者們需要先下載安裝Huawei DevEco Studio,可參照官網的指南進行操作:
·Huawei DevEco Studio安裝指南:
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/software_install-0000001053582415
接下來我們來解析本次Demo的代碼結構,方便大家做一個初步的了解:
● MainAbilitySlice文件
“MainAbilitySlice”文件在slice文件夾中,主要用于實現Demo邏輯,包括獲取WebView對象,加載頁面和實現Web頁面間的通信及交互。
● DataAbility文件
“DataAbility”文件主要是通過DataAbility訪問WebView加載的本地文件。
● background_button.xml文件
“background_button.xml”文件在graphic文件夾中,主要用于實現Demo中按鈕的背景設置。
● ability_main.xml文件
“ability_main.xml”文件在layout文件夾中,主要實現WebView組件的創建,同時也進行諸如文本輸入框和按鈕等其他UI界面內容的創建。
● text.html文件
“text.html”文件在rawfile文件夾中,是新增本地Web頁面的HTML文件,用于模擬WebView需要加載的本地Web頁面。
● config.json文件
config.json文件是工程相關配置文件,這里主要用于添加WebView加載Web頁面所需的網絡權限申請和DataAbility的聲明。
了解完基本的代碼結構,我們正式進入WebView組件的使用。
UI頁面的創建
我們先來創建一個UI界面(如圖1 Demo的UI界面),該界面將包含:
◆ TextField組件,用于接收用戶輸入的網址信息,本Demo中默認網址為
https://www.huawei.com/cn/;
◆ WebView組件,本Demo的重點組件,我們將在“WebView組件創建”中詳細描述;
◆ Button組件,即按鈕組件,本次Demo主界面中涉及5個按鈕組件將實現以下功能:加載Web頁面(Load URL)、Web網頁向后預覽(Go Back)、向前瀏覽(GO Forward)、加載本地HTML頁面(Load Local HTML)和給本地網頁發信息(Send Message to Local HTML)。
WebView組件創建
WebView派生于通用組件Component,包含基本組件的所有功能,可以像普通組件一樣使用。也就是說,WebView組件同樣可以采用XML形式和代碼形式創建,本次Demo使用的是XML形式:
1. 在"ability_main.xml"文件中創建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);
當然,開發者也可以使用代碼形式創建,詳情請參考官網:
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ui-java-component-webview-0000001092715158
Web頁面加載
WebView如何加載網絡Web頁面和本地Web頁面呢?接下來我們將分別進行介紹。
1.WebView加載網絡Web頁面
加載網絡Web頁面需要申請網絡權限ohos.permission.INTERNET。
我們在config.json中添加如下代碼進行申請:
- module": {
- ……
- "reqPermissions": [
- {
- "name": "ohos.permission.INTERNET"
- }
- ]
- }
完成網絡申請后,在"MainAbilitySlice.java"文件中通過webview.load(String url)方法訪問具體的網絡Web頁面,通過WebConfig類對WebView組件進行配置,示例代碼如下:
- WebConfig webConfig = webview.getWebConfig();
- // WebView加載URL,其中urlTextField為輸入URL的TextField組件
- webview.load(urlTextField.getText());
在Web頁面進行鏈接跳轉時,WebView默認會打開目標網址,通過WebAgent對象可以捕獲該行為,這里僅使用isNeedLoadUrl根據當前WebView請求檢查是否加載請求,當URL以"http:"或"https:"開頭,則執行加載,示例代碼如下:
- 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對象還提供了相關的回調函數以觀測頁面狀態的變更,如onLoadingPage、onPageLoaded、onError等方法,用于頁面“開始加載”、“停止加載”、“加載錯誤”時的調用,詳情可見官網WebAgent參考。
·官網:WebAgent參考
https://developer.harmonyos.com/cn/docs/documentation/doc-references/webagent-0000001078160526
同時,WebView提供Navigator類進行歷史記錄的瀏覽和處理,開發者可通過getNavigator()方法獲取該類的對象,使用canGoBack()或canGoForward()方法檢查是否可以向后或向前瀏覽,使用goBack()或goForward()方法實現向后或向前瀏覽,示例代碼如下:
- Navigator navigator = webView.getNavigator();
- if (navigator.canGoBack()) {
- navigator.goBack();
- }
- if (navigator.canGoForward()) {
- navigator.goForward();
- }
2.WebView加載本地Web頁面
出于安全考慮,WebView不支持直接通過File協議加載資源文件或本地文件。如開發者需實現相關業務,HarmonyOS提供兩種方式:通過processResourceRequest方法訪問文件和通過Data Ability訪問文件。
在本Demo中,我們將重點講述Data Ability訪問文件的形式,大家可以通過官網了解processResourceRequest方法的實現~
·官網:加載資源文件或本地文件
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ui-java-component-webview-0000001092715158
本次Demo中,我們將自行創建一個HTML文件,放在"resources/rawfile/"目錄下并將其命名為text.html。除了HTML文件常見的固定內容,我們還將在其中加入<button>標簽,用于生成按鈕“調用Java方法”和添加<script >插入一段JavaScript內容,示例代碼如下:
- <!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;">調用Java方法</button>
- <script type="text/javascript">
- …….// 省略部分為應用調用Web頁面及/ Web頁面調用應用內容,我們將在后續講解
- </script>
- </body>
- </html>
創建完本地Web頁面,我們來看看WebView如何通過DataAbility加載本地Web頁面。如果不了解DataAbility的具體使用方法,可以參考官網鏈接。
·官網: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應用和內置Web頁面其實是相互獨立的,彼此之間是相互隔斷的,它們需要通過WebVeiw組件實現相互調用,來完成諸如獲取信息、接收彈窗、關閉彈窗等功能。
這個時候需要APP應用和Web頁面之間進行通信與交互,那具體是如何實現的,讓我們以本地Web頁面"text.html"為例來介紹一下。
首先我們需要對WebView組件中的WebConfig對象進行配置,使APP應用能與Web頁面中的JavaScript腳本交互,在MainAbilitySlice中實現,示例代碼如下:
- // 配置是否支持JavaScript,默認值為false
- webConfig.setJavaScriptPermit(true);
1.APP應用調用本地Web頁面
我們先來介紹一下APP應用調用Web頁面的情況。在" text.html"文件中編寫callJS方法,待APP應用調用,示例代碼如下
- <script type="text/javascript">
- // 應用調用Web頁面
- function callJS(message) {
- alert(message);
- }
- </script>
在"slice/MainAbilitySlice.java"中實現APP應用對Web頁面JavaScript的調用,示例代碼如下:
- webview.executeJs("javascript:callJS('這是來自JavaSlice的消息')", msg -> {
- // 在這里處理Js方法的返回值
- });
當我們點擊“Send Message to Local HTML”按鈕時呈現效果如圖2所示:
我們還可以通過setBrowserAgent方法設置自定義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調用App應用
在" text.html"中編寫按鈕,實現Web頁面JavaScript對App應用的調用,示例代碼如下:
- <body>
- ......
- <button id="button" onclick="sendData()" style="background-color:#70DBDB;height:30px;">調用Java方法</button>
- <script type="text/javascript">
- function sendData() {
- if (window.JsCallJava && window.JsCallJava.call) {
- // Web頁面調用應用
- var rst = window.JsCallJava.call("這個是來自本地Web頁面的消息");
- } else {
- alert('發送消息給WebviewSlice失敗');
- }
- }
- </script>
- </body>
在"slice/MainAbilitySlice.java"中實現APP應用對JavaScript發起的調用的響應,示例代碼如下:
- private static final String JS_NAME = "JsCallJava";
- webview.addJsCallback(JS_NAME, str -> {
- // 處理接收到的JavaScript發送來的消息,本教程通過ToastDialog提示確認收到Web頁面發來的消息
- new ToastDialog(this).setText(str).setAlignment(LayoutAlignment.CENTER).show();
- // 返回給JavaScript
- return "Js Call Java Success";
- });
當" text.html"頁面中的“調用Java方法”按鈕被點擊時,呈現效果如圖3:
至此,我們通過一個Demo學習了如何使用WebView組件創建UI界面、Web頁面加載方式、APP應用與Web頁面間的通信及交互。當然以上只是基礎操作,更多場景應用及創新需要開發者們的奇思妙想,期待你的腦洞大開~