HarmonyOS:Web使用Dsbridge与JavaScript完成交互
·
一、简介
Dsbridge跨语言交互组件
HarmonyOS版的DSBridge,通过本库可以在HarmonyOS与JavaScript完成交互,可以相互调用彼此的功能。
目前兼容Android、iOS第三方DSBridge库的核心功能,基本保持原来的使用方式,后续会持续迭代保持与DSBridge库相同的功能,减少前端和客户端的适配工作,另外也会根据鸿蒙的特性做一些定制需求。
二、安装
安装库:
ohpm install @hzw/ohos-dsbridge
三、基本用法
3.1 ArkTS原生侧
在原生新建一个类JsBridge,实现业务API , 通过类来集中统一管理API,方法用@JavaScriptInterface()标注,是不是很眼熟呢,加一个@JavaScriptInterface()标注主要为了使用规范,是自定义的装饰器,与Android保持一致性。
原生调用前端方法效果图
前端调用原生方法效果图
JavaScript侧
- 在JavaScript中初始化dsBridge,通过cdn或者npm安装都可以。
如果项目没有历史包袱,建议直接用m-dsbridge包。
npm i m-dsbridge
// 或者cdn引入
<script src="https://cdn.jsdelivr.net/npm/m-dsbridge/dsBridge.js"></script>
也支持直接用原Android或iOS的DSBridge库的JS脚本。
https://cdn.jsdelivr.net/npm/dsbridge/dist/dsbridge.js
如果m-dsbridge 发生异常,建议切换到 https://cdn.jsdelivr.net/npm/dsbridge/dist/dsbridge.js
- 通过dsBridge对象注册Js函数,供原生调用。
// 注册同步函数
dsBridge.register('showAlert', function (a, b, c) {
// return "原生调用JS showAlert函数"
alert("原生调用JS showAlert函数" + a + " " + b + " " + c)
return true
})
// 注册异步函数
dsBridge.registerAsyn('showAlertAsync', function (a, b, c, callback) {
let counter = 0
let id = setInterval(() => {
if (counter < 5) {
callback(counter, false)
alert("原生调用JS showAlertAsync函数" + a + " " + b + " " + c + " " + counter)
counter++
} else {
callback(counter, true)
alert("原生调用JS showAlertAsync函数" + a + " " + b + " " + c + " " + counter)
clearInterval(id)
}
}, 1000)
})
其中异步的callback函数,如果最后一个参数返回true则完成整个链接的调用,false则可以一直回调给原生,这个就是JavaScript端的一次调用,多次返回。比如需要将JavaScript端进度数据不间断同步到原生,这时就可以派上用场了。
- 通过dsBridge对象调用原生API,第一个参数是原生方法名称,第二参数是原生方法接收的参数,异步方法有第三个参数是回调函数,会接收CompleteHandler异步回调结果。
// 同步
let msg = dsBridge.call('testSync', JSON.stringify({data: 100}))
// 异步, 参数可以是对象或者基本类型
dsBridge.call('testAsync', JSON.stringify({data: 200}), (msg) => {
updateMsg(msg)
})
// 如果你使用的是DSBridge 2.0脚本,异步调用的参数必须是一个对象
dsBridge.call('testAsync', {data: 200}, (msg) => {
updateMsg(msg)
})
前端页面testDsbridge.html 的代码
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<style>
.btn {
width: 600px;
height: 100px;
font-size: 40px;
margin-top: 60px;
}
</style>
<body>
<strong style="font-size:40px;">调用原生方法</strong>
</br>
<button class="btn" id="callArkTSTestStr" type="button" onclick="callArkTSTestStr()">callArkTSTestStr方法</button>
</br>
<button class="btn" id="callArkTSTestArry" type="button" onclick="callArkTSTestArry()">callArkTSTestArray方法</button>
</br>
<button class="btn" id="callArkTStoString2" type="button" onclick="callArkTStoString2()">callArkTStoString2方法</button>
</br>
<button class="btn" id="callTestAsync" type="button" onclick="callTestAsync()">callTestAsync方法</button>
<p style="font-size:40px;" id="resultData"></p>
<script src="https://cdn.jsdelivr.net/npm/m-dsbridge/dsBridge.js"></script>
<script>
function callArkTSTestStr() {
let str = testObjName.testStr();
document.getElementById("resultData").innerHTML = str;
console.info('H5 callArkTSTestStr 调用原生 testStr 方法返回的数据:' + str);
}
function callArkTSTestArry() {
let arrayNum = testObjName.testArray();
console.info('H5 callArkTSTestArry 调用原生 testArray 方法返回的数据:' + arrayNum);
}
function callArkTStoString2() {
testObjName.toString2("这是来自H5数据");
console.info('H5 callArkTStoString2 调用原生 toString2 方法 传递的数据');
}
function callTestAsync() {
// 异步, 参数可以是对象或者基本类型
dsBridge.call('testAsync', JSON.stringify({data: 200}), (msg) => {
console.info('H5 使用 dsBridge 调用原生 testAsync 方法');
})
}
// 注册同步函数
dsBridge.register('showAlert', function (a, b, c) {
// return "原生调用JS showAlert函数"
alert("原生调用JS showAlert函数" + a + " " + b + " " + c)
return true
})
// 注册异步函数
dsBridge.registerAsyn('showAlertAsync', function (a, b, c, callback) {
let counter = 0
let id = setInterval(() => {
if (counter < 2) {
callback(counter, false)
alert("原生调用JS showAlertAsync函数" + a + " " + b + " " + c + " " + counter)
counter++
} else {
callback(counter, true)
alert("原生调用JS showAlertAsync函数" + a + " " + b + " " + c + " " + counter)
clearInterval(id)
}
}, 1000)
})
</script>
</body>
</html>
鸿蒙原生H5DSApi代码
export class H5DSApi{
private cHandler: CompleteHandler = null
/**
* 同步
* @param p
* @returns
*/
@JavaScriptInterface(false)
testSync(p: string): string {
LogUtils.d("testSync: " + JSON.stringify(p))
return "hello native"
}
/**
* 异步
* @param p
* @param handler
*/
@JavaScriptInterface()
testAsync(p: string, handler: CompleteHandler) {
LogUtils.d("testAsync: " + JSON.stringify(p))
this.cHandler = handler
}
}
鸿蒙原生页面代码
import { JavaScriptInterface, OnReturnValue, WebViewControllerProxy } from '@hzw/ohos-dsbridge';
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit'
import { H5DSApi } from './dsbridge/H5DSApi'
import json from '@ohos.util.json';
import { JSON } from '@kit.ArkTS';
const H5_BASE_URL = "https://developer.huawei.com/consumer/cn/"
// const javaScriptMe
const JSmethodList = ["testStr", "testArray", "toString", "toString2", "navToBack", "requestEventData"];
class TestObj {
testStr(): string {
console.log("前端调用了 原生 testStr方法")
return "原生 testStr方法返回的数据"
}
testArray(): Array<Number> {
return [1, 2, 3, 4, 5, 6];
}
toString(): void {
console.log('toString 方法 Web Component toString');
}
toString2(param: String): void {
console.log('toString2 方法 Web Component toString param:' + param);
}
asyncTest(data: string): void {
console.log("async data:" + data);
}
}
@Entry
@Component
struct TestDsBridge {
@State message: string = 'Hello World';
webviewController: webview.WebviewController = new webview.WebviewController()
// 创建Web控制器代理实例
private controller: WebViewControllerProxy = WebViewControllerProxy.createController()
private testObj = new TestObj()
aboutToAppear(): void {
this.controller.setClosePageListener(() => {
return true; // false 会拦截关闭页面
})
try {
// this.controller.addJavascriptObject(new H5DSApi(), "H5DSObj")
// this.controller.supportDS2(true);
this.controller.addJavascriptObject(new H5DSApi())
webview.WebviewController.setWebDebuggingAccess(true);
} catch (error) {
console.error(`aboutToAppear webview 配置Web开启调试模式出错了:ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
}
// JS的注入
registerJavaScriptProxy() {
// javaScriptProxy接口只支持注册一个对象,使用registerJavaScriptProxy注册多个对象请
this.controller.registerJavaScriptProxy(this.testObj, 'testObjName', JSmethodList);
}
build() {
Column({space: 20}) {
Button("使用Dsbridge调用前端 showAlert 方法").onClick(() => {
this.controller.callJs("showAlert", [1, 2, '666'], (data: OnReturnValue) => {
console.log("前端 showAlert 方法回调:" + data)
})
})
Button("使用Dsbridge调用前端 showAlertAsync 方法").onClick(() => {
this.controller.callJs("showAlertAsync", [1, 2, '666'], (data: OnReturnValue) => {
console.log("前端 showAlertAsync 方法回调:" + data)
})
})
// Button('deleteJavaScriptRegister').fontColor(Color.Black).fontSize(20).onClick((_event) => {
// try {
// console.log("getJavaScriptProxy name: ", this.controller.getJavaScriptProxy().name)
// console.log("getJavaScriptProxy name: ", JSON.stringify(this.controller.getJavaScriptProxy().methodList))
// console.log("getJavaScriptProxy name: ", this.controller.getJavaScriptProxy().object)
// //getJavaScriptProxy name: _dsbridge
// // this.webviewController.deleteJavaScriptRegister(JavaScriptProxy_NAME);
// } catch (error) {
// console.error(`移除 testObjName 发生异常 ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
// }
// })
// Web({ src: H5_BASE_URL, controller: this.webviewController })// 将对象注入到web端
Web({ src: $rawfile('testDsbridge.html'), controller: this.controller.webviewController })// 将对象注入到web端
.overviewModeAccess(true)
.databaseAccess(true)
.geolocationAccess(false)
.mediaPlayGestureAccess(true)
.multiWindowAccess(true)
.horizontalScrollBarAccess(false)
.verticalScrollBarAccess(false)
.cacheMode(CacheMode.Default)
.forceDarkAccess(true)
.javaScriptAccess(true) // 允许JS执行
.fileAccess(true) // 允许文件访问
.imageAccess(true) // 允许加载图片资源
.onlineImageAccess(true) // 允许从网络加载图片
.domStorageAccess(true) // 允许使用DOM存储
// .mixedMode(MixedMode.Compatible)
.javaScriptProxy(this.controller.javaScriptProxy) // 设置JS代理
// .javaScriptProxy({
// object: this.testObj,
// name: "android",
// methodList: JSmethodList,
// controller: this.webviewController,
// // 可选参数
// asyncMethodList: ["responseRequest"],
// }
.onControllerAttached(() => {
this.registerJavaScriptProxy()
})
.onLoadIntercept((event) => {
//返回true表示阻止此次加载,否则允许此次加载
return false
})
.onAlert((event) =>{
AlertDialog.show({ message: event.message })
return false
})
.width("100%")
.height("100%")
}
.height('100%')
.width('100%')
}
}
四、HarmonyOS使用Dsbridge了如何注册多个javaScriptProxy代理对象
javaScriptProxy接口只支持注册一个对象,若需要注册多个对象请使用registerJavaScriptProxy。
效果图
原生TestObj代码
class TestObj {
testStr(): string {
console.log("前端调用了 原生 testStr方法")
return "原生 testStr方法返回的数据"
}
testArray(): Array<Number> {
return [1, 2, 3, 4, 5, 6];
}
toString(): void {
console.log('toString 方法 Web Component toString');
}
toString2(param: String): void {
console.log('toString2 方法 Web Component toString param:' + param);
}
asyncTest(data: string): void {
console.log("async data:" + data);
}
}
更多推荐









所有评论(0)