Ver código fonte

feat(基础组件): 新增 XWebview 消息交互功能- 新增 XWebController 接口和 XWebManager 类
- 实现了 XWebview 和原生代码之间的消息通信机制
- 更新了 MiniAppManager 中的 XWebHelper 使用新的消息通信功能- 优化了 XWebview组件,支持消息端口通信

徐勤民 1 mês atrás
pai
commit
fbca6847f1

+ 65 - 26
src/main/ets/pages/XWebview.ets

@@ -1,14 +1,16 @@
 import web_webview from '@ohos.web.webview';
+import webview from '@ohos.web.webview';
 import { router } from '@kit.ArkUI';
 import { XDialogController } from '../dialog/XDialogController';
 import { XDialogList } from '../dialog/XDialogList';
 import { picker } from '@kit.CoreFileKit';
 import { BusinessError } from '@kit.BasicServicesKit';
 import { ToolsHelper } from '../utils/ToolsHelper';
-import { XWebParams } from '../utils/XWebHelper';
+import { XWebController, XWebParams } from '../utils/XWebHelper';
 import { WindowHelper } from '../utils/WindowHelper';
 import { SZYXLocalStorageHelper } from '../utils/SZYXLocalStorageHelper';
 import { SZYXLocalStorageKeys } from '../utils/SZYXLocalStorageKeys';
+import { XWebManager } from '../utils/XWebManager';
 
 @Entry({ routeName: 'XWebview' })
 @Component
@@ -18,20 +20,26 @@ export struct XWebview {
   @State zoomAccess?: boolean = (router.getParams() as XWebParams).zoomAccess
   @State content?: string = (router.getParams() as XWebParams).content
   @State title?: string = (router.getParams() as XWebParams).title
+  @State xController?: XWebController = (router.getParams() as XWebParams).controller
   @State closeTag?: string = (router.getParams() as XWebParams).closeTag
   @State showMenu: boolean = (router.getParams() as XWebParams).showMenu ?? false
   @State errorInfo: string | null = null
   @State progress: number = 0
+  @State _uuid?: string = (router.getParams() as XWebParams)._uuid
+  @State _uuidToHtml?: string = (router.getParams() as XWebParams)._uuidToHtml
   controller: web_webview.WebviewController = new web_webview.WebviewController();
   dialogController: XDialogController = {} as XDialogController
+  ports: webview.WebMessagePort[] = [];
 
   aboutToAppear(): void {
     SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.XWebViewCLose, undefined)
+    webview.WebviewController.setWebDebuggingAccess(true);
+
     if (this.content) {
       try {
         this.controller.loadData(this.content,
           "text/html",
-          "UTF-8")
+          "UTF-8", '', '')
       } catch (e) {
         ToolsHelper.showAlertDialog({
           title: '警告',
@@ -44,12 +52,21 @@ export struct XWebview {
         })
       }
     }
+    if (this._uuidToHtml) {
+      XWebManager.addOnMessageToHtml(this._uuidToHtml, (msg) => {
+        if (this.ports && this.ports[1]) {
+          this.ports[1].postMessageEvent(msg);
+        }
+      })
+    }
   }
 
   aboutToDisappear(): void {
     if (this.closeTag !== undefined) {
       SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.XWebViewCLose, this.closeTag)
     }
