拍拍贷鸿蒙版H5容器之路

举报
信也科技布道师 发表于 2024/10/28 16:46:32 2024/10/28
【摘要】 背景介绍业务背景2024年1月18日华为宣布:HarmonyOS NEXT 将不再支持 Android系统,基于以上背景及国内信贷业务现状,公司决定启动借款App鸿蒙化项目。下图是2024年6月华为HDC大会上,华为宣布 HarmonyOS NEXT 将面向开发者和先锋用户启动Beta升级,并计划在今年四季度正式商用。技术背景借款APP业务层约70%是基于H5页面构建的,经过多年的迭代,An...

背景介绍

业务背景

2024年1月18日华为宣布:HarmonyOS NEXT 将不再支持 Android系统,基于以上背景及国内信贷业务现状,公司决定启动借款App鸿蒙化项目。

下图是2024年6月华为HDC大会上,华为宣布 HarmonyOS NEXT 将面向开发者和先锋用户启动Beta升级,并计划在今年四季度正式商用。

技术背景

借款APP业务层约70%是基于H5页面构建的,经过多年的迭代,Android与iOS已经有一个非常稳定和强大的Web组件,即:PPDWebUI。为了避免业务层过多地适配,加快App鸿蒙化进程,在技术上只需要开发一个鸿蒙版的PPDWebUI,功能和Android、iOS保持一致,就可以承接已有业务。最终使得业务站点改动的成本最小,并且实现了三端技术架构的统一。

下面的内容主要是介绍我们实现PPDWebUI的方案和实现过程中遇到的困难与挑战。

方案设计

如上图,方案的思路是基于鸿蒙官方提供的ArkWeb进行封装,实现鸿蒙PPDWebUI组件

ArkWeb简介:鸿蒙官方提供的基于谷歌Chromium内核的Web组件,使用的Chromium版本为M114(截止本文编写时)

PPDWebUI组件分为两部分

Web容器,提供H5容器和原生服务

ppdwebui.js,负责JS与Native的通信,本质上是对JsBrdige的封装

PPDWebUI组件的Web容器

原生和H5交互原理

1. 使用JsBridge通信通过javaScriptProxy和runJavaScript来实现JsBridge。使用javaScriptProxy将原生侧接口注入到H5的window对象上,通过runJavaScript接口执行JS脚本到H5中,并在回调中获取脚本执行结果。

调用流程如下图所示:

代码示例:

