09 多 HAP 包管理:一次开发多端部署实践
一、引言
HarmonyOS 的多 HAP 机制允许应用按设备形态分发不同的安装包。本项目中,手机/平板、电脑、智慧屏、手表分别使用独立的 HAP 包,共享同一套业务代码,实现"一次开发、多端部署"。
二、HAP 包结构
2.1 四个产品 HAP
| HAP 名称 | 安装包名 | 目标设备 | 入口 Ability |
multishortvideodefaultsample | products/default | 手机、平板 | MultiShortVideoDefaultAbility.ets |
multishortvideopcsample | products/pc | 电脑 | MultiShortVideoPcAbility.ets |
multishortvideotvsample | products/tv | 智慧屏 | MultiShortVideoTvAbility.ets |
multishortvideowearablesample | products/wearable | 手表 | MultiShortVideoWearableAbility.ets |
2.2 共享模块
| 模块 | 类型 | 被哪些 HAP 引用 |
multishortvideobase | common 共享库 | 全部 |
multishortvideoadaptivevideo | features 共享库 | 全部 |
multishortvideocomment | features 共享库 | 全部 |
multishortvideoindividual | features 共享库 | 全部 |
三、产品差异化入口
3.1 手机/平板(default)— 底部标签导航
使用MSVTabs配合 Navigation,支持底部浮动标签:
@Entry @ComponentV2 struct Index { build() { Navigation(this.pathStack) { MSVTabs({ data: this.data, ... }) } .navBarWidth(new WidthBreakpointType<number>(410, 410, 700, 700).getValue(this.windowInfo.widthBp)) .mode(NavigationMode.Stack) } }3.2 电脑(pc)— 侧边栏导航
使用SideBarContainer实现桌面风格的侧边栏菜单:
@Entry @ComponentV2 struct Index { build() { SideBarContainer(SideBarContainerType.Embed) { Column() { /* 侧边图标菜单 */ } Column() { /* 主内容区域 */ } } .sideBarWidth(112) .autoHide(false) .showControlButton(false) } }3.3 智慧屏(tv)— 顶部标签栏
使用TVTabs配合遥控器焦点导航:
@Entry @ComponentV2 struct Index { build() { Navigation(this.pathStack) { Stack({ alignContent: Alignment.Top }) { TVTabs() // 顶部标签 Column() { /* 内容区域 */ } } } .navBarWidth(880) .mode(NavigationMode.Split) } }3.4 手表(wearable)— 精简标签
取消 HDS 浮动效果,使用精简原生 Tabs:
@Entry @ComponentV2 struct Index { build() { Navigation(this.pathStack) { MSVTabs({ data: this.data, useFloating: false, barPosition: BarPosition.End, barFontsize: 15 }) } .mode(NavigationMode.Stack) } }四、模块依赖配置
4.1 根 build-profile.json5
{ modules: [ { name: "multishortvideodefaultsample", srcPath: "./products/default" }, { name: "multishortvideopcsample", srcPath: "./products/pc" }, { name: "multishortvideotvsample", srcPath: "./products/tv" }, { name: "multishortvideowearablesample", srcPath: "./products/wearable" }, { name: "multishortvideobase", srcPath: "./common/multishortvideobase" }, { name: "multishortvideoadaptivevideo", srcPath: "./features/multishortvideoadaptivevideo" }, { name: "multishortvideoindividual", srcPath: "./features/multishortvideoindividual" }, { name: "multishortvideocomment", srcPath: "./features/multishortvideocomment" }, ] }4.2 各 HAP 的 oh-package.json5
{ "dependencies": { "multishortvideobase": "file:../../common/multishortvideobase", "multishortvideoadaptivevideo": "file:../../features/multishortvideoadaptivevideo", "multishortvideocomment": "file:../../features/multishortvideocomment", "multishortvideoindividual": "file:../../features/multishortvideoindividual" } }五、多设备资源管理
每个 HAP 有独立的资源目录:
products/default/src/main/resources/ products/pc/src/main/resources/ products/tv/src/main/resources/ products/wearable/src/main/resources/各 HAP 可定义设备特定的颜色、字符串、图片等资源,与公共资源层级区分。
六、最佳实践
- 差异化最小化:只在 products 层处理设备特有 UI 差异,业务逻辑统一在 features 层
- 共享最大化:common 层的工具类和组件尽可能通用,减少重复代码
- 模块化构建:每个 HAP 独立编译,减少构建依赖
- 资源分级:设备特有资源放入各 HAP 的 resources 目录,通用资源放入共享模块
- 入口轻量化:Ability 入口只做初始化,页面布局交给 @Component 组件