4.7【HarmonyOS 鸿蒙开发】组件 WebView
作者:韩茹
公司:程序咖(北京)科技有限公司
鸿蒙巴士专栏作家
WebView 提供在利用中集成 Web 页面的能力。
阐明
- 请应用真机或模拟器运行查看 WebView 成果,预览器不反对 WebView 显示。
- 只有预置 WebView 能力的真机设备才反对 WebView 性能。具体请以理论设施反对状况为准。智能穿戴设施不反对 WebView。
一、WebView 的应用办法
WebView 派生于通用组件 Component,能够像一般组件一样进行应用。
形式一:
1、在 layout 目录下的 xml 文件中创立 WebView。
<ohos.agp.components.webengine.WebView
ohos:id="$+id:webview"
ohos:height="match_parent"
ohos:width="match_parent">
</ohos.agp.components.webengine.WebView>
2、在 MainAbility.java 文件中,应用 load 办法加载 Web 页面。
package com.example.hanruwebview.slice;
import com.example.hanruwebview.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.webengine.WebView;
public class MainAbilitySlice extends AbilitySlice {
private static final String EXAMPLE_URL="https://www.harmonybus.net/";
@Override
public void onStart(Intent intent) {super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
// 加载 WebView
WebView webView = (WebView) findComponentById(ResourceTable.Id_webview1);
webView.getWebConfig() .setJavaScriptPermit(true); // 如果网页须要应用 JavaScript,减少此行;如何应用 JavaScript 下文有具体介绍
final String url = EXAMPLE_URL; // EXAMPLE_URL 由开发者自定义
webView.load(url);
}
}
因为咱们要关上网络,须要网络拜访,那么就须要进行网络受权,在 config.json 文件中增加以下受权信息:
"reqPermissions": [
{"name": "ohos.permission.INTERNET"}
]
构造如下:
这里咱们关上的是鸿蒙巴士主页:
<img src=”https://img.chengxuka.com/WX20210616-151915@2x.png/mark” alt=”WX20210616-151915@2x” style=”zoom:50%;” />
形式二:
1、在 ComponentContainer 中创立 WebView。
咱们将 Layout 目录下新建一个 xml 布局文件:layout_webview_demo.xml,咱们不须要增加任何控件,只有在根布局中增加 id 属性即可。
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:id="$+id:directionallayout1"
ohos:orientation="vertical">
</DirectionalLayout>
而后在在 slice 目录下新建一个 AbilitySlice,SecondAbilitySlice.java
package com.example.hanruwebview.slice;
import com.example.hanruwebview.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.webengine.WebView;
public class SecondAbilitySlice extends AbilitySlice {
private static final String EXAMPLE_URL="https://www.baidu.com/";
@Override
protected void onStart(Intent intent) {super.onStart(intent);
super.setUIContent(ResourceTable.Layout_layout_webview_demo);
// 办法二:WebView webView = new WebView(getContext());
webView.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);
webView.setHeight(ComponentContainer.LayoutConfig.MATCH_PARENT);
webView.getWebConfig() .setJavaScriptPermit(true); // 如果网页须要应用 JavaScript,减少此行;如何应用 JavaScript 下文有具体介绍
DirectionalLayout directionalLayout = (DirectionalLayout) findComponentById(ResourceTable.Id_directionallayout1);
directionalLayout.addComponent(webView);
}
}
2、加载 Web 页面。
final String url = EXAMPLE_URL; // EXAMPLE_URL 由开发者自定义
webView.load(url);
批改一下程序的入口:
package com.example.hanruwebview;
import com.example.hanruwebview.slice.MainAbilitySlice;
import com.example.hanruwebview.slice.SecondAbilitySlice;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
public class MainAbility extends Ability {
@Override
public void onStart(Intent intent) {super.onStart(intent);
// super.setMainRoute(MainAbilitySlice.class.getName());
super.setMainRoute(SecondAbilitySlice.class.getName());
}
}
看一下成果:
<img src=”https://img.chengxuka.com/WX20210616-154516@2x.png/mark” alt=”WX20210616-154516@2x” style=”zoom:50%;” />
二、定制网址加载行为
当 Web 页面进行链接跳转时,WebView 默认会关上指标网址,通过以下形式能够定制该行为。
1、自定义 WebAgent 对象。
private class ExampleWebAgent extends WebAgent {
@Override
public boolean isNeedLoadUrl(WebView webView, ResourceRequest request) {Uri uri = request.getRequestUrl();
if (EXAMPLE_URL.equals(uri.getDecodedHost())) {
// 由 WebView 通过默认形式解决
return false;
}
// 减少开发者自定义逻辑
return super.isNeedLoadUrl(webView, request);
}
}
2、设置自定义 WebAgent 至 WebView。
webView.setWebAgent(new ExampleWebAgent());
三、浏览网页历史记录
1、通过 getNavigator 办法获取 Navigator 对象。
Navigator navigator = webView.getNavigator();
2、应用 canGoBack()或 canGoForward()查看是否能够向后或向前浏览,应用 goBack()或 goForward()向后或向前浏览。
if (navigator.canGoBack()) {navigator.goBack();
}
if (navigator.canGoForward()) {navigator.goForward();
}
四、应用 JavaScript
通过以下形式,能够建设利用和页面间的 JavaScript 调用。
1、通过 WebConfig 启用 JavaScript。
webView.getWebConfig().setJavaScriptPermit(true);
2、依据理论须要抉择调用形式。
- 注入回调对象到页面内容,并在页面中调用该对象。
final String jsName = "JsCallbackToApp";
webview.addJsCallback(jsName, new JsCallback() {
@Override
public String onCallback(String msg) {
// 减少自定义解决
return "jsResult";
}
});
在页面内通过 JavaScript 代码调用注入对象。
function callToApp() {if (window.JsCallbackToApp && window.JsCallbackToApp.call) {var result = JsCallbackToApp.call("message from web");
}
}
- 在利用内调用页面内的 JavaScript 办法。
webview.executeJs("javascript:callFuncInWeb()", new AsyncCallback<String>() {
@Override
public void onReceive(String msg) {// 在此确认返回后果}
});
五、观测 Web 状态
通过 setWebAgent 办法设置自定义 WebAgent 对象,以观测页面状态变更等事件:
webview.setWebAgent(new WebAgent() {
@Override
public void onLoadingPage(WebView webView, String url, PixelMap favicon) {super.onLoadingPage(webView, url, favicon);
// 页面开始加载时自定义解决
}
@Override
public void onPageLoaded(WebView webView, String url) {super.onPageLoaded(webView, url);
// 页面加载完结后自定义解决
}
@Override
public void onLoadingContent(WebView webView, String url) {super.onLoadingContent(webView, url);
// 加载资源时自定义解决
}
@Override
public void onError(WebView webView, ResourceRequest request, ResourceError error) {super.onError(webView, request, error);
// 产生谬误时自定义解决
}
});
六、观测浏览事件
通过 setBrowserAgent 办法设置自定义 BrowserAgent 对象,以观测 JavaScript 事件及告诉等:
webview.setBrowserAgent(new BrowserAgent(this) {
@Override
public void onTitleUpdated(WebView webView, String title) {super.onTitleUpdated(webView, title);
// 题目变更时自定义解决
}
@Override
public void onProgressUpdated(WebView webView, int newProgress) {super.onProgressUpdated(webView, newProgress);
// 加载进度变更时自定义解决
}
});
七、加载资源文件或本地文件
出于平安思考,WebView 不反对间接通过 File 协定加载资源文件或本地文件,如利用需实现相干业务,可参考如下形式实现。
形式一:通过 processResourceRequest 办法 拜访文件
1、通过 setWebAgent 办法设置自定义 WebAgent 对象,覆写 processResourceRequest 办法。
webview.setWebAgent(new WebAgent() {
@Override
public ResourceResponse processResourceRequest(WebView webView, ResourceRequest request) {
final String authority = "example.com";
final String rawFile = "/rawfile/";
final String local = "/local/";
Uri requestUri = request.getRequestUrl();
if (authority.equals(requestUri.getDecodedAuthority())) {String path = requestUri.getDecodedPath();
if (TextTool.isNullOrEmpty(path)) {return super.processResourceRequest(webView, request);
}
if (path.startsWith(rawFile)) {
// 依据自定义规定拜访资源文件
String rawFilePath = "entry/resources/rawfile/" + path.replace(rawFile, "");
String mimeType = URLConnection.guessContentTypeFromName(rawFilePath);
try {Resource resource = getResourceManager().getRawFileEntry(rawFilePath).openRawFile();
ResourceResponse response = new ResourceResponse(mimeType, resource, null);
return response;
} catch (IOException e) {HiLog.info(TAG, "open raw file failed");
}
}
if (path.startsWith(local)) {
// 依据自定义规定拜访本地文件
String localFile = getContext().getFilesDir() + path.replace(local, "/");
HiLog.info(TAG, "open local file" + localFile);
File file = new File(localFile);
if (!file.exists()) {HiLog.info(TAG, "file not exists");
return super.processResourceRequest(webView, request);
}
String mimeType = URLConnection.guessContentTypeFromName(localFile);
try {InputStream inputStream = new FileInputStream(file);
ResourceResponse response = new ResourceResponse(mimeType, inputStream, null);
return response;
} catch (IOException e) {HiLog.info(TAG, "open local file failed");
}
}
}
return super.processResourceRequest(webView, request);
}
});
2、加载资源文件或本地文件。
// 加载资源文件 resources/rawfile/example.html
webView.load("https://example.com/rawfile/example.html");
// 加载本地文件 /data/data/com.example.dataability/files/example.html
webView.load("https://example.com/local/example.html");
形式二:通过 Data Ability 拜访文件
1、创立 Data Ability。
public class ExampleDataAbility extends Ability {
private static final String PLACEHOLDER_RAW_FILE = "/rawfile/";
private static final String PLACEHOLDER_LOCAL_FILE = "/local/";
private static final String ENTRY_PATH_PREFIX = "entry/resources";
@Override
public RawFileDescriptor openRawFile(Uri uri, String mode) throws FileNotFoundException {
final int splitChar = '/';
if (uri == null) {throw new FileNotFoundException("Invalid Uri");
}
// path will be like /com.example.dataability/rawfile/example.html
String path = uri.getEncodedPath();
final int splitIndex = path.indexOf(splitChar, 1);
if (splitIndex < 0) {throw new FileNotFoundException("Invalid Uri" + uri);
}
String targetPath = path.substring(splitIndex);
if (targetPath.startsWith(PLACEHOLDER_RAW_FILE)) {
// 依据自定义规定拜访资源文件
try {return getResourceManager().getRawFileEntry(ENTRY_PATH_PREFIX + targetPath).openRawFileDescriptor();} catch (IOException e) {throw new FileNotFoundException("Not found support raw file at" + uri);
}
} else if (targetPath.startsWith(PLACEHOLDER_LOCAL_FILE)) {
// 依据自定义规定拜访本地文件
File file = new File(getContext().getFilesDir(), targetPath.replace(PLACEHOLDER_LOCAL_FILE, ""));
if (!file.exists()) {throw new FileNotFoundException("Not found support local file at" + uri);
}
return getRawFileDescriptor(file, uri);
} else {throw new FileNotFoundException("Not found support file at" + uri);
}
}
private RawFileDescriptor getRawFileDescriptor(File file, Uri uri) throws FileNotFoundException {
try {final FileDescriptor fileDescriptor = new FileInputStream(file).getFD();
return new RawFileDescriptor() {
@Override
public FileDescriptor getFileDescriptor() {return fileDescriptor;}
@Override
public long getFileSize() {return -1;}
@Override
public long getStartPosition() {return 0;}
@Override
public void close() throws IOException {}
};
} catch (IOException e) {throw new FileNotFoundException("Not found support local file at" + uri);
}
}
}
2、在 config.json 中注册 Data Ability。
{
"name": "com.example.webview.ExampleDataAbility",
"type": "data",
"uri": "dataability://com.example.dataability",
"metaData": {
"customizeData": [
{
"name": "com.example.provider",
"extra": "$profile:path"
}
]
}
}
以及在 resources/base/profile 目录新增 path.xml:
<paths>
<root-path name="root" path="/" />
</paths>
3、配置反对拜访 Data Ability 资源。
webConfig.setDataAbilityPermit(true);
4、通过 dataability 协定加载资源文件或本地文件。
// 加载资源文件 resources/rawfile/example.html
webView.load("dataability://com.example.dataability/rawfile/example.html");
// 加载本地文件 /data/data/com.example.dataability/files/example.html
webView.load("dataability://com.example.dataability/local/example.html");
更多内容:
1、社区:鸿蒙巴士 https://www.harmonybus.net/
2、公众号:HarmonyBus
3、技术交换 QQ 群:714518656
4、视频课:https://www.chengxuka.com