+    XWebManager.removeOnMessage(this._uuid)
+    XWebManager.removeOnMessageToHtml(this._uuidToHtml)
   }
 
   onBackPress(): boolean | void {
@@ -123,9 +140,9 @@ export struct XWebview {
         .height('100%')
         .visibility(this.errorInfo == null ? Visibility.Visible : Visibility.None)
         .mixedMode(MixedMode.All)//允许加载HTTP和HTTPS混合内容
-        .zoomAccess(this.zoomAccess??false)//不支持手势进行缩放
+        .zoomAccess(this.zoomAccess ?? false)//不支持手势进行缩放
         .mediaPlayGestureAccess(false)//有声视频播放不需要用户手动点击
-        .cacheMode(CacheMode.Default)//设置缓存模式
+        .cacheMode(CacheMode.None)//设置缓存模式
         .onConfirm((event) => { // 自定义Confirm弹窗
           if (event) {
             console.log("event.url:" + event.url)
@@ -178,28 +195,50 @@ export struct XWebview {
             console.log('mimetype:' + event.mimetype)
           }
         })
-        // .onErrorReceive((event) => { // 加载失败
-        //   if (this.progress > 65) {
-        //     return
-        //   }
-        //   if (event) {
-        //     this.errorInfo = `错误码:${event.error.getErrorCode()}\n${event.error.getErrorInfo()}`
-        //   } else {
-        //     this.errorInfo = '错误码:-1\n未知错误'
-        //   }
-        //   ToolsHelper.log(JSON.stringify(event),this.url)
-        // })
-        // .onHttpErrorReceive((event) => { // 加载失败
-        //   if (this.progress > 65) {
-        //     return
-        //   }
-        //   if (event) {
-        //     this.errorInfo = `错误码:${event.response.getResponseCode()}\n${event.response.getReasonMessage()}`
-        //   } else {
-        //     this.errorInfo = '错误码:-1\n未知错误'
-        //   }
-        //   ToolsHelper.log( this.errorInfo,this.url)
-        // })
+        .onPageEnd((url) => {
+          ToolsHelper.log(url.url)
+          // 1、创建两个消息端口。
+          this.ports = this.controller.createWebMessagePorts();
+          this.ports[1].onMessageEvent((result: webview.WebMessage) => {
+            if (typeof (result) === 'string') {
+              ToolsHelper.log(result, typeof (result))
+              XWebManager.sendMessage(result)
+            }
+          })
+          this.controller.postMessage('__init_port__', [this.ports[0]], '*');
+        })
+        .onControllerAttached(() => {
+          try {
+            let userAgent = this.controller.getUserAgent() + '/szyx_sdk';
+            this.controller.setCustomUserAgent(userAgent);
+            // this.controller.runJavaScript('window.SZYX_YWX_WebViewBridge.onIsYwxApp()');
+
+          } catch (error) {
+            console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
+          }
+        })
+        .onErrorReceive((event) => { // 加载失败
+          if (this.progress > 65) {
+            return
+          }
+          if (event) {
+            this.errorInfo = `错误码:${event.error.getErrorCode()}\n${event.error.getErrorInfo()}`
+          } else {
+            this.errorInfo = '错误码:-1\n未知错误'
+          }
+          ToolsHelper.log(JSON.stringify(event), this.url)
+        })
+        .onHttpErrorReceive((event) => { // 加载失败
+          if (this.progress > 65) {
+            return
+          }
+          if (event) {
+            this.errorInfo = `错误码:${event.response.getResponseCode()}\n${event.response.getReasonMessage()}`
+          } else {
+            this.errorInfo = '错误码:-1\n未知错误'
+          }
+          ToolsHelper.log(this.errorInfo, this.url)
+        })
         .onProgressChange((event) => { // 加载进度
           if (event) {
             console.log('newProgress:' + event.newProgress)

+ 23 - 1
src/main/ets/utils/XWebHelper.ets

@@ -3,10 +3,15 @@ import { BusinessError } from '@kit.BasicServicesKit';
 import { LogHelper } from '../../../../Index';
 import { baseEncode } from '../util/base64Util';
 import { ToolsHelper } from './ToolsHelper';
+import { XWebManager } from './XWebManager';
 
 const XWebview = import('../pages/XWebview');
 
 
+export interface XWebController {
+  sendMessage: (message: string) => void
+}
+
 export interface XWebParams {
   url?: string
   zoomAccess?: boolean
@@ -15,6 +20,10 @@ export interface XWebParams {
   showMenu?: boolean
   closeTag?: string
   watermarkTxt?: string
+  _uuid?: string
+  _uuidToHtml?: string
+  onMessage?: (message: string) => void
+  controller?: XWebController
 }
 
 export class XWebHelper {
@@ -26,6 +35,16 @@ export class XWebHelper {
    * @param params
    */
   public static openWeb(params: XWebParams): Promise<boolean> {
+    if (params.onMessage) {
+      params._uuid = XWebManager.addOnMessage(params.onMessage)
+    }
+    if (params.controller) {
+      params._uuidToHtml = ToolsHelper.getUuid()
+      params.controller.sendMessage = (msg) => {
+        XWebManager.sendMessageToHtml(msg)
+      }
+    }
+
     return new Promise((resolve) => {
       router.pushNamedRoute({
         name: 'XWebview',
@@ -40,8 +59,11 @@ export class XWebHelper {
       })
     })
   }
+
   public static openPreview(params: XWebParams): Promise<boolean> {
-    params.url = `https://mdtdemo.51trust.com/preview/onlinePreview?url=${baseEncode(params.url)}&watermarkTxt=${encodeURI(params.watermarkTxt??'')}`
+    params.url =
+      `https://mdtdemo.51trust.com/preview/onlinePreview?url=${baseEncode(params.url)}&watermarkTxt=${encodeURI(params.watermarkTxt ??
+        '')}`
     return new Promise((resolve) => {
       router.pushNamedRoute({
         name: 'XWebview',

+ 41 - 0
src/main/ets/utils/XWebManager.ets

@@ -0,0 +1,41 @@
+import { ToolsHelper } from './ToolsHelper';
+
+export class XWebManager {
+  private static MapEventListener = new Map<string, (msg: string) => void>();
+
+  static addOnMessage(listener: (msg: string) => void): string {
+    const id = ToolsHelper.getUuid()
+    XWebManager.MapEventListener.set(id, listener)
+    return id
+  }
+
+  static removeOnMessage(id?: string) {
+    if (id) {
+      XWebManager.MapEventListener.delete(id)
+    }
+  }
+
+  static sendMessage(message: string) {
+    for (let item of XWebManager.MapEventListener.values()) {
+      item(message)
+    }
+  }
+
+  private static MapEventListenerToHtml = new Map<string, (msg: string) => void>();
+
+  static addOnMessageToHtml(id: string, listener: (msg: string) => void) {
+    XWebManager.MapEventListenerToHtml.set(id, listener)
+  }
+
+  static removeOnMessageToHtml(id?: string) {
+    if (id) {
+      XWebManager.MapEventListenerToHtml.delete(id)
+    }
+  }
+
+  static sendMessageToHtml(message: string) {
+    for (let item of XWebManager.MapEventListenerToHtml.values()) {
+      item(message)
+    }
+  }
+}