利用鸿蒙 JavaUI 框架的 WebView 加载本地冰墩墩网页

简介: 最近冰墩墩也太火了,各路大神纷纷表示用代码画冰墩墩,而我也刚好看到一个前端大神 Austin 用 JavaScript 前端写了一个冰墩墩,大家可以下载代码,本地打开就可以看到这个可爱的冰墩墩了。代码在后文参考资料中,大家可以自己下载。

起因

最近冰墩墩也太火了,各路大神纷纷表示用代码画冰墩墩,而我也刚好看到一个前端大神 Austin 用 JavaScript 前端写了一个冰墩墩,大家可以下载代码,本地打开就可以看到这个可爱的冰墩墩了。代码在后文参考资料中,大家可以自己下载。


自己前端知识既然不够,而刚好自己也在学习鸿蒙,这不就想着怎么把这个顶流拉取到本地然后读取到我的鸿蒙代码中呢,这不我立马搜索一下:鸿蒙如何读取本地 HTML


然后就有了对 WebView 的探索,最后终于让我琢磨成功,运行成功后的样子预览图如下:


image.png


除了对本地文件的读取,还支持对网络页面的访问,比如我这里就是读取 HarmonyOS应用开发官网,读者当然可以自己想访问哪个网页就访问自己的网页。

什么是 Webview

其实现在很多应用 App 里都内置了 Web 网页,比如微信、淘宝。在 Android 中就是利用 WebView 这一组件实现。WebView 是一个基于 webkit 引擎、展现 web 页面的控件。


鸿蒙也不例外,也通过 WebView 来提供应用中集成 Web 页面的能力。


作用:


  • 显示和渲染 Web 页面
  • 直接使用 HTML 文件(网络上或本地 resources 中)作布局
  • 可和 JavaScript 交互调用

WebView 使用

如果我们要加载远程网页,就要增加对网络的支持。在 config.json 中写入如下代码:

  "module": {
    "package": "com.yuzhou1su.webviewdemo",
    "name": ".MyApplication",
    "mainAbility": "com.yuzhou1su.webviewdemo.MainAbility",
    "deviceType": [
      "phone", "tv", "tablet"
    ],
    "reqPermissions": [
      {
        "name": "ohos.permission.INTERNET"  // 增加网络权限
      }
    ],


在 layout 的 ability_main.xml 中创建 WebView


在"slice/MainAbilitySlice.java"文件中通过 webview.load(String url) 方法访问具体的 Web 页面,通过 WebConfig 类对 WebView 组件的行为进行配置,代码如下:

package com.yuzhou1su.webviewdemo.slice;
import com.yuzhou1su.webviewdemo.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.TextField;
import ohos.agp.components.webengine.BrowserAgent;
import ohos.agp.components.webengine.JsMessageResult;
import ohos.agp.components.webengine.ResourceRequest;
import ohos.agp.components.webengine.WebAgent;
import ohos.agp.components.webengine.WebConfig;
import ohos.agp.components.webengine.WebView;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.ToastDialog;
public class MainAbilitySlice extends AbilitySlice {
    private static final String URL_LOCAL = "dataability://com.yuzhou1su.webviewdemo.DataAbility/resources/rawfile/BingDwenDwen.html";
    private static final String JS_NAME = "JsCallJava";
    private WebView webview;
    private TextField urlTextField;
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        initView();
    }
    private void initView() {
        webview = (WebView) findComponentById(ResourceTable.Id_webview);
        webview.getWebConfig().setDataAbilityPermit(true);  //这个要加上,设置 webview 支持打开本地文件
        urlTextField = (TextField) findComponentById(ResourceTable.Id_textField);
        initButton();
        configWebView();
    }
    private void configWebView() {
        WebConfig webConfig = webview.getWebConfig();
        // 是否支持Javascript,默认值false
        webConfig.setJavaScriptPermit(true);
        webview.setWebAgent(new WebAgent() {
            @Override
            public boolean isNeedLoadUrl(WebView webView, ResourceRequest request) {
                if (request == null || request.getRequestUrl() == 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);
                }
            }
        });
        webview.setBrowserAgent(new BrowserAgent(this) {
            @Override
            public boolean onJsMessageShow(WebView webView, String url, String message, boolean isAlert, JsMessageResult result) {
                if (isAlert) {
                    new ToastDialog(getApplicationContext()).setText(message).setAlignment(LayoutAlignment.CENTER).show();
                    result.confirm();
                    return true;
                } else {
                    return super.onJsMessageShow(webView, url, message, isAlert, result);
                }
            }
        });
        // 配置JS发来的消息处理
        webview.addJsCallback(JS_NAME, str -> {
            // 处理接收到的Js发送来的消息
            new ToastDialog(this).setText(str).setAlignment(LayoutAlignment.CENTER).show();
            // 返回给Js
            return "Js Call Java Success";
        });
    }
    private void initButton() {
        initLoadUrlButton();
        initLoadLocalUrlButton();
    }
    private void initLoadLocalUrlButton() {
        Button loadLocalUrlButton = (Button) findComponentById(ResourceTable.Id_load_local_url);
        loadLocalUrlButton.setClickedListener(component -> {
            webview.load(URL_LOCAL);
        });
    }
    private void initLoadUrlButton() {
        Button loadUrlButton = (Button) findComponentById(ResourceTable.Id_loadUrl);
        loadUrlButton.setClickedListener(component -> {
            webview.load(urlTextField.getText());
        });
    }
    @Override
    public void onActive() {
        super.onActive();
    }
    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}


