1. Stage模型应用程序包结构解析
在鸿蒙Stage模型开发中,应用程序包结构是项目的基础骨架。一个标准的Stage模型应用包通常包含以下核心目录和文件:
code复制/applications
/entry
/src
/main
/ets
/pages # 页面组件目录
/resources # 资源文件目录
/app.ets # 应用入口文件
/resources
/base
/element # 字符串/颜色等资源
/media # 媒体资源
/config.json # 应用配置文件
config.json是包结构的核心配置文件,其关键配置项包括:
json复制{
"app": {
"bundleName": "com.example.myapp",
"vendor": "example",
"version": {
"code": 1,
"name": "1.0.0"
}
},
"module": {
"name": "entry",
"type": "entry",
"abilities": [
{
"name": "MainAbility",
"icon": "$media:icon",
"label": "$string:mainability_label",
"type": "page",
"launchType": "standard"
}
]
}
}
关键提示:Stage模型与FA模型的最大区别在于ability的生命周期管理。Stage模型中每个ability运行在独立的进程中,通过ArkUI的UIAbility类进行管理。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 应用间跳转实现详解
2.1 显式跳转实现
显式跳转需要明确指定目标应用的bundleName和abilityName:
typescript复制import featureAbility from '@ohos.ability.featureAbility';
let want = {
bundleName: "com.example.targetapp",
abilityName: "MainAbility"
};
featureAbility.startAbility(want).then(() => {
console.log('跳转成功');
}).catch((error) => {
console.error('跳转失败: ' + JSON.stringify(error));
});
2.2 隐式跳转配置
隐式跳转通过action和entities定义:
typescript复制let want = {
action: "action.system.detail",
entities: ["entity.system.default"],
uri: "https://example.com/data"
};
目标应用的config.json需要配置对应的intentFilter:
json复制"abilities": [
{
"name": "DetailAbility",
"intentFilters": [
{
"actions": ["action.system.detail"],
"entities": ["entity.system.default"]
}
]
}
]
2.3 跳转参数传递
参数传递支持多种数据类型:
typescript复制let want = {
bundleName: "com.example.targetapp",
abilityName: "DetailAbility",
parameters: {
"id": 123,
"name": "测试数据",
"isValid": true,
"complexData": {
"key": "value"
}
}
};
注意事项:传递的数据总量不应超过1MB,复杂对象需要实现序列化接口。跨应用传递敏感数据时,建议使用加密传输。
3. HSP共享包开发实践
3.1 HSP创建与配置
创建HSP模块:
bash复制hdc shell bm create -p /data/hsp/com.example.mylibrary -n mylibrary
关键配置文件hsp/build-profile.json5:
json复制{
"apiType": "stageMode",
"library": {
"name": "mylibrary",
"types": ["ets", "resources"],
"jar": false
}
}
3.2 HSP使用示例
在宿主应用的build-profile.json5中添加依赖:
json复制"dependencies": {
"sharedLibrary": [
{
"name": "mylibrary",
"version": "1.0.0"
}
]
}
调用HSP中的方法:
typescript复制import { myFunction } from 'mylibrary';
@Entry
@Component
struct MyPage {
build() {
Column() {
Button('调用HSP方法')
.onClick(() => {
let result = myFunction('测试参数');
console.log(result);
})
}
}
}
3.3 HSP资源访问
访问HSP中的资源:
typescript复制import resourceManager from '@ohos.resourceManager';
let context = getContext(this) as any;
let resource = context.resourceManager;
let hspResource = resourceManager.getResourceManagerByBundle('com.example.mylibrary');
let stringValue = await hspResource.getString($r('app.string.hello_world').id);
开发经验:HSP版本升级时,建议采用语义化版本控制。重大变更应升级主版本号,确保宿主应用能正确处理依赖关系。
4. HAR静态共享包实战
4.1 HAR与HSP的区别对比
| 特性 | HAR | HSP |
|---|---|---|
| 打包方式 | 静态链接 | 动态共享 |
| 资源隔离 | 资源合并到宿主 | 资源独立 |
| 版本控制 | 编译时确定 | 运行时可更新 |
| 适用场景 | 工具类库/UI组件 | 业务模块/功能插件 |
| 性能影响 | 增加包体积 | 运行时加载开销 |
4.2 HAR开发流程
创建HAR模块:
bash复制hdc shell bm create -p /data/har/com.example.utils -n utils --static
典型目录结构:
code复制/utils
/src
/main
/ets
/components # 共享组件
/utils # 工具类
/resources # 资源文件
/oh-package.json5 # 依赖配置
4.3 HAR使用示例
宿主应用引入HAR:
json复制"dependencies": {
"@ohos/utils": "file:../utils"
}
调用HAR中的组件:
typescript复制import { MyCustomComponent } from '@ohos/utils';
@Entry
@Component
struct MainPage {
build() {
Column() {
MyCustomComponent({
title: '来自HAR的组件',
onClick: () => {
// 事件处理
}
})
}
}
}
性能优化:HAR中应避免包含大型资源文件,建议将图片等资源放在HSP中动态加载。工具类HAR建议使用Tree Shaking减少最终包体积。
5. 常见问题排查指南
5.1 应用跳转失败排查
-
错误码401:权限未配置
- 解决方案:在config.json中添加所需权限
json复制"reqPermissions": [ { "name": "ohos.permission.START_ABILITIES_FROM_BACKGROUND" } ] -
错误码1600001:目标ability不存在
- 检查步骤:
- 确认目标bundleName和abilityName拼写正确
- 确认目标应用已安装
- 对于隐式跳转,检查intentFilter配置
- 检查步骤:
5.2 HSP加载问题
-
资源加载失败:
- 典型表现:$r('app.string.xxx')返回undefined
- 解决方案:
- 确认HSP的resources目录结构正确
- 检查资源文件命名是否符合规范(不能使用中文/特殊字符)
-
版本冲突:
- 现象:java.lang.NoSuchMethodError
- 处理方案:
- 统一宿主与HSP的SDK版本
- 在hsp/build-profile.json5中明确声明兼容版本范围
5.3 HAR编译问题
-
重复类定义:
- 错误信息:Duplicate class com.example.Utils found
- 解决方案:
- 检查是否有多个HAR包含相同包名的类
- 使用ProGuard进行混淆处理
-
资源ID冲突:
- 现象:资源显示异常
- 修复方法:
- 在HAR的oh-package.json5中配置resourcePrefix
json复制{ "resourcePrefix": "utils_" }
6. 进阶开发技巧
6.1 动态加载HSP
typescript复制import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
async function loadHsp() {
try {
let atManager = abilityAccessCtrl.createAtManager();
await atManager.requestPermissionsFromUser(['ohos.permission.INSTALL_BUNDLE']);
let bundleInstaller = await bundle.getBundleInstaller();
await bundleInstaller.install('/data/hsp/com.example.plugin.hsp');
let hspModule = await import('com.example.plugin');
hspModule.init();
} catch (error) {
console.error('HSP加载失败: ' + JSON.stringify(error));
}
}
6.2 多HSP版本管理
推荐版本控制策略:
json复制// 宿主应用的build-profile.json5
"dependencies": {
"sharedLibrary": [
{
"name": "mylibrary",
"version": "^1.2.0", // 兼容1.2.0及以上,2.0.0以下
"exclude": ["unused-module"]
}
]
}
6.3 性能优化建议
-
HSP预加载:
typescript复制// 应用启动时预加载常用HSP onWindowStageCreate() { import('com.example.commonlib').then(() => { console.log('公共库预加载完成'); }); } -
资源懒加载:
typescript复制// 按需加载HSP资源 async function loadImageResource() { let hspRes = await ResourceManager.getResourceManagerByBundle('com.example.resources'); let pixelMap = await hspRes.getMedia($r('app.media.large_image').id); // 使用资源... } -
代码分割:
typescript复制// 动态导入非关键功能 button.onClick(async () => { const { advancedFeature } = await import('./AdvancedFeature'); advancedFeature.run(); });
在实际项目中,Stage模型的包结构设计会直接影响应用的维护性和扩展性。根据我的经验,对于大型项目建议采用"核心HAR+业务HSP"的架构,将通用组件和工具库放在HAR中,各业务模块拆分为独立的HSP,这样既能保证代码复用,又能实现模块的热更新。
