Harmonyos之加载本地web页面

server/2025/6/21 15:43:52/

Harmonyos之加载本地web页面

  • 本地文件存放位置
    • resources资源文件下的rawfile目录
    • resources资源文件下的自定义目录
  • Native和H5的交互
    • 通过端口通信技术
      • Native代码
      • H5代码
  • h5调用Native方法(对象注册)
    • javaScriptProxy(Native注册对象)
    • registerJavaScriptProxy(Native注册对象)
    • deleteJavaScriptRegister(Native删除注册对象)
    • h5端调用注册对象的方法
  • Native调用H5的方法
    • H5侧代码
    • Native侧
  • 参考链接

本地文件存放位置

resources资源文件下的rawfile目录

第一种是放在src\main\resources\rawfile文件夹下,在ets文件中通过$rawfile('文件名')访问
在这里插入图片描述

Web({ src: $rawfile('test.html'), controller: this.controller})

resources资源文件下的自定义目录

我们也可以把h5文件访问到src\main\resources\目录下的自定目录

在这里插入图片描述
加载方式:

// 获取本地h5的资源路径,可以凭借h5链接需要的参数@State url: string = "file://" + getContext().resourceDir + "/uatfile/index.html#/"+"?accessToken="+this.acct+"&userName="+this.user_nameWeb({ src: '', controller: this.controller }).onlineImageAccess(true).imageAccess(true).darkMode(this.mode).domStorageAccess(true)//开启文档对象模型存储接口.javaScriptAccess(true)//允许执行JavaScript脚本.javaScriptProxy({object: new HippiusBridge(this.controller),name: "xxxx",methodList: ["postMessage"],controller: this.controller}).fileAccess(true)//开启应用中文件系统的访问.mixedMode(MixedMode.All)//允许加载超文本传输协议(HTTP)和超文本传输安全协议(HTTPS)混合内容.focusOnTouch(false).metaViewport(true)//设置meta标签的viewport属性是否可用.onControllerAttached(() => {//当Controller成功绑定到Web组件时触发该回调// 推荐在此loadUrl、设置自定义用户代理、注入JS对象等if (this.url) {console.info('[ ~~ mwebview onControllerAttached~~  ]  : ' +this.url.toString());this.controller.setPathAllowingUniversalAccess([getContext().resourceDir,getContext().resourceDir+"/uatfile"])try {let userAgent = this.controller.getUserAgent() + this.customUserAgent;this.controller.setCustomUserAgent(userAgent)} catch (error) {console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);}this.controller.loadUrl(this.url)}this.initBridge()}).onOverrideUrlLoading((webResourceRequest: WebResourceRequest) => {//当空白页则拦截 加载自定义空白页面if (webResourceRequest && webResourceRequest.getRequestUrl() == "about:blank") {return true;}return false;}).onPageBegin((event) => {if (event) {console.log('onPageBegin url:' + event.url);}}).onLoadIntercept((event) => {// 通过url检测是否点击打电话if (event.data.getRequestUrl().startsWith('tel')) {this.pushTelPage(event.data.getRequestUrl())}return false}).onProgressChange((event) => {if (event) {console.log('newProgress:' + event.newProgress);}}).onPageEnd((event) => {// 推荐在此事件中执行JavaScript脚本if (event) {console.log('onPageEnd url:' + event.url);}}).geolocationAccess(true)

Native和H5的交互

通过端口通信技术

前端页面和Native之间可以用createWebMessagePorts()接口创建消息端口来实现两端的通信

Native代码

创建通道:

ports: webview.WebMessagePort[] = [];
// 1、创建两个消息端口。this.ports = this.controller.createWebMessagePorts();

在Native侧消息端口(如端口1)注册 回调事件:

// 2、在应用侧的消息端口(如端口1)上注册回调事件。this.ports[1].onMessageEvent((result: webview.WebMessage) => {// 注册回调事件, 监听H5发送过来的消息// type WebMessage = ArrayBuffer | string;// result代表h5传递过来的结果,支持上述类型的数据})

将另一个消息端口(如端口0)发送到HTML侧,由HTML侧保存并使用。

