diff --git a/zh-cn/application-dev/Readme-CN.md b/zh-cn/application-dev/Readme-CN.md index 238cbc3aee84e81ca2932fb1918561f584dee5cc..603a38b9ac205ab36eec595899f2a66afe409565 100644 --- a/zh-cn/application-dev/Readme-CN.md +++ b/zh-cn/application-dev/Readme-CN.md @@ -26,7 +26,11 @@ - [多HAP运行机制及数据通信方式](quick-start/multi-hap-principles.md) - [应用程序包安装和卸载流程](quick-start/application-package-install-uninstall.md) - 共享包 - - [HAR共享包](quick-start/har-package.md) + - [HAR](quick-start/har-package.md) + - HSP + - [HSP概述](quick-start/hsp-guide.md) + - [应用内HSP开发指导](quick-start/in-app-hsp.md) + - [应用间HSP开发指导](quick-start/cross-app-hsp.md) - 应用配置文件(Stage模型) - [应用配置文件概述(Stage模型)](quick-start/application-configuration-file-overview-stage.md) - [app.json5配置文件](quick-start/app-configuration-file.md) diff --git a/zh-cn/application-dev/quick-start/cross-app-hsp.md b/zh-cn/application-dev/quick-start/cross-app-hsp.md new file mode 100644 index 0000000000000000000000000000000000000000..8b9d5f8832629a6d19659f027b9476ad45397cdd --- /dev/null +++ b/zh-cn/application-dev/quick-start/cross-app-hsp.md @@ -0,0 +1,221 @@ +# 应用间HSP开发指导 + +应用间`HSP`用于不同应用间的代码、资源共享。 +应用间`HSP`的宿主应用是一种特殊状态的应用,只能由一个[HSP](hsp-guide.md)包组成,不会独立运行在设备上,而是被普通应用模块的依赖项引用。当普通应用运行时,通过动态调用的方式使用应用间`HSP`提供的能力,从而实现应用自身所需要的功能。 + +## 应用间HSP的使用 +应用间HSP会分为两部分对外发布: + +一部分为[HAR包](har-package.md),这部分`HAR`包中不会包含具体的功能实现代码,而仅仅包含导出的对象与方法,所以体积很小。应用开发者将`HAR`包集成到自身的工程中,然后就可以通过调用`HAR`包中提供的对象与方法完成自身的应用功能。 + +另外一部分为[HSP](hsp-guide.md),这部分为应用间`HSP`的具体实现,里面包含js/ts代码、C++库、资源和配置文件。这部分会上架到应用市场或者集成到系统版本中。 + +### 集成应用间HSP的HAR包 +`HAR`包中的`index.d.ets`文件是应用间`HSP`导出的声明文件的入口,所有需要导出的接口,统一在`index.d.ets`文件中定义。`index.d.ets`文件路径如下: +``` +src +├── main +| └── module.json5 +├── index.d.ets +└── package.json +``` +`index.d.ets`内容样例如下: +```ts +@Component +export declare struct UIComponent { + build():void; +} + +export declare function hello(): string; + +export declare function foo1(): string; + +export declare function foo2(): string; + +export declare function nativeHello(): string; +``` +其中UIComponent为导出的ArkUI组件,`hello()`、`foo1()`与`foo2()`为应用间HSP导出的ts方法,`nativeHello()`方法为应用间HSP导出的native方法。具体实现如下: +#### **ArkUI组件** +在`HSP`中ArkUI组件的具体实现样例: +```ts +// lib/src/main/ets/ui/MyUIComponent.ets +@Component +export struct UIComponent { + @State message: string = 'Hello World' + build() { + Column() { + Text(this.message) + .fontSize(32) + .padding(8) + .fontColor(0xffffff) + .backgroundColor(0x0000ff) + }.padding(8).width('100%') + } +} +``` + +#### **ts方法** +在`HSP`中ts方法的具体实现: +```ts +export function hello(name: string): string { + return "hello + " + name; +} + +export function foo1() { + return "foo1"; +} + +export function foo2() { + return "foo2"; +} +``` +#### **native方法** +在`HSP`中native方法的具体实现: +```C++ +#include "napi/native_api.h" +#include +#include +#include + +const std::string libname = "liba"; +const std::string version = "v10001"; + +static napi_value Hello(napi_env env, napi_callback_info info) { + napi_value ret; + std::string msg = libname + ":native hello, " + version; + napi_create_string_utf8(env, msg.c_str(), msg.length(), &ret); + return ret; +} + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) { + napi_property_descriptor desc[] = { + {"nativeHello", nullptr, Hello, nullptr, nullptr, nullptr, napi_default, nullptr}}; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} +EXTERN_C_END + +static napi_module demoModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "liba", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +extern "C" __attribute__((constructor)) void RegisterLibaModule(void) { + napi_module_register(&demoModule); +} +``` +### 使用HAR包导出的能力 +引用`HAR`包前,需要先配置对`HAR`的依赖,配置方式可参考[文档](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-development-npm-package-0000001222578434#section89674298391)。`HAR`包配置成功后,在配置模块的`module.json`中会生成相关依赖项信息,如下所示: +```json +"dependencies": [ + { + "bundleName": "com.share.liba", + "moduleName": "liba", + "versionCode": 10001 + } +] +``` +其中`bundleName`为应用间`HSP`的`bundle`名称,`moduleName`为应用间`HSP`的模块名称,`versionCode`为应用间`HSP`的版本号。 +#### **使用HAR包中的ArkUI组件** +`HAR`共享包的依赖配置成功后,可以引用`HAR`共享包的ArkUI组件。ArkUI组件的导入方式与ts的导入方式一致,通过`import`引入`HAR`共享包导出的ArkUI组件,示例如下所示: +``` ts +import { UIComponent } from 'liba' + +@Entry +@Component +struct Index { + @State message: string = 'Hello World' + build() { + Row() { + // 引用HAR共享包的ArkUI组件 + UIComponent() + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} +``` + +#### **使用HAR包中的ts方法** +通过`import`引用`HAR`共享包导出的ts类和方法,示例如下所示: +``` ts +import { foo1 } from 'liba' +import { foo2 } from 'liba' + +@Component +struct Index { + build() { + Row() { + Column() { + Button('Button') + .onClick(()=>{ + // 引用HAR共享包的ts方法 + foo1(); + foo2(); + }) + } + .width('100%') + } + .height('100%') + } +} +``` +#### **使用HAR包中的native方法** +通过`import`引用`HAR`共享包导出的native方法,示例如下所示: +``` ts +import { nativeHello } from 'liba' + +@Component +struct Index { + build() { + Row() { + Column() { + Button('Button') + .onClick(()=>{ + // 引用HAR共享包的native方法 + nativeHello(); + }) + } + .width('100%') + } + .height('100%') + } +} +``` + +## 应用间HSP的分发方式 +应用间`HSP`由于并未直接完整的集成到开发者应用中去,所以需要提前预置在系统版本中或者随开发者应用同步安装到设备上,主要有以下两种形式: +1. 随系统发布,部分常用应用间`HSP`会预置在系统版本中 +2. 随应用发布,即用户在应用市场下载应用时,如果应用依赖了一个或者多个应用间`HSP`,同时设备上没有安装这个其依赖的应用间`HSP`时,应用市场会为用户同时下载普通应用以及其依赖的应用间`HSP`。从而保证普通应用能够正常使用共享库的功能。 + +### 应用间HSP的调试方式 +开发者本地调试应用间`HSP`相关的功能时,可能并不具备上述分发的条件,此时可以通过`bm`相关指令本地完成应用间`HSP`的分发,主要步骤如下: +1. 获取到应用间`HSP`的安装包 +2. 通过`bm`指令先安装应用间`HSP`的安装包 +``` +bm install -s sharebundle.hsp +``` +3. 通过`bm`指令后安装开发者自身的应用`hap` +``` +bm install -p feature.hap +``` +4. 启动开发者自身的应用,调试相关功能 + +**注意**:步骤2和步骤3不可以颠倒,否则会由于缺少必要的应用间`HSP`导致开发者的应用安装失败。更多`bm`相关指令可以参考[文档](https://gitee.com/openharmony/bundlemanager_bundle_framework#bm%E5%B7%A5%E5%85%B7%E5%91%BD%E4%BB%A4)。 + +## 注意事项 +1. 应用间`HSP`的代码会运行再开发者应用的进程中,调用相关代码时,需要做好异常捕获与容错处理,防止由于应用间`HSP`功能异常导致的稳定性问题 +2. 一个应用可以同时依赖多个应用间`HSP` +3. 应用间`HSP`会影响开发者应用自身的启动时间,依赖过多的应用间HSP可能会导致启动时延发生明显的劣化,建议将依赖的数目控制在16个以内。 +4. 当前三方开发者开发者只能使用系统提供的应用间`HSP`,不支持开发并发布自己的应用间`HSP`。 \ No newline at end of file diff --git a/zh-cn/application-dev/quick-start/figures/in-app-hsp-har.png b/zh-cn/application-dev/quick-start/figures/in-app-hsp-har.png new file mode 100644 index 0000000000000000000000000000000000000000..3cce70ac75424dabe0af4436f46319f943c9cade Binary files /dev/null and b/zh-cn/application-dev/quick-start/figures/in-app-hsp-har.png differ diff --git a/zh-cn/application-dev/quick-start/har-package.md b/zh-cn/application-dev/quick-start/har-package.md index e1d3ae490e9a6c053d9be152c9a90362ed039326..ed82cdf4949b6946feab4f462655346dca070223 100644 --- a/zh-cn/application-dev/quick-start/har-package.md +++ b/zh-cn/application-dev/quick-start/har-package.md @@ -1,6 +1,5 @@ -# HAR共享包 -## HAR共享包概述 -HAR(OpenHarmony Archive)是OpenHarmony静态共享包,可以包含代码、C++库、资源和配置文件。通过HAR共享包,可以实现多个模块或多个工程共享ArkUI组件、资源等相关代码。HAR不同于HAP,不能独立安装运行在设备上,只能作为应用模块的依赖项被引用。 +# HAR +HAR(Harmony Archive)是Harmony静态共享包,可以包含代码、C++库、资源和配置文件。通过HAR共享包,可以实现多个模块或多个工程共享ArkUI组件、资源等相关代码。HAR不同于HAP,不能独立安装运行在设备上,只能作为应用模块的依赖项被引用。 ## 创建HAR模块 HAR包对应DevEco Studio工程中的“Library”类型的[Module](https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/ohos-adding-deleting-module-0000001218760594-V3),可以通过DevEco Studio创建一个HAR模块。HAR模块默认不开启混淆能力,开启混淆能力,需要把HAR模块的build-profile.json5文件中的artifactType字段设置为obfuscation,配置如下所示: @@ -21,7 +20,7 @@ artifactType字段有以下两种取值,默认缺省为original。 注意:artifactType字段设置为obfuscation时,apiType字段必须设置为stageMode,因为Stage模型才支持混淆。 ## HAR共享包开发注意事项 -- HAR不支持在配置文件中声明ability、extensionAbility组件。 +- HAR不支持在配置文件中声明abilities、extensionAbilities组件。 - HAR不支持在配置文件中声明pages页面。 - HAR不支持在build-profile.json5文件的buildOption中配置worker。 - FA模型与Stage模型的HAR不支持相互引用。 diff --git a/zh-cn/application-dev/quick-start/har-structure.md b/zh-cn/application-dev/quick-start/har-structure.md index 6bd6ad0d4ff3c2c0e9efa60955d19d36d3dd8c2f..cc154c35d98365155bffb2ee8bb995ef51d69571 100644 --- a/zh-cn/application-dev/quick-start/har-structure.md +++ b/zh-cn/application-dev/quick-start/har-structure.md @@ -1,10 +1,9 @@ # HAR包结构 -HAR(OpenHarmony Archive)包用于实现多个模块或多个工程间的代码共享。HAR包不同于HAP,不能独立安装运行在设备上,只能作为应用模块的依赖项被引用。 +[HAR(Harmony Archive)](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-development-npm-package-0000001222578434)是Harmony静态共享包,可以包含代码、C++库、资源和module.json文件(Stage模型)或config.json文件(FA模型)等,用于实现多个模块或多个工程间的代码共享。 +HAR包不同于HAP,不能独立安装运行在设备上,只能作为应用模块的依赖项被引用。 HAR包对应DevEco Studio工程中的“Library”类型的[Module](https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/ohos-adding-deleting-module-0000001218760594-V3)。 - -OpenHarmony的[HAR包](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-development-npm-package-0000001222578434),是OpenHarmony静态共享包,可以包含代码、C++库、资源和module.json文件(Stage模型)或config.json文件(FA模型)等。 diff --git a/zh-cn/application-dev/quick-start/hsp-guide.md b/zh-cn/application-dev/quick-start/hsp-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..e2a5e3cc161ac493652b89bd5240cfb80c4f7bbd --- /dev/null +++ b/zh-cn/application-dev/quick-start/hsp-guide.md @@ -0,0 +1,18 @@ +# HSP概述 + +`HSP`(`Harmony Shared Package`)是Harmony动态共享包,可以包含代码、C++库、资源和配置文件。 +`HSP`与[HAR(Harmony Achive)](har-package.md)都是为了实现代码和资源的共享,最大的不同之处在于,`HAR`中的代码和资源跟随使用方编译,如果有多个使用方,它们的编译产物中会存在多份相同拷贝。**而`HSP`中的代码和资源可以独立编译,运行时在一个进程中代码也只会存在一份。** + +**图1** `HAR`和`HSP`在`APP`包中的形态示意图 +![in-app-hsp-har](figures/in-app-hsp-har.png) + +**HSP旨在解决HAR包存在的几个问题:** +- 多个`HAP`引用相同`HAR`包,导致的`APP`包大小膨胀问题 +- 多个`HAP`引用相同`HAR`包,`HAR`包中的一些状态变量无法共享的问题 + +**HSP的一些约束:** +- `HSP`及其使用方都必须是`Stage`模型 +- `HSP`及其使用方都必须使用`esmodule`编译模式 +- `HSP`不支持在配置文件中声明`abilities`、`extensionAbilities`标签 + +`HSP`按照使用场景可以分为[应用内HSP](in-app-hsp.md)和[应用间HSP](cross-app-hsp.md)。它们在配置文件和使用方式等方面有所区别。 \ No newline at end of file diff --git a/zh-cn/application-dev/quick-start/in-app-hsp.md b/zh-cn/application-dev/quick-start/in-app-hsp.md new file mode 100644 index 0000000000000000000000000000000000000000..2c456b608da986d0063c5821f6a515ec13e69761 --- /dev/null +++ b/zh-cn/application-dev/quick-start/in-app-hsp.md @@ -0,0 +1,153 @@ +# 应用内HSP开发指导 + +应用内`HSP`指的是专门为某一应用开发的`HSP`,只能被该应用内部其他`HAP`/`HSP`使用,用于应用内部代码、资源的共享。 +应用内`HSP`跟随其宿主应用的APP包一起发布,与该宿主应用具有相同的包名和生命周期。 + +## 开发应用内HSP + +`HSP`模块可以在`DevEco Studio`中由指定模板创建,我们以创建一个名为`library`的`HSP`模块为例。基本的工程目录结构大致如下: +``` +library +├── src +│ └── main +│ ├── ets +│ │ ├── pages +│ │ └── index.ets +│ ├── resources +│ └── module.json5 +└── package.json +``` +模块`module.json5`中的`"type"`标识模块类型,`HSP`的`"type"`是`"shared"`。 +```json +{ + "type": "shared" +} +``` + +`HSP`通过在入口文件中导出接口,对外提供能力。入口文件在模块`package.json`的`"main"`中配置。例如: +```json +{ + "main": "./src/main/ets/index.ets" +} +``` + +### 导出ts类和方法 +通过`export`导出ts类和方法,例如: +```ts +// library/src/main/ets/utils/test.ts +export class Log { + static info(msg) { + console.info(msg); + } +} + +export function add(a: number, b: number) { + return a + b; +} + +export function minus(a: number, b: number) { + return a - b; +} +``` +对外暴露的接口,需要在入口文件`index.ets`中声明: +```ts +// library/src/main/ets/index.ets +export { Log, add, minus } from './utils/test' +``` + +### 导出ArkUI组件 +ArkUI组件也可以通过`export`导出,例如: +```ts +// library/src/main/ets/components/MyTitleBar.ets +@Component +export struct MyTitleBar { + build() { + Row() { + Text($r('app.string.library_title')) + .fontColor($r('app.color.white')) + .fontSize(25) + .margin({left:15}) + } + .width('100%') + .height(50) + .padding({left:15}) + .backgroundColor('#0D9FFB') + } +} +``` +对外暴露的接口,需要在入口文件`index.ets`中声明: +```ts +// library/src/main/ets/index.ets +export { MyTitleBar } from './components/MyTitleBar' +``` +#### HSP中资源使用说明 +注意,在`HSP`中,通过`$r`/`$rawfile`可以使用本模块`resources`目录下的资源。 +如果使用相对路径的方式,例如: +在`HSP`模块中使用`Image("common/example.png")`,实际上该`Image`组件访问的是`HSP调用方`(如`entry`)下的资源`entry/src/main/ets/common/example.png`。 + +### 导出native方法 +在`HSP`中也可以包含`C++`编写的`so`。对于`so`中的`native`方法,`HSP`通过间接的方式导出,以导出`libnative.so`的乘法接口`multi`为例: +```ts +// ibrary/src/main/ets/utils/nativeTest.ts +import native from "libnative.so" + +export function nativeMulti(a: number, b: number) { + return native.multi(a, b); +} +``` + +对外暴露的接口,需要在入口文件`index.ets`中声明: +```ts +// library/src/main/ets/index.ets +export { nativeMulti } from './utils/nativeTest' +``` + +## 使用应用内HSP +要使用`HSP`中的接口,首先需要在使用方的`package.json`中配置对它的依赖。如果应用内`HSP`和使用方在同一工程下,可以直接本地引用,例如: +```json +// entry/src/main/module.json5 +"dependencies": { + "library": "file:../library" +} +``` +然后就可以像使用`HAR`包一样调用`HSP`的对外接口了。 +例如,上面的`library`已经导出了下面这些接口: +```ts +// library/src/main/ets/index.ets +export { Log, add, minus } from './utils/test' +export { MyTitleBar } from './components/MyTitleBar' +export { nativeMulti } from './utils/nativeTest' +``` +在使用方的代码中,可以这样使用: +```ts +// entry/src/main/ets/pages/index.ets +import { Log, add, MyTitleBar, nativeMulti } from "library" + +@Entry +@Component +struct Index { + @State message: string = 'Hello World' + build() { + Row() { + Column() { + MyTitleBar() + Text(this.message) + .fontSize(30) + .fontWeight(FontWeight.Bold) + Button('add(1, 2)') + .onClick(()=>{ + Log.info("add button click!"); + this.message = "result: " + add(1, 2); + }) + Button('nativeMulti(3, 4)') + .onClick(()=>{ + Log.info("nativeMulti button click!"); + this.message = "result: " + nativeMulti(3, 4); + }) + } + .width('100%') + } + .height('100%') + } +} +``` \ No newline at end of file diff --git a/zh-cn/application-dev/quick-start/module-configuration-file.md b/zh-cn/application-dev/quick-start/module-configuration-file.md index d97f6a350774b9c88eb0f9aa92a351066572599f..dbd64ee433a13647d1cf022a1c0c3984fd6afed3 100644 --- a/zh-cn/application-dev/quick-start/module-configuration-file.md +++ b/zh-cn/application-dev/quick-start/module-configuration-file.md @@ -72,7 +72,7 @@ module.json5配置文件包含以下标签。 | 属性名称 | 含义 | 数据类型 | 是否可缺省 | | -------- | -------- | -------- | -------- | | name | 标识当前Module的名称,标签值采用字符串表示(最大长度31个字节),该名称在整个应用要唯一,不支持中文。 | 字符串 | 该标签不可缺省。 | -| type | 标识当前Module的类型。类型有两种,分别:
- entry:应用的主模块。
- feature:应用的动态特性模块。 | 字符串 | 该标签不可缺省。 | +| type | 标识当前Module的类型。类型有4种,分别:
- entry:应用的主模块。
- feature:应用的动态特性模块。
- har:静态共享包模块。
- shared:动态共享包模块。 | 字符串 | 该标签不可缺省。 | | srcEntry | 标识当前Module所对应的代码路径,标签值为字符串(最长为127字节)。 | 字符串 | 该标签可缺省,缺省值为空。 | | description | 标识当前Module的描述信息,标签值是字符串类型(最长255字节)或对描述内容的字符串资源索引。 | 字符串 | 该标签可缺省,缺省值为空。 | | process | 标识当前Module的进程名,标签值为字符串类型(最长为31个字节)。如果在HAP标签下配置了process,该应用的所有UIAbility、DataShareExtensionAbility、ServiceExtensionAbility都运行在该进程中。
> **说明:**
> 仅支持系统应用配置,三方应用配置不生效。 | 字符串 | 可缺省,缺省为app.json5文件下app标签下的bundleName。 |