HarmonyOS之常用组件WebView的使用

Posted Forever_wj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HarmonyOS之常用组件WebView的使用相关的知识,希望对你有一定的参考价值。

一、WebView 功能

  • WebView 提供在应用中集成 Web 页面的能力。
  • 请使用真机或模拟器运行查看 WebView 效果,预览器不支持 WebView 显示。
  • 只有预置 WebView 能力的真机设备才支持 WebView 功能,智能穿戴设备不支持 WebView。

二、WebView 的使用方法

  • WebView 派生于通用组件 Component,可以像普通组件一样进行使用。
  • 在使用 WebView 时需要配置应用的网络权限,打开“entry > src > main > config.json”,并添加如下配置:
	{
	  ...
	  "module": {
	    ...
	    "reqPermissions": [
	      {
	        "name": "ohos.permission.INTERNET"
	      }
	    ],
	    ...
	  }
	}
  • 方式一:
    • 在 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>
    • 在 Java 代码中,使用 load 方法加载 Web 页面:
	WebView webView = (WebView) findComponentById(ResourceTable.Id_webview);
	webView.getWebConfig().setjavascriptPermit(true);  // 如果网页需要使用JavaScript,增加此行;如何使用JavaScript下文有详细介绍  
	final String url = EXAMPLE_URL; // EXAMPLE_URL由开发者自定义
	webView.load(url);
  • 方式二:
    • 在 Java 代码中,通过 ComponentContainer 容器创建布局 DirectionalLayout,并在 DirectionalLayout 内添加 WebView:
	DirectionalLayout dLayout = new DirectionalLayout(this);
	dLayout.setLayoutConfig(new ComponentContainer.LayoutConfig(
	    ComponentContainer.LayoutConfig.MATCH_PARENT,
	    ComponentContainer.LayoutConfig.MATCH_PARENT
	));
	super.setUIContent(dLayout);
	WebView webView = new WebView(getContext());
	webView.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);
	webView.setHeight(ComponentContainer.LayoutConfig.MATCH_PARENT);
	webView.getWebConfig().setJavaScriptPermit(true);  // 如果网页需要使用JavaScript,增加此行;如何使用JavaScript下文有详细介绍
	dLayout.addComponent(webView);
    • 加载 Web 页面:
	final String url = EXAMPLE_URL; // EXAMPLE_URL由开发者自定义
	webView.load(url);

三、浏览网页历史记录

  • 通过 getNavigator 方法获取 Navigator 对象:
	Navigator navigator = webView.getNavigator();
  • 使用 canGoBack() 或 canGoForward() 检查是否可以向后或向前浏览,使用 goBack() 或 goForward() 向后或向前浏览:
	if (navigator.canGoBack()) {
	    navigator.goBack();
	}
	if (navigator.canGoForward()) {
	    navigator.goForward();
	}

四、使用 JavaScript

  • 通过 WebConfig 启用 JavaScript:
	webView.getWebConfig().setJavaScriptPermit(true);
  • 根据实际需要选择调用方式:
    • 注入回调对象到页面内容,并在页面中调用该对象:
	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);
	        // 加载进度变更时自定义处理
	    }
	});

七、定制网址加载行为

  • 当 Web 页面进行链接跳转时,WebView 默认会打开目标网址,通过以下方式可以定制该行为。
  • 自定义 WebAgent 对象:
	private class ExampleWebAgent extends WebAgent {
	    public static final String EXAMPLE_URL = "...";
	    @Override
	    public boolean isNeedLoadUrl(WebView webview, ResourceRequest request) { 
	        if (request == null || request.getRequestUrl() == null) {
	            return false;
	        }
	        Uri uri = request.getRequestUrl();
	        // EXAMPLE_URL由开发者自定义
	        if (uri.getDecodedHost().equals(EXAMPLE_URL)) {
	            // 增加开发者自定义逻辑
	            return false;
	        } else {
	            return super.isNeedLoadUrl(webview, request);
	        }
	    }
	}
  • 设置自定义 WebAgent 至 WebView:
	webView.setWebAgent(new ExampleWebAgent());

八、加载资源文件或本地文件

  • 出于安全考虑,WebView 不支持直接通过 File 协议加载资源文件或本地文件。
  • 如应用需实现相关业务,可参考如下方式实现。
① 通过 processResourceRequest 方法访问文件
  • 通过 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);
	    }
	});
  • 在 resources 目录下的 rawfile 路径下创建"example.html"资源文件,以及在本机设备内创建"example.html"本地文件。
  • 加载资源文件或本地文件:
	// 加载资源文件 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 访问文件
  • 创建 Java 文件 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);
	        }
	    }
	}
  • 在 config.json 中注册 Data Ability,以及在 resources/base/profile 目录新增 path.xml:
	{
	"name": "com.example.webview.ExampleDataAbility",
	"type": "data",
	"uri": "dataability://com.example.dataability",
	"metaData": {
	    "customizeData": [
	    {
	        "name": "com.example.provider",
	        "extra": "$profile:path"
	    }
	    ]
	}
	}
	<paths>
	    <root-path name="root" path="/" />
	</paths>
  • 在 resources 目录下的 rawfile 路径下创建"example.html"资源文件,以及在本机设备内创建"example.html"本地文件。
  • 配置支持访问 Data Ability 资源:
	webConfig.setDataAbilityPermit(true);
  • 通过 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");

以上是关于HarmonyOS之常用组件WebView的使用的主要内容,如果未能解决你的问题,请参考以下文章

HarmonyOS之常用组件ScrollView的功能和使用

HarmonyOS之常用组件ListContainer的功能和使用

HarmonyOS之常用组件ProgressBar的功能和使用

HarmonyOS之深入分析常用组件Text的功能和使用

HarmonyOS之常用组件Image的功能和使用

HarmonyOS之深入分析常用组件TextField的功能和使用