// 创建web控制器方法
controller: webview.WebviewController = new webview.WebviewController();this.controller.postMessage('__init_port__', [this.ports[0]], '*');

使用Native的端口给传递给h5的端口发送消息:

// 发送消息给H5
this.ports[1].postMessageEvent(this.sendFromEts);

H5代码

监听window上的message方法,接受Native传递过来的端口:

var h5Port;
window.addEventListener('message', function (event) {
// 接收端if (event.data === '__init_port__') {if (event.ports[0] !== null) {h5Port = event.ports[0]; // 1. 保存从应用侧发送过来的端口。h5Port.onmessage = function (event) {//  onmessage 方法是监听Native端发过来的消息}}}})

h5段通过端口给Native发送消息:

// 使用h5Port向Native发送消息。
function PostMsgToEts(data) {if (h5Port) {h5Port.postMessage(data);} else {console.error('h5Port is null, Please initialize first');}
}

h5调用Native方法(对象注册)

javaScriptProxy(Native注册对象)

在Web组件初始化的时候调用javaScriptProxy()方法,给h5注册对象

注入JavaScript对象到window对象中,并在window对象中调用该对象的方法所有参数不支持更新。注册对象时,同步与异步方法列表请至少选择一项不为空,可同时注册两类方法。同一方法在同步与异步列表中重复注册,将默认异步调用

创建一个注册的类

class testClass {constructor() {}test(): string {return 'ArkTS Hello World!';}
}

注册对象:

class testClass {constructor() {}test(): string {return "ArkUI Web Component";}toString(): void {console.log('Web Component toString');}
}// 将对象注入到web端.javaScriptProxy({object: this.testObj, // 需要注册的对象name: "testObjName",// windows对象上的对象methodList: ["test"],// 注册对象中的方法列表controller: this.webviewController,// 可选参数asyncMethodList: [],permission: ''})

registerJavaScriptProxy(Native注册对象)

在Web组件初始化完成后调用registerJavaScriptProxy()方法来注册

// 这个是在组件加载完成后, 你可以在生命周期方法中
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"],// 可选参数, asyncMethodList[],// 可选参数, permission'')使用registerJavaScriptProxy()接口注册方法时,注册后需调用refresh()接口生效。

deleteJavaScriptRegister(Native删除注册对象)

上述两种方式都需要和deleteJavaScriptRegister方法来配合使用, 防止内存泄漏。

try {this.webviewController.deleteJavaScriptRegister("testObjName");} catch (error) {console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);}

h5端调用注册对象的方法

// 直接获取Native注册到windows的对象testObjName, 然后调用其方法
let str = testObjName.test();

Native调用H5的方法

H5侧代码

// 调用有参函数时实现。
function htmlTest(param) {// 有参数数实现方法
}
// 调用无参函数时实现。
function htmlTest() {// 无参函数实现方法     
}
//上述方法前面实际省略了windwos. , 这个两个方法中实际上住注册在window对象中的。

Native侧

// 前端页面函数无参时,将param删除。
this.webviewController.runJavaScript('htmlTest(param)');

在实际开发过程中我们其实可以灵活实现, 我们在H5可把回调方法传递给Native侧, 然后Native侧得到结果之后再调用回调方法。

// 获取app版本信息window.getAppInfoSuccess = this.getOhosAppVersion.bind(this);const dict = {'className': 'AppVersionBridgePlugin','function': 'getVersionNumber','successCallBack': 'getAppInfoSuccess','failureCallBack': '',};// Native侧注册一个公共对象HandBridge, 然后该对象中有一个公共方法,postMessage, 前端统一调用该对象的这个方法, Native收到这个对象在去分发到每个具体的功能实现类中
HandBridge.postMessage(JSON.stringify(dict))

HandBridge方法实现:

 postMessage(data: string) {if (data) {let obj = JSON.parse(data) as object //获取js传递过来的数据if (obj) {let className = obj["className"] as stringlet functionName = obj["function"] as stringlet params = obj["params"] as objectlet successCallBack = obj["successCallBack"] as stringlet failCallBack = obj["failureCallBack"] as stringlet callbackContext =new CallbackContext(successCallBack, failCallBack, this.controller)if (this.plugins.get(className)) {//调用原生方法this.exec(this.plugins.get(className), functionName, params, callbackContext)return}import(`../plugin/${className}`).then((ns: ESObject) => {let classObj: ESObject = new ns[className](); // 实例化if (classObj instanceof HippiusPlugin) {this.plugins.set(className, classObj)this.exec(classObj, functionName, params, callbackContext)}})}}}private exec(plugin: HippiusPlugin, action: string, params: ESObject, callback: CallbackContext) {if (plugin) {plugin.execute(action, params, callback)}}

CallbackContext类实现:

export class CallbackContext {static readonly TAG = 'CallbackContext'mSuccess: stringmError: stringcontroller: webview.WebviewControllerconstructor(mSuccess: string, mError: string, controller: webview.WebviewController) {this.mSuccess = mSuccessthis.mError = mErrorthis.controller = controller}public onSuccess(args: string) {this.toJS(this.mSuccess, args)}public onError(args: string) {this.toJS(this.mError, args)}private toJS(fun: string, args: string) {if (args) {args = args.replace("'", "\\'")}let js = `${fun}('${args}')`if (this.controller) {this.controller.runJavaScript(js)}}
}

参考链接

更多Native和H5交互资料参考链接:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/web-use-frontend-page-js


http://www.ppmy.cn/server/181223.html

相关文章

coding ability 展开第七幕(前缀和算法——进阶巩固)超详细!!!!

文章目录 前言和为k的子数组思路 和可被k整除的子数组思路 连续数组思路 矩阵区域和思路 总结总结 前言 本专栏上篇博客带大家了解了前缀和的有关模版以及习题的训练 从一维到二维的拓展,今天我们继续来练习一下前缀和的有关算法 fellow me 和为k的子数组 思路 设 i…

【Easylive】TokenUserInfoDto中@JsonIgnoreProperties和 Serializable 接口作用

【Easylive】项目常见问题解答(自用&持续更新中…) 汇总版 这段代码定义了一个名为 TokenUserInfoDto 的 DTO(数据传输对象),用于封装用户令牌信息。以下是对 JsonIgnoreProperties 和 Serializable 接口作用的详…

大型语言模型的秘密:思考链长度与提示格式的魔力

嘿,朋友们!今天我要和大家聊聊一个超级酷的话题——大型语言模型(LLMs) 它们在“思考”和回答问题时的一些“小秘密”。你可能已经听说过**“思考链”(Chain of Thought, COT** 这个概念,它是一种让模型在回…

【Go】数组

数组Array 重点: 数组是值类型 注意点: 1. 数组:是同一种数据类型的固定长度的序列。2. 数组定义:var a [len]int,比如:var a [5]int,数组长度必须是常量,且是类型的组成部分。一旦定义&…

[BJDCTF2020]Mark loves cat [git泄露][变量覆盖漏洞]

扫出来/.git/ 利用GitHack拿到index.php 源代码&#xff1a; <?phpinclude flag.php; //flag.php: //<?php //$flag file_get_contents(/flag);$yds "dog"; $is "cat"; $handsome yds;foreach($_POST as $x > $y){$$x $y; }foreach($_GE…

vue 4 组件通信

props , $event 自定义事件&#xff0c;mitt &#xff0c; 文章目录 前言 不同组件之间传递消息&#xff0c;父子组件通信&#xff0c;props&#xff0c;自定义事件&#xff0c; $event vue基础介绍了props组件通信 。 一、父子组件通信 1.props父子通信 props是使用频率最…

PyTorch之torchvision

PyTorch torchvision 是 PyTorch 生态中专门用于计算机视觉任务的库&#xff0c;提供了以下核心功能&#xff1a; 1. 核心功能概览 功能类别主要内容数据集内置经典数据集&#xff08;MNIST/CIFAR/ImageNet/COCO等&#xff09;预训练模型主流CV模型&#xff08;ResNet/VGG/Vi…

从零实现Json-Rpc框架】- 项目实现 - 基于Dispatcher模块的RPC框架

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…