概述

在鸿蒙开发过程中,经常会遇到鸿蒙h5混合开发的场景,涉及到混合开发,避不开的就是两个端的通信,本文理清了鸿蒙端使用webView的runJavaScript调用h5的方法,以及h5侧调用鸿蒙侧能力的方法,附上源码以及效果。

实战前准备

准备web页面模拟h5

在鸿蒙项目的src/main/resources/rawfile 目录下新建myWeb.html,以便于Web组件引用,Web组件显示网页的方法详情可阅读之前的博客:鸿蒙实战之登录 ,Span高亮隐私协议字体,Web组件展示隐私协议,并设置输入时键盘避让,没有废话,全是干货-CSDN博客

 这里是一个web页面,页面中有一个按钮,点击这个按钮,可调用鸿蒙侧的函数,

window.hm.postToH5Message()  // 这个window对象下的函数是鸿蒙侧给h5端注册的函数

 myWeb.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta content="width=device-width, initial-scale=1.0" name="viewport">
    <title>鸿蒙h5通信示例</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            margin-top: 50px;
        }
        button {
            padding: 10px 20px;
            margin: 10px;
            font-size: 16px;
            cursor: pointer;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 5px;
        }
        button:hover {
            background-color: #45a049;
        }
        #msg {
            margin-top: 20px;
            font-size: 24px;
            font-weight: bold;
        }
        #result {
            margin-top: 20px;
            font-size: 18px;
        }
    </style>
</head>
<body>
<h1>我是H5</h1>
<button onclick="getHmMessage()">点我调用鸿蒙侧函数</button>
<div id="msg">还未调用</div>
<div id="result"></div>

<script>
    let msg = '';
    // H5侧调用鸿蒙侧函数
    function getHmMessage() {
        window.hm.postToH5Message()

    }

    // 鸿蒙侧调用的函数
    function changeMessage(hmMsg) {
        msg = hmMsg
        document.getElementById("msg").textContent = msg;
    }
</script>
</body>
</html>

开始实战

鸿蒙调用h5的函数

下面是官方api文档:

@ohos.web.webview (Webview)-ArkTS API-ArkWeb(方舟Web)-应用框架 - 华为HarmonyOS开发者https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V14/js-apis-webview-V14#runjavascript

鸿蒙调用h5侧的函数,官方提供了一个方法,就是webView控制器上的runJavaScript方法,这个方法接收一个字符串,这个字符串就是h5侧被调用的方法,注意:传参时要注意一个问题,就是咱这里的调用这个方法,是直接写字符串去调用,但是如果要在调用方法里边传参,且正好是个字符串,就需要区分双引号和单引号,保证对runJavaScript穿的方法收尾对应的是一组符号,而方法内部传参对应的是一组符号,示例如下:

this.controller.runJavaScript('changeMessage("调用h5方法成功")')

 在鸿蒙侧准备一个按钮,去点击触发h5的方法

 Button('runJavaScript方法调用js方法')
          .onClick(() => {
            if (this.controller) {
              this.controller.runJavaScript('changeMessage("调用h5方法成功")')
            }
          })

在h5侧声明这个方法

  // 鸿蒙侧调用的函数
    function changeMessage(hmMsg) {
        msg += hmMsg
        document.getElementById("msg").textContent = msg;
    }

很明显,鸿蒙侧调用这个changeMessage之后h5侧的msg就会一直拼上鸿蒙这边传过去的参数,效果如下:

h5调用鸿蒙:

鸿蒙给h5注册方法

h5调用鸿蒙侧的能力,官方也提供了一个api就是Web组件的javaScriptProxy方法,

Web-ArkTS 组件-ArkWeb(方舟Web)-应用框架 - 华为HarmonyOS开发者

还有webView控制器的registerJavaScriptProxy方法,Web-ArkTS 组件-ArkWeb(方舟Web)-应用框架 - 华为HarmonyOS开发者​​​​​​

二者的用法一样,接收的参数也差不多,但是也有点区别:

javaScriptProxy和registerJavaScriptProxy有什么区别,能注册多少个对象-Web开发(ArkWeb)-Web框架-应用框架开发-开发 - 华为HarmonyOS开发者

从功能上讲,二者都可以注入JavaScript对象到window对象中,并在window对象中调用该对象的方法。

从注册对象上讲,前者只能注册一个对象,后者可以注册多个对象。

从生命周期上讲,javaScriptProxy在Web组件初始化调用,registerJavaScriptProxy在Web组件初始化完成后调用。

从接口上讲,javaScriptProxy是Web组件的方法,而registerJavaScriptProxy是WebviewController的方法。

javaScriptProxy可以参考javaScriptProxy,registerJavaScriptProxy可以参考registerJavaScriptProxy

 这里就介绍JavaScriptProxy的用法,先分析这个属性接收的参数

名称

类型

必填

说明

object

object

参与注册的对象。只能声明方法,不能声明属性。

name

string

注册对象的名称,与window中调用的对象名一致。

methodList

Array<string>

参与注册的应用侧JavaScript对象的同步方法。

controller

WebController | WebviewController9+

