如何低成本的上线一个鸿蒙原生APP,充分利用已有小程序业务资源改造整合,提高APP开发效率~
一、如何尽可能的复用已有代码资源~
为原生鸿蒙系统开发一个鸿蒙APP,其实不止是开发团队的工作,有大量的代码适配、测试工作去做,其实在真实的落地业务中,业务部门的第一反应就是:能不能直接复用安卓端的代码,业务部门也没有这么多精力来配合。
一个业务用iOS写过一遍,也上线了安卓,还有微信小程序,能不能把这些代码直接搬过去,不需要重新去写代码?
今天分享一个最近使用的技术路径,核心思路是:不去做颠覆性的开发,只需要开发一个宿主APP,然后集成一个小程序容器的SDK,让现有的小程序包体就可以直接跑在鸿蒙APP里,看看有没有帮助
二、整体思路复盘
第一种是全部用鸿蒙原生代码重写,每个小程序对应一套 ArkUI 代码。好处是性能最优,坏处是工期长,几十个小程序全部重写,加上测试,上线周期拖得很长,而且每次功能迭代都要同步改两套代码,维护成本翻倍。
第二个就是混合开发架构。鸿蒙只做一个壳,集成小程序容器 SDK,底座用原生实现,上面所有的业务功能全部用小程序承载。不需要重写已有的小程序代码,直接把现有包体复用进来就行。
整个混合开发的核心,是把 APP 分成两层:
Native 层(鸿蒙原生):负责启动框架、账户登录、支付通道、推送通知等核心能力,这些就只能用鸿蒙原生代码实现,否则就无法通过。
小程序层(业务功能):具体的业务场景全部以小程序形式存在,每个小程序独立开发、独立发布、独立更新,和 Native 层相互解耦。

三、技术架构:三层结构
整体技术架构分为三层,从下到上分别是:
第一层:HarmonyOS 底层。 这是 APP 的根基,包括启动框架、账户体系、支付通道、推送通道等核心能力,都用鸿蒙原生代码实现。这一层相当于整个 APP 的底座,不随业务变化而改动。
第二层:FinClip 小程序容器 SDK。 这是本文的核心。通过集成 SDK,鸿蒙 APP 获得了运行微信小程序的能力。SDK 内部包含 JavaScript 引擎、双线程运行时、渲染层、组件库、路由系统、JSBridge 和端能力 API。业务小程序运行在这个容器里,与宿主 APP 完全隔离,一个小程序出问题不会影响整个 APP。
第三层:业务小程序层。 停车找位、会议室预约、活动报名这些具体场景,每个都是独立的小程序包,独立开发、独立发布、独立更新。用户从停车场小程序切换到会议室预约小程序,整个过程不需要重新登录,也不占用额外的系统资源。

