赞
踩
基于鸿蒙 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
- // 对象注入 web
- object: this.WebCallAppMethod,
- name: 'WebCallApp', // AppCallWeb WebCallAppSsss WebCallApp
- methodList: ['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 文件中添加如下 script 段落后,在业务所需的地方调用即可
- // index.html
- <script>
- // eruda.init()
- (function () {
- if (!window.applicationCache && typeof(Worker)=='undefined') {
- alert("E001-检测到您的环境不支持HTML5,程序终止运行!");//不支持HTML5
- return;
- }
-
- var global = window; // create a pointer to the window root
- if (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 window
- window.AMap.global = global;
- })();
- </script>
- // 业务所需的点击事件方法中调用
- methods : {
- onClickGoBack() {
- let str = WebCallAppSsss.CmdTest('[交互] - 测试'); // 方式一
- // this.webApp.WebCallApp('CmdTest', '111111'); // 方式二
- Toast.success('abc');
- },
- }
自定义 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 Next
- console.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 & iOS
- context = 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) {
- //IOS
- params.sn = sn;
- window.webkit.messageHandlers["WebCallApp"].postMessage(JSON.stringify(params));
- } else if (Elf.WebCallApp) {
- //Android
- params.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,程序终止运行!");//不支持HTML5
- return;
- }
-
- var global = window;//create a pointer to the window root
- if (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');
- },
- }
以上便是此次分享的全部内容,希望能对大家有所帮助!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。