Web({ src: this.url ?? '', controller: this.webviewController }).javaScriptProxy({ // 将对象注入到web object: this.jsApi, name: "_foo", methodList: ["bar"], controller: this.webviewController })

注入原生服务不采用开始加载页面的时候就注入原生服务的原因:

减少不必要的注入,每次注入原生服务都需要依赖于站点应用引用的js。

更安全可控,每次注入原生服务的时候都可以进行安全校验。通过ArkWeb中的onInterceptRequest方法拦截js替换本地WebUI.js,同时注入原生的插件方法名称,让其挂载在容器上,这样H5就可以调用原生方法,拦截注入代码如下:

onInterceptRequest(event?: InterceptEvent): WebResourceResponse | null { let url: string = event?.request?.getRequestUrl() as string; if (url.match(/^https?:\/\/xxx\.xxx\.com\/[\d.]+\/xxx\.js$/)) { let webResp = new WebResourceResponse(); const resourceMgr: resourceManager.ResourceManager = this.context.resourceManager; let js = buffer.from(resourceMgr.getRawFileContentSync('xxx1.0.js')).toString('utf-8') let respData = `${js};window.PPDWebUI && window.PPDWebUI.initJSConfig && window.PPDWebUI.initJSConfig(${this.appendJsStr})` webResp.setResponseData(respData); webResp.setResponseCode(200) webResp.setResponseEncoding('utf-8') webResp.setResponseMimeType('application/javascript') webResp.setResponseIsReady(true) return webResp } else { return null } }

PPDWebUI容器使用

1. 容器初始化

// 页面即将显示的时候注册服务aboutToAppear(): void { PPDWebUIInitManager.registerService(new LoanServiceCaller());}//自定义WebUI组件初始化WebUI({ webUrl: this.webUrl, props: this.webuiPro, webClient: new WebClientImp(getContext(this)), webUIConfig: new WebUIConfig(this.appendUserAgent,true), webUIHostController: this.webUIHostController}) .layoutWeight(1) .width('100%')

H5业务的适配

1. 升级WebUI.js:所有业务的H5页面均使用统一提供的PPDWebUI.js调用Native的原生能力,H5页面仅需要对 PPDWebUI.js 进行升级,即可以运行在鸿蒙系统上,无需其他特殊适配逻辑。

2. 如有需要针对操作系统的特殊需求,页面可依据Native注入的系统信息来识别当前运行的操作系统,简单高效。

困难与挑战

下面列举了我们在实现鸿蒙版PPDWebUI组件时遇到的问题与解决方案,供大家参考

1. H5页面与原生容器如何联调?

ArkWeb组件支持使用DevTools工具调试前端页面,开发者需通过setWebDebuggingAccess()接口开启Web组件前端页面调试能力,利用DevTools工具可以在电脑上调试移动设备上的前端网页

使用DevTools工具,可以执行以下步骤:

在应用代码中开启Web调试开关,具体如下:

aboutToAppear() { // 配置Web开启调试模式 webview.WebviewController.setWebDebuggingAccess(true); } build() { Column() { Web({ src: 'www.example.com', controller: this.controller }) } }}

开启调试功能需要在DevEco Studio应用工程hap模块的module.json5文件中增加如下权限,添加方法请参考在配置文件中声明权限。

"requestPermissions":[ { "name" : "ohos.permission.INTERNET" } ]

将设备连接上电脑,在电脑端配置端口映射,配置方法如下:

//查找 devtools 远程调试所需的 domain socket 名称,该名称与进程号有关,重启调试应用后,需要重复此步骤,以完成端口转发cat /proc/net/unix | grep devtools// 添加映射 [pid] 替换成实际的进程idhdc fport tcp:9222 localabstract:webview_devtools_remote_[pid]// 查看映射 hdc fport ls示例:hdc shellcat /proc/net/unix | grep devtoolsexithdc fport tcp:9222 localabstract:webview_devtools_remote_3458hdc fport ls

在电脑端Chrome浏览器地址栏中输入chrome://inspect/#devices,页面识别到设备后,就可以开始页面调试。调试效果如下:

2. 导航栏标题不显示或显示不对问题?

通过H5容器的ArkWeb的原生onTitleReceive方法获取H5的docment.title,设置导航标题

Web(...) .onTitleReceive((event) => {     this.props.navTitle = event.title; })

3. H5页面需支持侧滑返回上一次H5页面问题?

通过H5容器的ArkWeb的原生onBackPressed方法监听返回键,拦截返回动作,实现H5页面的侧滑返回上一页。

4. 同一个webview中,先打开A页面,然后setTimeout 2秒 后使用location.href跳转B页面。B页面没有触发webview的任何事件问题?

原因是调用setCustomUserAgent后与web页面的跳转时序相关,Web跳转后才设置UserAgent,这就导致页面跳转了但新UserAgent关联的页面堆栈数仍只有一个WebView

5. 多个JsBridge注入问题?

无法使用 javaScriptProxy 方法注入多个 JsBridg对象,需要在生命周期方法 onControllerAttached() 中 调用 WebViewController 的 registerJavaScriptProxy() 方法注入 JsBridg对象

Web(...) .onControllerAttached(() => { this.webviewController.registerJavaScriptProxy(...) })

未来规划

在业务迭代过程中,为进一步抹平三端差异,计划将Android/iOS离线包方案也移植到鸿蒙版借款App中,提升H5的用户体验

性能优化,开发过程中,也面临ArkWeb加载和丢帧等问题,目前了解到DevEco Profiler提供ArkWeb分析模板,后面也会结合ArkWeb执行流程的关键trace点,来定位问题发生的阶段,并做一些针对性的性能优化

作者简介

Jsiguo,信也科技移动研发资深专家




【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。