如何低成本的上线一个鸿蒙原生APP,充分利用已有小程序业务资源改造整合,提高APP开发效率~

举报
AI Coing中 发表于 2026/05/13 11:13:27 2026/05/13
【摘要】 如何在不大规模重写代码的前提下,快速上线一个鸿蒙原生APP,分享一下基于小程序容器SDK 搭建一个“Native+小程序容器”的混合开发技术,让从"重写几十套 ArkUI 代码"压缩到"集成一个 SDK 加配置几个入口",复用已有代码资源,大幅度降低开发成本~

一、如何尽可能的复用已有代码资源~

为原生鸿蒙系统开发一个鸿蒙APP,其实不止是开发团队的工作,有大量的代码适配、测试工作去做,其实在真实的落地业务中,业务部门的第一反应就是:能不能直接复用安卓端的代码,业务部门也没有这么多精力来配合。
一个业务用iOS写过一遍,也上线了安卓,还有微信小程序,能不能把这些代码直接搬过去,不需要重新去写代码?
今天分享一个最近使用的技术路径,核心思路是:不去做颠覆性的开发,只需要开发一个宿主APP,然后集成一个小程序容器的SDK,让现有的小程序包体就可以直接跑在鸿蒙APP里,看看有没有帮助

二、整体思路复盘

第一种是全部用鸿蒙原生代码重写,每个小程序对应一套 ArkUI 代码。好处是性能最优,坏处是工期长,几十个小程序全部重写,加上测试,上线周期拖得很长,而且每次功能迭代都要同步改两套代码,维护成本翻倍。

第二个就是混合开发架构。鸿蒙只做一个壳,集成小程序容器 SDK,底座用原生实现,上面所有的业务功能全部用小程序承载。不需要重写已有的小程序代码,直接把现有包体复用进来就行。

整个混合开发的核心,是把 APP 分成两层:

Native 层(鸿蒙原生):负责启动框架、账户登录、支付通道、推送通知等核心能力,这些就只能用鸿蒙原生代码实现,否则就无法通过。

小程序层(业务功能):具体的业务场景全部以小程序形式存在,每个小程序独立开发、独立发布、独立更新,和 Native 层相互解耦。

三、技术架构:三层结构

整体技术架构分为三层,从下到上分别是:

第一层:HarmonyOS 底层。 这是 APP 的根基,包括启动框架、账户体系、支付通道、推送通道等核心能力,都用鸿蒙原生代码实现。这一层相当于整个 APP 的底座,不随业务变化而改动。

第二层:FinClip 小程序容器 SDK。 这是本文的核心。通过集成 SDK,鸿蒙 APP 获得了运行微信小程序的能力。SDK 内部包含 JavaScript 引擎、双线程运行时、渲染层、组件库、路由系统、JSBridge 和端能力 API。业务小程序运行在这个容器里,与宿主 APP 完全隔离,一个小程序出问题不会影响整个 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)和重度依赖微信生态的商业化功能,不适合这套方案,这些还是要走原生路线。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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