前端 Web 与原生应用端 WebView 通信交互 - HarmonyOS Next

基于鸿蒙 HarmonyOS Next 与前端 Vue 通信交互相关小结;
DevEco Studio NEXT Developer Preview2
Vue js

两端相互拟定好协议后,通过前端页面的点击事件,将所需的数据传输给原生移动端组件方法中,处理后将消息回传至前端.

根据官方文档的案例尝试,但没成功 ... 后经过几经尝试后两端握手成功 ... (官方文档略显粗糙,好一番折腾)

一.应用端

基于 import web_webview from '@ohos.web.webview' 并初始化 Web 组件;
调用 javaScriptProxy 方法,定义配置协议、参数和方法相关,具体可参考如下 code 片段;
name: 交互协议
object: 定义交互对象
methodList: 交互对象中所涵盖的方法,支持多个,也可以通过一个对象方法再细化多个子方法
controller: 组件

import web_webview from '@ohos.web.webview'@Entry
@Component
export struct HomePage {controller: web_webview.WebviewController = new web_webview.WebviewController()ports: web_webview.WebMessagePort[] = [];nativePort: web_webview.WebMessagePort | null = null;message: web_webview.WebMessageExt = new web_webview.WebMessageExt();// 声明注册对象@State WebCallAppMethod: WebCallAppClass = new WebCallAppClass()aboutToAppear(): void {try {// 启用网页调试功能web_webview.WebviewController.setWebDebuggingAccess(true);} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.log(`Error Code: ${e.code}, Message: ${e.message}`);this.controller.refresh(); // 页面异常,刷新}}build() {Row() {Column({ space: 20 }) {Web({ src: 'http://192.168.12.108:8080', controller: this.controller }).width('100%').height('100%').backgroundColor(Color.White).multiWindowAccess(true).javaScriptAccess(true).geolocationAccess(true).imageAccess(true).onlineImageAccess(true).domStorageAccess(true).fileAccess(true).mediaPlayGestureAccess(true).mixedMode(MixedMode.All).layoutMode(WebLayoutMode.FIT_CONTENT) // 自适应布局.verticalScrollBarAccess(true).horizontalScrollBarAccess(false).cacheMode(CacheMode.Default).zoomAccess(false)// 禁止手势缩放.onConsole((event) => {console.log('[交互] - onConsole')LogUtils.info(event?.message.getMessage())return false}).onPageBegin(() => { // 页面加载中// this.registerWebJavaScript()}).onPageEnd(() => { // 页面加载完成console.log('[Web] - 页面加载完成')// this.registerWebJavaScript()}).onErrorReceive((event) => { // 异常: 无网络,页面加载错误时if (event) {console.info('getErrorInfo:' + event.error.getErrorInfo());console.info('getErrorCode:' + event.error.getErrorCode());console.info('url:' + event.request.getRequestUrl());console.info('isMainFrame:' + event.request.isMainFrame());console.info('isRedirect:' + event.request.isRedirect());console.info('isRequestGesture:' + event.request.isRequestGesture());console.info('getRequestHeader_headerKey:' + event.request.getRequestHeader().toString());let result = event.request.getRequestHeader();console.info('The request header result size is ' + result.length);for (let i of result) {console.info('The request header key is : ' + i.headerKey + ', value is : ' + i.headerValue);}}}).onHttpErrorReceive((event) => { // 异常: 网页加载资源 Http code >= 400 时if (event) {console.info('url:' + event.request.getRequestUrl());console.info('isMainFrame:' + event.request.isMainFrame());console.info('isRedirect:' + event.request.isRedirect());console.info('isRequestGesture:' + event.request.isRequestGesture());console.info('getResponseData:' + event.response.getResponseData());console.info('getResponseEncoding:' + event.response.getResponseEncoding());console.info('getResponseMimeType:' + event.response.getResponseMimeType());console.info('getResponseCode:' + event.response.getResponseCode());console.info('getReasonMessage:' + event.response.getReasonMessage());let result = event.request.getRequestHeader();console.info('The request header result size is ' + result.length);for (let i of result) {console.info('The request header key is : ' + i.headerKey + ' , value is : ' + i.headerValue);}let resph = event.response.getResponseHeader();console.info('The response header result size is ' + resph.length);for (let i of resph) {console.info('The response header key is : ' + i.headerKey + ' , value is : ' + i.headerValue);}}}).onConfirm((event) => { // 提示框处理相关AlertDialog.show({title: '温馨提示',message: event?.message,confirm: {value: 'onAlert',action: () => {event?.result.handleConfirm()}},cancel: () => {event?.result.handleCancel()}})return true;}).onShowFileSelector((event) => { // 文件上传处理相关console.log('MyFileUploader onShowFileSelector invoked');const documentSelectOptions = new picker.PhotoSelectOptions();let uri: string | null = null;const documentViewPicker = new picker.PhotoViewPicker();documentViewPicker.select(documentSelectOptions).then((documentSelectResult) => {uri = documentSelectResult[0];console.info('documentViewPicker.select to file succeed and uri is:' + uri);if (event) {event.result.handleFileList([uri]);}}).catch((err: BusinessError) => {console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`);})return true;}).javaScriptProxy({ // web call app// 对象注入 webobject: this.WebCallAppMethod,name: 'WebCallApp', // AppCallWeb WebCallAppSsss  WebCallAppmethodList: ['WebCallApp', 'CmdTest', 'CmdOpenUrl'],controller: this.controller})}.width('100%').height('100%')}}
}class WebCallAppClass {constructor() {}WebCallApp(value: string): string { // 采用该 Json 对象模式,通过解析对象中的 type 后细化对应不同的子方法console.log('[交互] --- WebCallApp - 测试')console.log(value)console.log(JSON.parse(value))return '[交互] --- WebCallApp - 测试 - 回调123123123'}CmdOpenUrl(): Object {console.log('[交互] --- WebCallApp - CmdOpenUrl');new Object({'command': '111',})return Object;}CmdTest(value: string): string {console.log('[交互] --- WebCallApp - test');console.log(value);return '[交互] --- WebCallApp - test';}
}

二.前端

前端配置有两种方式,可以通过 index.html 配置 js 后调用,也可以单独另起一个 js 类方法去适配,具体可参考如下 code 按需尝试;

方式一.通过 index.html

在项目根目录的 index.html 文件中添加如下 script 段落后,在业务所需的地方调用即可

// index.html
<script>// eruda.init()(function () {if (!window.applicationCache && typeof(Worker)=='undefined') {alert("E001-检测到您的环境不支持HTML5,程序终止运行!");//不支持HTML5return;}var global = window; // create a pointer to the window rootif (typeof WebCallAppSsss === 'undefined') {global.WebCallApp = { // 此处的 WebCallApp 与原生端 javaScriptProxy 中的 name 相互匹配// 如下方法对应的是 javaScriptProxy 中 object 对象中的方法WebCallApp: (arg) => {},CmdOpenUrl: (arg) => {},CmdTest: (arg) => {},}; // create elf root if not existed}window.WebCallAppSsss.global = global; // add a pointer to windowwindow.AMap.global = global;})();
</script>
// 业务所需的点击事件方法中调用
methods : {onClickGoBack() {let str = WebCallAppSsss.CmdTest('[交互] - 测试'); // 方式一// this.webApp.WebCallApp('CmdTest', '111111'); // 方式二Toast.success('abc');},
}

方式二.通过自定义 js

自定义 webCallApp 类,通过引入类方法调用

// WebCallApp.js
import {AppCallBacks,AppCommendBackHandlers,
} from './AppMsgHandlers'export default {WebCallApp(command,args,callback,context) {/*** 交互** 协议:command* 入参:args* 回调:callback* 参数:context* */if (typeof Elf.AppCallWeb != "undefined") {if (this.isInHarmonyOS()) { // 鸿蒙 HarmonyOS Nextconsole.log('[OpenHarmony] - ' + command);let params = {args: args, // 入参command: command // 交互协议};console.log('[鸿蒙] - 入参');console.log(params);if (typeof WebCallApp === 'undefined') {Elf.WebCallApp = {WebCallApp: (args) => {}};}window.WebCallApp.Elf = Elf;} else { // Android & iOScontext = context || window;//默认为window对象args = args || {};let  sn = null;//IOS调用相机--sn特殊处理if (command == "callCamera") {sn = "examCamera";} else {sn = this.getSerialNumber();//请求App统一加水单号}let params = {args: args,command: command};//绑定回调函数if (callback) {AppCallBacks[sn] = {callback: callback,context: context};}if (window.webkit && window.webkit.messageHandlers) {//IOSparams.sn = sn;window.webkit.messageHandlers["WebCallApp"].postMessage(JSON.stringify(params));} else if (Elf.WebCallApp) {//Androidparams.sn = sn;Elf.WebCallApp(JSON.stringify(params));} else {}}}},isInApp() {if (typeof Elf.AppCallWeb != "undefined") {return !!((window.webkit && window.webkit.messageHandlers) || typeof Elf.WebCallApp == "function" || typeof Elf.WebCallCef == "function");}},isInIOS() {return window.webkit && window.webkit.messageHandlers;},isInAndroid() {if (typeof Elf.AppCallWeb != "undefined") {return typeof Elf.WebCallApp == "function";}},isInHarmonyOS() {if (navigator.userAgent.toLowerCase().indexOf('openharmony') !== -1) {return true;} else {return false;}},getSerialNumber() {var uuid = this.UUID(3,8);return new Date().format("yyyyMMddhhmmssS") + uuid;},UUID(len,radix) {var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');var uuid = [],i;radix = radix || chars.length;if (len) {for (i = 0; i < len; i++) {uuid[i] = chars[0 | Math.random() * radix];}} else {var r;uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';uuid[14] = '4';for (i = 0; i < 36; i++) {if (!uuid[i]) {r = 0 | Math.random() * 16;uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];}}}return uuid.join('');},
}
/* eslint-disable */
// AppMsgHandlers
import webApp from './index';/*** app对接* 移动端种植Elf对象* window => Elf* */
(function () {if (!window.applicationCache&&typeof(Worker)=='undefined') {alert("E001-检测到您的环境不支持HTML5,程序终止运行!");//不支持HTML5return;}var global = window;//create a pointer to the window rootif (typeof Elf === 'undefined') {global.Elf = {};//create elf root if not existed}Elf.global = global;//add a pointer to window
})();var AppCallBacks = {},//动态数据流水列表AppCommendBackHandlers = [],//APP后退监听事件列表APPCommendBookStateHandlers = [],//下载状态监听事件列表AppCommendRefreshHandlers = [],//刷新监听事件列表APPCommendAddToBookShelfHandlers = [],//添加到书架监听事件列表APPCommendAddToObtainedBookHandlers = [],//添加到已获得图书列表监听APPCommendReBackHandlers = [],//监听重新回到页面通知AppCommendNetworkHandlers = [],//监听网络链接状态AppCommendAppStartingHandlers = [],//监听APP进入后台运行AppCommendAppReactivateHandlers = [],//监听APP重新进入前台运行AppCommendScreenShotss = [],//监听手机截屏AppCommendKeyboardBounceUp = [];//监听移动端软键盘事件if (typeof Elf != "undefined") {Elf.AppCallWeb = (sn,result) => {if (result && typeof result == "string") {result = decodeURIComponent(result.replace(/\+/g,'%20'));try {result = JSON.parse(result);//解决空格变成+的问题} catch (error) {AppCallBacks[sn].callback.call(AppCallBacks[sn].context,result);return;}if (result.sn) {AppCallBacks[sn].callback.call(AppCallBacks[sn].context,result.QrCode);return;}}if (AppCallBacks[sn]) {if (JSON.parse(result.opFlag)) {//执行对应回调AppCallBacks[sn].callback.call(AppCallBacks[sn].context,(typeof result.serviceResult == "string") ? JSON.parse(result.serviceResult) : result.serviceResult);} else {//接口调用返回失败信息,统一处理错误消息Toast(result.errorMessage ? result.errorMessage : "服务器异常!");}//调用完成删除对象delete AppCallBacks[sn];} else if (AppMsgHandlers[sn] && typeof AppMsgHandlers[sn] == "function") {//处理消息通知AppMsgHandlers[sn].call(window,result);}};
}export {AppCallBacks,AppCommendBackHandlers
}

业务方法调用

// 业务所需的点击事件方法中调用
methods : {onClickGoBack() {// let str = WebCallAppSsss.CmdTest('[交互] - 测试'); // 方式一this.webApp.WebCallApp('CmdTest', '111111'); // 方式二Toast.success('abc');},
}

以上便是此次分享的全部内容,希望能对大家有所帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/23122.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GDB调试工具

-D&#xff0c;指定编译内容。 调试: gdb ./a.out 文件名 l可以查看代码内容 c全部执行 n执行下一步 q退出 gdb ./a.out -p id号 查找ID号用管道命令&#xff5c;。

【重磅丨教育设备】推动大规模设备更新和消费品以旧换新行动方案

近日&#xff0c;国务院印发《推动大规模设备更新和消费品以旧换新行动方案》&#xff08;以下简称《行动方案》&#xff09;。《行动方案》提出&#xff1a;实施设备更新行动。提升教育文旅医疗设备水平&#xff0c;推动符合条件的高校、职业院校&#xff08;含技工院校&#…

FarmersWorld农民世界源码开发:0撸卷轴+潮玩模式

一、引言 随着科技的发展&#xff0c;游戏产业日益壮大&#xff0c;一种新型的游戏形式——零撸游戏应运而生。本文将深入探讨FarmersWorld农民世界源码开发&#xff0c;以其独特的0撸卷轴潮玩模式&#xff0c;为玩家带来全新的游戏体验。 二、源码开发的专业性和深度 Farmer…

笔记 | 软件工程01:从程序到软件

1 软件工程知识域 2 程序 2.1 何为程序及程序的质量要求 何为程序&#xff1a; 理解&#xff1a;软件工程可能就是在弥补OOP语言与自然语言之间还存在的鸿沟 2.1.1 程序质量的内在和外在体现 2.1.2 程序质量的语法和语义体现 2.2 编写代码的基本原则 2.3 程序质量保证方法 …

xml创建模型组合体

XML创建模型组合体 创建步骤模型准备模型处理模型文件XML编写 效果 创建步骤 模型准备 CAD 提供的原始模型如下&#xff1a; 该模型存在的问题&#xff1a; 单位问题&#xff1a;CAD出图的是 mm 为单位&#xff0c;但是 mujoco 建模这边用的是以 m 为单位的&#xff1b;原点…

2024年会计、金融与工商管理国际会议(ICAFBA 2024)

2024年会计、金融与工商管理国际会议 2024 International Conference on Accounting, Finance, and Business Administration 【1】会议简介 2024年会计、金融与工商管理国际会议是一场集合了全球会计、金融与工商管理领域专家学者的学术盛会。此次会议旨在深入探讨会计、金融与…

matlab模拟黑洞包含吸积盘和喷流,简单模拟

本文介绍 黑洞的简单实现和模拟 代码 % Black Hole Simulation in 3D% Clear workspace and figures clear; close all; clc;% Create figure and set axis properties figure; axis([-10 10 -10 10 -10 10]); hold on; grid on; view(3);% Parameters for the black hole a…

C# 判断字符串不等于空的示例

在C#中&#xff0c;要判断一个字符串是否不等于空&#xff08;即它既不是null也不是空字符串""&#xff09;&#xff0c;方法有如下几种&#xff0c;如下。 方法1 使用逻辑运算符和string.IsNullOrEmpty方法 string myString "123"; // 假设要检查的字…

Capture One Pro 23:专业 Raw 图像处理的卓越之选

在当今的数字摄影时代&#xff0c;拥有一款强大的图像处理软件至关重要。而 Capture One Pro 23 for Mac/Win 无疑是其中的佼佼者&#xff0c;为摄影师和图像爱好者带来了前所未有的体验。 Capture One Pro 23 以其出色的 Raw 图像处理能力而闻名。它能够精准地解析和处理各种…

微软不再允许Windows 11通过1@1.com绕过登录 但还有其他办法可以继续用

微软不再允许 Windows 11 通过 11.com 和 nothankyou.com 绕过登录&#xff0c;但断网的情况下使用 OOBE\BYPASSNRO 命令仍然是有效的。如果你在安装或重置系统时仍然需要创建本地账户&#xff0c;请直接使用 OOBE 命令。 在 Windows 11 家庭版和专业版中用户必须保持设备联网…

【SW-拉伸曲面】

拉伸曲面记录 前言一、步骤二、结果展示总结 前言 2024/6/4去教xyy的时候学到了新的技能ε(┬┬﹏┬┬)3 一、步骤 画好草图之后点拉伸曲面 注意选的时候要选线条&#xff0c;不要选择面 二、结果展示 超级薄的曲面结构出来了。 总结 这篇文章依旧没有总结

设计模式-策略模式(行为型)

行为型-策略模式 了解策略模式 策略模式是一种行为型设计模式&#xff0c;在策略模式中定义了一系列算法或者策略&#xff0c;并将这些策略封装到独立的类中&#xff0c;使得可以相互替换。在使用时&#xff0c;可以指定响应的策略使用。 角色 策略接口&#xff1a;对于某种…

uniPush2.0消息推送(云对象)

1.创建uniCloud云开发环境 关联云服务空间&#xff08;没有云空间到官网上创建&#xff09;步骤如下 2. index.obj.js代码 &#xff0c;然后上传部署 // 云对象教程: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj // jsdoc语法提示教程&#xff1a;https://ask.dc…

STM32电子实战项目(一)记录:BLDC kitchen prep centre

产品目的&#xff1a; 解决搅拌机食材粘壁问题。 产品功能及需求分析&#xff1a; 需求分析及实现可能性&#xff1a; 从项目需求看&#xff0c;该项目要实现的功能并不复杂&#xff0c;控制电机的正反转及对应LED显示即可&#xff0c;同时也没必要控制电机转速&#xff0c;…

如何根据业务需求,轻松挑选SSL证书?

在当今数字化时代&#xff0c;网站的安全性愈发受到重视。SSL证书作为网站安全的“守门员”&#xff0c;不仅能保护用户数据不被窃取&#xff0c;还能提升网站的信任度。但面对市场上琳琅满目的SSL证书产品&#xff0c;如何根据业务需求挑选合适的证书呢&#xff1f;今天&#…

流量分析——一、蚁剑流量特征

君衍. 一、Webshell特征流量分析二、环境介绍三、使用Wireshark进行流量分析1、环境说明2、HTTP追踪流分析3、蚁剑请求体中代码块解读 四、使用BurpSurite进行流量分析1、环境配置2、抓包分析 六、总结 一、Webshell特征流量分析 对于重保、护网等攻防演练的防守方来说&#x…

wps:样式集的使用【笔记】

wps&#xff1a;样式集的使用【笔记】 前言版权推荐wps&#xff1a;样式集的使用1拿到一个内容模板2修改样式集3修改样式的详细说明4保存样式集5应用样式集 说明另外最后 前言 2024-6-5 23:36:20 以下内容源自《【笔记】》 仅供学习交流使用 版权 禁止其他平台发布时删除以…

LLM大语言模型(十六):最新开源 GLM4-9B 本地部署,带不动,根本带不动

目录 前言 本机环境 GLM4代码库下载 模型文件下载&#xff1a;文件很大 修改为从本地模型文件启动 启动模型cli对话demo 慢&#xff0c;巨慢&#xff0c;一个字一个字的蹦 GPU资源使用情况 GLM3资源使用情况对比 前言 GLM-4-9B 是智谱 AI 推出的最新一代预训练模型 …

Apache Superset:数据可视化的现代开源解决方案

Superset&#xff1a; 洞察数据&#xff0c;一目了然- 精选真开源&#xff0c;释放新价值。 概览 Apache Superset 是一个由 Apache 软件基金会支持的开源数据可视化和数据探索平台。它允许用户以直观的方式构建丰富的数据报告和仪表板&#xff0c;支持从多种数据源中提取数据…

2024版本---LabVIEW 软件安装及使用教程

目录 第1章 LabVIEW 软件安装及使用教程 1. 简介 2. 安装教程 2.1 下载 LabVIEW 2024 版本 2.2 安装 LabVIEW 3. 激活 LabVIEW 4. LabVIEW 基本使用教程 4.1 用户界面介绍 4.2 创建一个简单的 VI&#xff08;虚拟仪器&#xff09; 4.3 数据采集示例 5. 进阶功能介绍…