HarmonyOS h5与原生交互, 在原生实现的js方法中怎么获取到webController,用于调用runJavaScript方法?

HarmonyOS端定义js方法,提供给前端调用,之后需要通过webController的runJavaScript的方法调用h5的方法,但是JavaScriptObjTest在struct UI类外部,获取不到webController,HarmonyOS这边应该如何跟UI线程通信呢?

class JavaScriptObjTest { 
  mUnlineLocationCallBack: string = ''; 
  jssdkCallSystemInfo(param: string) { 
    PiccLog.info('js参数' + param); 
    let unLineJsBirdgeReq: UnLineJsBirdgeReq = WebImp.parse(param); 
    if (unLineJsBirdgeReq == null) { 
      return; 
    } 
    switch (unLineJsBirdgeReq.method) { 
      case WebviewConstant.METHOD_SYSTEMINFO_SYSTEMINFO: 
        let systemInfo = WebImp.getSystemInfo(); 
        let loadSystemInfoScriptUrl = "javascript:" + unLineJsBirdgeReq.callback + "('" + systemInfo + "')"; 
        break; 
    } 
  } 
}; 
@Entry 
@Component 
struct WebViewPage { 
  webParam: WebParam = router.getParams() as WebParam; 
  url: string = this.webParam.webUrl; 
  webController: webview.WebviewController = new webview.WebviewController(); 
 
  build() { 
    Web({ src: this.url, controller: this.webController }) 
      .javaScriptAccess(true) 
      .javaScriptProxy({ 
        object: this.javascript, 
        name: 'PICAppModel', 
        methodList: ['jssdkCallSystemInfo'], 
        controller: this.webController 
      }) 
  } 
}
HarmonyOS
3天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
Heiang

可以对javaScriptProxy和runJavaScript封装,实现JSBridge通信方案。使用Web组件javaScriptProxy将原生侧接口注入到H5的window对象上,通过runJavaScript接口执行JS脚本到H5中,并在回调中获取脚本执行结果。首先通过Web组件的javaScriptProxy属性,将JSBridgeHandle对象注册到H5的window上,作为H5调用原生的通道。当H5开始加载时,在onPageBegin生命周期中调用initJSBridge()方法初始化JSBridge。

// javaScriptProxy对象  
public get javaScriptProxy() {  
    return {  
        object: {  
            call: this.call  
        },  
        name: "JSBridgeHandle",  
        methodList: ['call'],  
        controller: this.controller,  
    }  
} 
// 使用Web组件加载H5页面  
@Component  
struct JsProxy {  
  private controller: WebviewController = new WebView.WebviewController()  
  private jsBridge: JSBridge = new JSBridge(this.controller)  
  build() {  
    Column(){  
      Web({ src: $rawfile('index.html'), controller: this.controller })  
        .javaScriptProxy(this.jsBridge.javaScriptProxy)  
        .onPageBegin(() => {  
          this.jsBridge.initJSBridge()  
        })  
    }  
  }  
}

在initJSBridge方法中,通过webviewControll.runJavaScript()将JSBridge初始化脚本注入H5执行。当H5调用时,生成window.callID标识回调函数,将callID与调用参数使用JSBridgeHandle.call传到原生侧。通过JSBridgeCallback接收原生侧执行的结果,根据callID找到对应callback执行并且释放内存。

// bridgeKey与bridgeMethod动态生成H5侧调用的入口  
bridgeKey: string = 'JSBridge'  
bridgeMethod: string = 'call'  
// 初始化脚本注入H5侧  
public initJSBridge() {  
    try {  
        this.controller.runJavaScript(`  
            // 接收原生侧结果,执行callback  
            function JSBridgeCallback(id, params){  
                window.JSBridgeMap[id](params)  
            };  
            // 声明调用入口  
            window.${this.bridgeKey} = {  
                ${this.bridgeMethod}(method, params, callback){  
                    window.JSBridgeMap[id] = callback || (() => {});  
                    JSBridgeHandle.call(method, JSON.stringify(paramsObj));  
                },  
            }`)  
    }  
}

JSBridgeHandle.call()是H5调用原生接口的统一入口,在该方法中根据H5调用的方法名,匹配到对应接口去调用。调用结束后通过this.callback()方法将调用结果返回H5。callback方法中使用webviewControll.runJavaScript()调用H5的JSBridgeCallback回传callID和调用结果。

// call方法调用原生侧方法,接收结果  
private call = (fun, params) => {  
    try {  
        const paramsObj = JSON.parse(params)  
        const events = this.exposeManage.methodMap.get(fun)  
        const results = []  
        events.forEach(callFun => {  
            results.push(callFun(paramsObj.data))  
        })  
        Promise.all(results.filter(i => !!i)).then(res => {  
            this.callback(paramsObj.callID, res.length > 1 ? res : res[0])  
        })  
    }  
}  
  
// 通过runJavaScript调用JSBridgeCallback执行回调  
private callback(id, data) {  
    this.controller.runJavaScript(`__JSBridgeCallback__("${id}", ${JSON.stringify(data)})`);  
}

​完整demo参考链接如下:​https://gitee.com/harmonyos/codelabs/tree/master/SelectContact

分享
微博
QQ
微信
回复
3天前
相关问题
HarmonyOS web原生H5如何交互
377浏览 • 1回复 待解决
HarmonyOS 原生js交互
33浏览 • 1回复 待解决
HarmonyOS webH5交互
450浏览 • 1回复 待解决
H5原生调JSbrigedemo示例
43浏览 • 1回复 待解决
HarmonyOS H5应用侧数据交互Demo
378浏览 • 1回复 待解决
H5页面如何ArkTS交互
2865浏览 • 1回复 待解决
HarmonyOS webH5两端数据交互
550浏览 • 1回复 待解决
Webwebview和H5交互
947浏览 • 1回复 待解决
原生调用htmljavascript实现
249浏览 • 1回复 待解决