本篇Codelab主要介绍H5如何调用原生侧相关功能,并在回调中获取执行结果。以“获取通讯录”为示例分步讲解JSBridge桥接的实现。
Web组件:提供具有网页显示能力的Web组件。
@ohos.web.webview:提供web控制能力。
源码下载
我们首先需要完成HarmonyOS开发环境搭建,可参照如下步骤进行。
DevEco Studio版本:DevEco Studio 3.1 Release。
HarmonyOS SDK版本:API version 9。
设备类型:华为手机或运行在DevEco Studio上的华为手机设备模拟器。
HarmonyOS系统:3.1.0 Developer Release。
安装DevEco Studio,详情请参考下载和安装软件。
设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。
如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。
开发者可以参考以下链接,完成设备调试的相关配置:使用真机进行调试
本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在源码下载或gitee中提供。
├──entry/src/main/ets // 代码区
│ ├──common // 公共代码区
│ │ ├──constants // 公共常量
│ │ │ ├──CodeConstant.ets // 异步脚本模板
│ │ │ └──CommonConstant.ets // 公共常量和样式常量
│ │ └──utils // 工具类
│ │ ├──JsBridge.ets // 桥接类
│ │ └──Logger.ets // 日志类
│ ├──entryability
│ │ └──EntryAbility.ets // 程序入口
│ ├──pages
│ │ └──SelectContact.ets // 主页面
│ └──viewmodel // 项目所需数据类型定义
│ ├──JavaScriptItem.ets // javaScriptProxy数据格式
│ └──ParamsItem.ets // 回调参数数据格式
└──entry/src/main/resources // 资源入口(rawfile文件夹中存放html)
└──rawfile
├──js
│ └──mainPage.js // H5调用函数文件
├──css
│ └──main.css // H5样式文件
└──MainPage.html // H5页面
在initJSBridge方法中,通过webviewControll.runJavaScript()将JSBridge初始化脚本注入H5执行。其中callID用来标识H5回调;JSBridgeCallback方法用来执行H5侧回调;window.ohosCallNative对象给H5侧提供调用函数。
// CodeConstant.ets
/**
* 异步执行脚本
*/
export const code = `
const JSBridgeMap ={};
let callID =0;
// 执行H5回调函数
function JSBridgeCallback (id, params){
JSBridgeMap[id](params);
JSBridgeMap[id]= null;
delete JSBridgeMap[id];
}
// 在window中声明callNative方法供H5调用
window.ohosCallNative ={
callNative(method, params, callback){
const id = callID++;
const paramsObj ={
callID: id,
data: params || null
}
JSBridgeMap[id]= callback ||(()=>{});
JSBridgeHandle.call(method, JSON.stringify(paramsObj));
}
}
`;
通过Web组件的javaScriptProxy属性,将JSBridgeHandle对象注册到H5侧的window上,作为H5调用原生的通道。
// JsBridge.ets
export defaultclassJsBridge{
/**
* 注入JavaScript对象到window对象中
*
* @returns javaScriptProxy object
*/
get javaScriptProxy(): JavaScriptItem {
return{
object:{
call:this.call
},
name:"JSBridgeHandle",
methodList:['call'],
controller:this.controller
}as JavaScriptItem;
}
}
// SelectContact.ets
@Entry
@Component
struct SelectContact {
webController: WebView.WebviewController =newWebView.WebviewController();
private jsBridge: JSBridge =newJSBridge(this.webController);
build(){
Column(){
Web({
src:$rawfile('MainPage.html'),
controller:this.webController
})
.javaScriptAccess(true)
.javaScriptProxy(this.jsBridge.javaScriptProxy)
...
}
...
}
}
call方法作为H5调用原生侧接口的统一入口,在该方法中根据H5调用的方法名,匹配到对应的接口后调用,调用结束后通过this.callback()方法,将调用结果回传到H5。
// JsBridge.ets
/**
* 定义桥接类
*/
export defaultclassJsBridge{
/**
* 将ArkTS侧数据传递给call方法
*/
call =(func: string, params: string):void=>{
const paramsObject: ParamsItem = JSON.parse(params);
switch(func){
case'chooseContact':
result =this.chooseContact();
break;
default:
break;
}
result.then((data: string)=>{
this.callback(paramsObject?.callID, data);
})
}
/**
* 将ArkTS侧数据传递到H5
*/
callback =(id: number, data: string):void=>{
this.controller.runJavaScript(`JSBridgeCallback("${id}",${JSON.stringify(data)})`);
}
}
实现了上述桥接逻辑后,在H5侧只需要调用ohosCallNative方法,将函数名以及回调函数传递到ArkTS。
// mainPage.js
function chooseContact(){
window.ohosCallNative.callNative('chooseContact',{},(data)=>{
...
});
}
您已经完成了本次Codelab的学习,并了解到以下知识点: