1. APP 内嵌网页与应用互操作概述
在通常的 APP 开发中,经常会采用内嵌网页的形式,通过网页来展现丰富的动态内容,虽少了很多原生开发的功能,但是这么做无可厚非,毕竟 APP 需要适配的系统平台很多,比如安卓、苹果、各种 PC 端,现在还有如日中天的鸿蒙系统;为每一种平台做定制难度还是很大的,但是这些平台的 APP 都支持内嵌网页,通过网页可以屏蔽各平台的差异,从而减少开发难度,提高开发效率。
当然,单纯的内嵌网页还是有不少局限性的,不过,可以通过应用和网页的互操作来提升用户的使用体验,所谓的互操作,就是可以在网页中调用 APP 中的方法,或者在 APP 中执行网页中的脚本,鸿蒙通过 web 组件中的 javaScriptProxy 接口提供了注册应用侧 js 对象到 web 组件中的方法:
javaScriptProxy(javaScriptProxy: { object: object, name: string, methodList: Array<string>,controller: WebviewController | WebController, asyncMethodList?: Array<string>})
复制代码
当然,也可以使用 WebviewController 的 registerJavaScriptProxy 接口:
registerJavaScriptProxy(object: object, name: string, methodList: Array<string>, asyncMethodList?: Array<string>): void
复制代码
在应用侧执行网页中的脚本使用的是 WebviewController 类的 runJavaScript 接口:
runJavaScript(script: string): Promise<string>
复制代码
通过上述几个接口,就可以实现强大的 Web 组件与应用互操作功能
2. Web 组件与应用互操作示例
本示例运行后的界面如下所示
单击网页中“计算应用侧的乘法”按钮,可以自动计算 app 上部的乘法,计算后的界面如下所示;
在 app 内调节 RGB 颜色分量,设置好选择的背景色后,单击应用中的“设置网页背景色”按钮,可以设置网页的背景色:
下面详细介绍创建该应用的步骤。
步骤 1:创建 Empty Ability 项目。
步骤 2:在 module.json5 配置文件加上对权限的声明:
"requestPermissions": [ { "name": "ohos.permission.INTERNET" } ]
复制代码
这里添加了获取互联网信息的权限。
步骤 3:添加资源文件 demo.html,路径为 src/main/resources/rawfile/demo.html,内容如下:
<!-- index.html --><!DOCTYPE html><html><meta charset="utf-8">
<body> <div style="text-align: center;font-size: larger;"> <button type="button" onclick="compute()">计算应用侧的乘法</button> </div> <div id="info">
</div></body><script type="text/javascript"> function compute() { let multiplier = multipObj.getMultiplier(); let multiplicand = multipObj.getMultiplicand(); let product = multiplier * multiplicand multipObj.setProduct(product); }
function setbackcolor(color) { document.body.style.backgroundColor = color; }</script>
</html>
复制代码
该资源文件很重要,是本示例互操作实现的基础。
步骤 4:在 Index.ets 文件里添加如下的代码:
import web_webview from '@ohos.web.webview'
//注册到web组件中的应用侧js对象class ComputeObj { constructor() { }
public multiplier: number = 0.618 public multiplicand: number = 3.14 public product: string = "乘积"
//获取乘数 public getMultiplier() { return this.multiplier; }
//获取被乘数 public getMultiplicand() { return this.multiplicand; }
//设置乘积 public setProduct(newProduct: number) { this.product = newProduct.toString(); }}
@Entry@Componentstruct Index { @State computeObj: ComputeObj = new ComputeObj() jsName: string = "multipObj" @State rColor: number = 100 @State gColor: number = 100 @State bColor: number = 100 @State backColor: string = "#646464" scroller: Scroller = new Scroller() controller: web_webview.WebviewController = new web_webview.WebviewController()
build() { Row() { Column() { Text("Web组件与应用互操作示例") .fontSize(14) .fontWeight(FontWeight.Bold) .width('100%') .textAlign(TextAlign.Center) .padding(5)
Text("输入乘数和被乘数,在web组件中单击计算按钮进行计算") .fontSize(14) .width('100%') .textAlign(TextAlign.Start) .padding(5)
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { TextInput({ text: this.computeObj.multiplier.toString() }) .onChange((value) => { this.computeObj.multiplier = parseFloat(value) }) .type(InputType.NUMBER_DECIMAL) .width(110) .fontSize(11) .flexGrow(1)
Text("*") .fontSize(14) .width(20) .flexGrow(0)
TextInput({ text: this.computeObj.multiplicand.toString() }) .onChange((value) => { this.computeObj.multiplicand = parseFloat(value) }) .type(InputType.NUMBER_DECIMAL) .width(100) .fontSize(11) .flexGrow(1)
Text("=") .fontSize(14) .width(20) .flexGrow(0)
TextInput({ text: `${this.computeObj.product}` }) .width(100) .fontSize(11) .enabled(false) .flexGrow(1) } .width('100%') .padding(5)
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { Text("R颜色分量") .fontSize(14) .width(100) .flexGrow(0)
Slider({ value: this.rColor, min: 0, max: 255 }) .onChange((value: number, mode: SliderChangeMode) => { this.rColor = value this.computeBackcolor() }) .flexGrow(1) } .width('100%') .padding(5)
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { Text("G颜色分量") .fontSize(14) .width(100) .flexGrow(0)
Slider({ value: this.gColor, min: 0, max: 255 }) .onChange((value: number, mode: SliderChangeMode) => { this.gColor = value this.computeBackcolor() }) .flexGrow(1) } .width('100%') .padding(5)
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { Text("B颜色分量") .fontSize(14) .width(100) .flexGrow(0)
Slider({ value: this.bColor, min: 0, max: 255 }) .onChange((value: number, mode: SliderChangeMode) => { this.bColor = value this.computeBackcolor() }) .flexGrow(1) } .width('100%') .padding(5)
Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { Text(`选中的颜色:${this.backColor}`) .fontSize(14) .height(30) .width(150) .backgroundColor(this.backColor)
Button("设置网页背景色") .onClick(() => { this.controller.runJavaScript(`setbackcolor('${this.backColor}')`) }) .width(140) .fontSize(14) .flexGrow(0) } .width('100%') .padding(5)
Scroll(this.scroller) { Web({ src: $rawfile("demo.html"), controller: this.controller }) .padding(10) .width('100%') .textZoomRatio(300) .backgroundColor(0xeeeeee) //注册js对象 .javaScriptProxy({ object: this.computeObj, name: this.jsName, methodList: ["getMultiplier", "getMultiplicand", "setProduct"], controller: this.controller, }) } .align(Alignment.Top) .backgroundColor(0xeeeeee) .height(300) .flexGrow(1) .scrollable(ScrollDirection.Vertical) .scrollBar(BarState.On) .scrollBarWidth(20) } .width('100%') .justifyContent(FlexAlign.Start) .height('100%') } .height('100%') }
//计算背景色 computeBackcolor() { this.backColor = "#" + parseInt(this.rColor.toFixed(0)).toString(16) + parseInt(this.gColor.toFixed(0)).toString(16) + parseInt(this.bColor.toFixed(0)).toString(16) }}
复制代码
步骤 5:编译运行,可以使用模拟器或者真机。
步骤 6:具体的操作过程上面讲过了,就不再赘述了。
3. 关键功能分析
第一个是要注册到 web 组件中的 js 对象,在 API12 中写成 class 的形式,
//注册到web组件中的应用侧js对象class ComputeObj { constructor() { }
public multiplier: number = 0.618 public multiplicand: number = 3.14 public product: string = "乘积"
//获取乘数 public getMultiplier() { return this.multiplier; }
//获取被乘数 public getMultiplicand() { return this.multiplicand; }
//设置乘积 public setProduct(newProduct: number) { this.product = newProduct.toString(); }}
复制代码
第二个是注册对象的代码:
Web({ src: $rawfile("demo.html"), controller: this.controller }) .padding(10) .width('100%') .textZoomRatio(300) .backgroundColor(0xeeeeee) //注册js对象 .javaScriptProxy({ object: this.computeObj, name: this.jsName, methodList: ["getMultiplier", "getMultiplicand", "setProduct"], controller: this.controller, })
复制代码
这里 javaScriptProxy 方法的各个参数一定要保证准确,否则在 web 组件中调用会失败,其中 name 和 demo.html 中使用的注册对象名称 multipObj 要完全一致,methodList 参数为注册对象声明的方法,也要保证拼写正确。
最后是计算背景的代码:
//计算背景色 computeBackcolor() { this.backColor = "#" + parseInt(this.rColor.toFixed(0)).toString(16) + parseInt(this.gColor.toFixed(0)).toString(16) + parseInt(this.bColor.toFixed(0)).toString(16) }
复制代码
把选中的颜色分量拼凑成了颜色字符串,最前面的是字符 #。
(本文作者原创,除非明确授权禁止转载)
本文源码地址:
https://gitee.com/zl3624/harmonyos_network_samples/tree/master/code/web/WebAppInteropDemo
本系列源码地址:
https://gitee.com/zl3624/harmonyos_network_samples
评论