四、第一步:配置 OHPM 仓库
在 HarmonyOS 项目里接入 FinClip SDK,第一步是配置仓库地址,让项目能找到 SDK 依赖包。
在项目根目录创建 .ohpmrc 文件,配置 OHPM 仓库地址:
registry=https://ohpm.openharmony.cn/ohpm/
@finclip:registry=https://ohpm.finogeeks.com/repos/ohpm
然后在 oh-package.json5 中添加核心依赖:
{
"@finclip/sdk": "latest"
}
执行 ohpm install 完成安装。如果在内网环境,可以从 FinClip 官网下载 SDK 的 HAR 包,放到项目目录后以本地路径方式引用:
{
"@finclip/sdk": "file:../har/FinClipSDK.har",
"@finclip/share-sdk": "file:../har/FinClipShareSDK.har"
}
五、第二步:配置 Ability
由于鸿蒙共享包无法自动注册 Ability,需要宿主 APP 显式声明。在 module.json5 中配置:
{
"name": "AppletAbility",
"srcEntry": "./ets/appletAbility/AppletAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:app_icon",
"launchType": "specified",
"startWindowIcon": "$media:app_icon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"removeMissionAfterTerminate": true
}
这里有一个细节:launchType 必须设为 specified,否则同一个小程序无法同时打开多个实例。在多业务场景下,用户可能在停车小程序和会议室预约之间频繁切换,不支持多实例体验会很差。removeMissionAfterTerminate 设为 true 确保小程序关闭后不在系统任务列表残留。
Ability 的具体实现参考文档:
import { FinAppClient } from '@finclip/sdk';
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
export default class AppletAbility extends UIAbility {
onCreate() {
}
onDestroy() {
}
async onWindowStageCreate(windowStage: window.WindowStage) {
const client = FinAppClient.getInstance();
await client?.initContext(this.context, windowStage, this.launchWant.parameters);
}
async onWindowStageDestroy() {
}
onForeground() {
}
onBackground() {
}
}
六、第三步:初始化 SDK
SDK 依赖添加完成后,需要在 APP 启动时完成初始化,这一步很关键,顺序不能搞错。
import { FinAppletShare } from '@finclip/share-sdk';
import { FinAppletContact } from '@finclip/contact-sdk';
import { FinAppletBluetooth } from '@finclip/bluetooth-sdk';
import { FinAppClient, IFinAppConfig } from '@finclip/sdk';
// 第一步:初始化扩展 SDK(顺序不能错)
FinAppletShare.init('wxAppId', 'scheme')
FinAppletContact.init()
FinAppletBluetooth.init()
// 第二步:初始化核心 SDK
const finAppConfig: IFinAppConfig = {
finStoreConfigs: [{
apiServer: 'apiServer',
sdkKey: 'sdkKey',
sdkSecret: 'sdkSecret',
apmServer: 'apmServer'
}]
}
FinAppClient.init(finAppConfig, this.context, 'AppletAbility')
扩展 SDK 包括分享、通讯录、蓝牙、日历、剪贴板、相册等模块,按需引入即可。只要用了扩展 SDK,就必须保证版本号与核心 SDK 一致,且初始化顺序在核心 SDK 之前。
顺序千万不能搞反。 必须先初始化扩展 SDK,再初始化核心 SDK。如果反过来,扩展能力不会正确注册到运行时,分享、推送这类功能调不起来,但日志里不会报明显错误,排查起来很费时间。
七、第四步:启动小程序
SDK 初始化完成后,就可以启动小程序了。
// 最简单的启动方式:通过 appId 直接拉起
FinAppClient.getInstance().startApplet({
appId: '小程序的 appId',
apiServer: '服务器的地址'
})
// 如果需要跳转到特定页面,携带参数
FinAppClient.getInstance().startApplet({
appId: '小程序的 appId',
apiServer: '服务器的地址',
startParams: {
path: '/pages/index/index',
query: 'floor=3&type=parking'
}
})
startApplet 是在 APP 里启动小程序的统一入口,只需要传小程序的 appId 和接口地址,不需要关心小程序的文件结构。容器会自动下载包体、启动 JS 引擎、完成页面渲染,整个过程由 SDK 内部完成,调用方不需要写额外的启动逻辑。
八、第五步:发布和更新
小程序开发完成后的发布流程,和在微信里差不多。
第一步: 开发完成后,在小程序管理后台上传小程序包体,填写版本信息和更新日志。
第二步: 提交审核。内部使用的业务小程序,可以跳过审核直接上线;
第三步: 审核通过后,一键发布。可以选择全量发布(推送给所有用户)或灰度发布。
第四步: 用户打开 APP,SDK 自动检测到新版本,静默下载,用户下次打开时自动加载最新版本。整个过程用户无感知,不需要去应用市场更新 APP。
九、几个常见的问题
坑一:扩展 SDK 初始化顺序搞反
这是接入过程中最容易遇到的问题。
分享功能调不起来,点击分享按钮没有任何反应,日志里也找不到相关报错。排查了一圈,发现原因是扩展 SDK 在核心 SDK 之后才调用了初始化方法,导致分享模块没有正确注册到运行时。
解决办法:严格遵循"先扩展 SDK、后核心 SDK"的顺序,写代码审核时这一点必须过审。
坑二:DevEco Studio 版本过低
集成完成后,Ability 启动时报 can't find module '@finclip/sdk' 的错误,但依赖明明已经加了。
原因是项目使用的 DevEco Studio 版本低于 5.0.3.300,OHPM 无法正确解析 SDK 的依赖声明。
解决办法:升级 DevEco Studio 到 5.0.3.300 以上,同时确认手机系统版本在 3.0.0.22 以上。集成前的环境检查表要把这两项列进去,不能忽略。
坑三:多实例支持没配置
用户从停车小程序切换到会议室预约小程序,发现切换不回来,必须关掉重新打开。
原因是 Ability 的 launchType 没有设为 specified,同一个小程序无法同时打开多个实例。在多业务场景下,用户频繁切换是小概率事件,但一旦发生就是功能性问题。
解决办法:在 module.json5 中配置 "launchType": "specified",确保每个小程序都能独立运行,互不干扰。
十、性能数据
接入完成后,实测了几个关键指标:
冷启动耗时: Ability 模式下约 1.8 秒(测试机型:Mate 60 Pro,HarmonyOS 5.0)。和原生 APP 的冷启动体验基本持平,用户感知不到明显差异。
包体积影响: 核心 SDK 增量约 3.2MB,每个扩展 SDK 约 200-500KB。如果只集成两三个业务场景,扩展 SDK 总增量控制在 1MB 以内。相比重写同等规模的原生模块(预估 8-10 人月),接入成本不到十分之一。
多小程序内存占用: 同时运行 3 个小程序,内存占用峰值约 280MB,与 HarmonyOS 系统小程序框架的平均水平基本一致。
整体看下来,如果公司有较多存量小程序资源,要快速上线鸿蒙 APP,混合开发是不错的选择。工期从"重写几十套 ArkUI 代码"压缩到"集成一个 SDK 加配置几个入口",现有包体直接复用,测试成本也低。
前提是对技术边界有清醒认识:强渲染类场景(游戏、AR/VR)和重度依赖微信生态的商业化功能,不适合这套方案,这些还是要走原生路线。
- 点赞
- 收藏
- 关注作者
评论(0)