-

asyncMethodList12+

Array<string>

参与注册的应用侧JavaScript对象的异步方法。异步方法无法获取返回值。

permission12+

string

json字符串,默认为空,通过该字符串配置JSBridge的权限管控,可以定义object、method一级的url白名单。

示例请参考前端页面调用应用侧函数

 这里只需关注必传参数,其他参数按需传入即可,案例中传入了四个参数,具体如下:

鸿蒙侧被调用的方法

   // h5侧调用时鸿蒙侧弹一个窗
     postToH5Message() {
           AlertDialog.show({ message: '鸿蒙侧被h5调用了', })
         }

 给javaScriptProxy方法传参



  Web({
        src: $rawfile('myWeb.html'),
        controller: this.controller
      })
        .layoutWeight(1)
        .javaScriptProxy({
          // 参与h5端注册的对象
          object: {
            postToH5Message: () => {
              this.postToH5Message();
            },
          },
          // 注册的js对象名
          name: "hm",
          // 注册的js方法
          methodList: ["postToH5Message"],
          // web的控制器
          controller: this.controller
        })

h5调用鸿蒙侧方法

到此咱们已经将鸿蒙侧的方法注册到了h5的window对象下的hm对象下,h5侧调用就只需要在需要的时机调用window.hm.postToH5Message()方法即可调用鸿蒙端的能力,示例中点击按钮之后,调用鸿蒙侧的方法,鸿蒙侧就会弹窗提示被调用:

<body>
<h1>我是H5</h1>
<button onclick="getHmMessage()">点我调用鸿蒙侧函数</button>
<div id="msg">还未调用</div>
<div id="result"></div>

<script>
    let msg = '';
    // H5侧调用鸿蒙侧函数
    function getHmMessage() {
        window.hm.postToH5Message()

    }

    // 鸿蒙侧调用的函数
    function changeMessage(hmMsg) {
        msg += hmMsg
        document.getElementById("msg").textContent = msg;
    }
</script>
</body>

总结: 

至此,鸿蒙侧调用h5侧方法,以及h5侧调用鸿蒙侧能力的一个小案例就完成了,在实际开发中可根据使用场景去灵活搭配使用, 通信的核心就是鸿蒙侧两个api  :鸿蒙调用h5就使用web控制器的runJavaScript方法,h5调用鸿蒙侧就使用javaScriptProxy方法给h5侧的window对象注册函数,去调用鸿蒙侧能力

完整代码:

h5侧:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta content="width=device-width, initial-scale=1.0" name="viewport">
    <title>鸿蒙h5通信示例</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            margin-top: 50px;
        }
        button {
            padding: 10px 20px;
            margin: 10px;
            font-size: 16px;
            cursor: pointer;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 5px;
        }
        button:hover {
            background-color: #45a049;
        }
        #msg {
            margin-top: 20px;
            font-size: 24px;
            font-weight: bold;
        }
        #result {
            margin-top: 20px;
            font-size: 18px;
        }
    </style>
</head>
<body>
<h1>我是H5</h1>
<button onclick="getHmMessage()">点我调用鸿蒙侧函数</button>
<div id="msg">还未调用</div>
<div id="result"></div>

<script>
    let msg = '';
    // H5侧调用鸿蒙侧函数
    function getHmMessage() {
        window.hm.postToH5Message()

    }

    // 鸿蒙侧调用的函数
    function changeMessage(hmMsg) {
        msg += hmMsg
        document.getElementById("msg").textContent = msg;
    }
</script>
</body>
</html>

鸿蒙侧:

import webview from '@ohos.web.webview'


@Entry
@Component
struct WebPage {
  controller: webview.WebviewController = new webview.WebviewController()
  @State msg: string = '我是鸿蒙侧'

  postToH5Message() {
    AlertDialog.show({ message: '鸿蒙侧被h5调用了', })
  }

  build() {
    Column({ space: 20 }) {
      Text('鸿蒙h5通信')
        .margin({ top: 20 })
        .fontSize(26)
        .fontWeight(FontWeight.Bold)
        .width('100%')
        .height(60)
        .textAlign(TextAlign.Center)
        .backgroundColor('#F6662F')
      Column({ space: 20 }) {

        Text(this.msg)
          .fontSize(24)
          .fontWeight(FontWeight.Bold)

        Button('runJavaScript方法调用js方法')
          .onClick(() => {
            if (this.controller) {
              this.controller.runJavaScript('changeMessage("调用h5方法成功")')
            }
          })
      }.layoutWeight(1)
      .justifyContent(FlexAlign.Center)

      Web({
        src: $rawfile('myWeb.html'),
        controller: this.controller
      })
        .layoutWeight(1)
        .javaScriptProxy({
          // 参与h5端注册的对象
          object: {
            postToH5Message: () => {
              this.postToH5Message();
            },
          },
          // 注册的js对象名
          name: "hm",
          // 注册的js方法
          methodList: ["postToH5Message"],
          // web的控制器
          controller: this.controller
        })
    }
    .backgroundColor(Color.Gray)
    .height('100%')
    .width('100%')
  }
}

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