background_ability_main.xml 写入如下代码:

<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
       ohos:shape="rectangle">
    <solid
        ohos:color="#F8F1EAEA"/>
</shape>


background_button.xml 写入如下代码:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
       ohos:shape="rectangle">
    <corners
        ohos:radius="20vp"/>
    <solid
        ohos:color="#FF46F5C3"/>
</shape>

WebView 读取本地页面

将本地的 HTML 文件放在"resources/rawfile/"目录下,在本教程中命名为  BingDwenDwen.html 。在 HarmonyOS 系统中,WebView 要访问本地 Web 文件,需要通过 DataAbility 的方式进行访问,所以此处创建 DataAbility.java 文件,写入如下代码:

package com.yuzhou1su.webviewdemo;
import java.io.FileNotFoundException;
import java.io.IOException;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.global.resource.RawFileDescriptor;
import ohos.utils.net.Uri;
public class DataAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
    }
    @Override
    public RawFileDescriptor openRawFile(Uri uri, String mode) throws FileNotFoundException {
        if (uri == null) {
            return super.openRawFile(uri, mode);
        }
        String path = uri.getEncodedPath();
        final int splitIndex = path.indexOf('/', 1);
        final 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;
    }
}


然后在 "entry/src/main/config.json" 中完成 DataAbility 的声明,代码如下:

{
        "name": "com.yuzhou1su.webviewdemo.DataAbility",
        "type": "data",
        "uri": "dataability://com.yuzhou1su.webviewdemo.DataAbility"
      }


至此,整个 config.json 文件内容如下:

{
  "app": {
    "bundleName": "com.yuzhou1su.webviewdemo",
    "vendor": "yuzhou1su",
    "version": {
      "code": 1000000,
      "name": "1.0.0"
    }
  },
  "deviceConfig": {},
  "module": {
    "package": "com.yuzhou1su.webviewdemo",
    "name": ".MyApplication",
    "mainAbility": "com.yuzhou1su.webviewdemo.MainAbility",
    "deviceType": [
      "phone", "tv", "tablet"
    ],
    "reqPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ],
    "distro": {
      "deliveryWithInstall": true,
      "moduleName": "entry",
      "moduleType": "entry",
      "installationFree": true
    },
    "abilities": [
      {
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ],
        "orientation": "unspecified",
        "name": "com.yuzhou1su.webviewdemo.MainAbility",
        "icon": "$media:icon",
        "description": "$string:mainability_description",
        "label": "$string:entry_MainAbility",
        "type": "page",
        "launchType": "standard"
      },
      {
        "name": "com.yuzhou1su.webviewdemo.DataAbility",
        "type": "data",
        "uri": "dataability://com.yuzhou1su.webviewdemo.DataAbility"
      }
    ]
  }
}


然后在 "slice/MainAbilitySlice.java" 中声明需要访问的文件路径,通过 webview.load(String url) 方法加载本地 Web 页面,可以通过 WebConfig 类的对象对 WebView 访问 DataAbility 的能力进行配置,示例代码如下:

private static final String URL_LOCAL = "dataability://com.yuzhou1su.webviewdemo.DataAbility/resources/rawfile/BingDwenDwen.html";
    private static final String JS_NAME = "JsCallJava";
    private WebView webview;
    private TextField urlTextField;
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        initView();
    }

代码结构如下

image.png


然后运行一个 MataPad Pro,执行我们的代码:


image.png


如果点击打开在线网页,就能看到鸿蒙开发官网:


image.png


然后我们点击 打开本地网页,就能看到一个可爱的冰墩墩:


image.png

总结

至此,我们通过 WebView 来访问远程网页和本地 HTML 都成功了,但是这仅仅是很小的一个工作,奈何本人前端知识实在匮乏,比如冰墩墩让我画我肯定画不出来的,但是并不影响我对冰墩墩和鸿蒙开发的热爱。


如果大家还想继续研究 WebView,可以自己多多探索,如果大家看完我的文章,有兴趣去做出一个 APP 内置浏览器功能,那我的目的也就达到了。

相关文章
|
6月前
|
JavaScript 开发工具 开发者
【HarmonyOS 5】鸿蒙Web组件和内嵌网页双向通信DEMO示例
【HarmonyOS 5】鸿蒙Web组件和内嵌网页双向通信DEMO示例
248 3
|
2月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
337 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
2月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
313 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
2月前
|
移动开发 Rust JavaScript
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
721 4
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
5月前
|
移动开发 前端开发 JavaScript
鸿蒙NEXT时代你所不知道的全平台跨端框架:CMP、Kuikly、Lynx、uni-app x等
本篇基于当前各大活跃的跨端框架的现状,对比当前它们的情况和未来的可能,帮助你在选择框架时更好理解它们的特点和差异。
634 0
|
3月前
|
JSON 自然语言处理 数据格式
使用Tabs选项卡组件快速搭建鸿蒙APP框架
ArkUI提供了很多布局组件,其中Tabs选项卡组件可以用于快速搭建鸿蒙APP框架,本文通过案例研究Tabs构建鸿蒙原生应用框架的方法和步骤。
427 5
使用Tabs选项卡组件快速搭建鸿蒙APP框架
|
2月前
|
移动开发 Android开发
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
190 0
|
4月前
|
移动开发 网络协议 小程序
鸿蒙NEXT即时通讯/IM系统RinbowTalk v2.4版发布,基于MobileIMSDK框架、ArkTS编写
RainbowTalk是一套基于开源即时通讯讯IM框架 MobileIMSDK 的产品级鸿蒙NEXT端IM系统。纯ArkTS编写、全新开发,没有套壳、也没走捷径,每一行代码都够“纯血”。与姊妹产品RainbowChat和RainbowChat-Web 技术同源,历经考验。
262 1
|
移动开发 JavaScript 前端开发
HarmonyOS鸿蒙应用开发——探索原生与H5通信框架DSBridge
HarmonyOS版DSBridge是一个桥梁库,允许鸿蒙原生环境与JavaScript交互。它兼容Android和iOS的第三方DSBridge核心功能,支持同步和异步调用、命名空间API管理、进度回调及页面关闭监听等功能。主要特性包括适配鸿蒙NEXT版本、支持串行异步并发任务、兼容DSBridge 2.0与3.0版本JS脚本,并提供类形式集中管理API及自定义页面组件注册。源码仓库:HarmonyOS版 - DSBridge-HarmonyOS。安装命令为`ohpm install @hzw/ohos-dsbridge`。通过该库,开发者可以方便地在鸿蒙系统中实现原生与JS的高效交互。
808 1
|
7月前
|
数据安全/隐私保护
贡献 OpenHarmony 库关键配置 #自研框架#ArkUI-X#三方框架#OpenHarmony#HarmonyOS
# 贡献 OpenHarmony 库关键配置 #自研框架#ArkUI-X#三方框架#OpenHarmony#HarmonyOS
205 11

热门文章

最新文章