Intelligent Assistant
Chat with our virtual assistant to get answers promptly.
A Harmony Archive (HAR) is a static shared package that can contain code, C++ libraries, resource files, and configuration files (also called profiles). It enables modules and projects to share code of ArkUI components, resources, and more.
If the startAbility API is used to start the UIAbility in the HAR, the value of moduleName in the API parameter must be the module name of the HAP or HSP that depends on the HAR.
Cyclic dependency: For example, there are three HARs. HAR-A depends on HAR-B, HAR-B depends on HAR-C, and HAR-C depends on HAR-A.
Dependency transfer: For example, there are three HARs. HAR-A depends on HAR-B, and HAR-B depends on HAR-C. If dependency transfer is not supported, HAR-A can use the methods and components of HAR-B, but cannot directly use that of HAR-C.
You can create a HAR module for calling C++ code in DevEco Studio. During the creation, turn on Enable native on the Configure New Module page. For details, see Creating a HAR Module.
You can export the ArkUI components, APIs, and other resources of a HAR for other applications or intra-application modules to reference.
The Index.ets file acts as the entry of the HAR export declaration file and is where the HAR exports APIs. This file is automatically generated by DevEco Studio by default. You can specify another file as the entry declaration file in the main field in the oh-package.json5 file of the module. The code snippet is as follows:
- {
- // ...
- "main": "Index.ets",
- // ...
- }
When compiling together with the host application, the HAR code is directly compiled into the host application. A HAR package serves as an intermediate build product rather than a final runtime entity. At runtime, the HAR operates under the identity of its host application, and the system differentiates behaviors based on the version of the host application. If it is necessary to implement version-specific behaviors for the host application within the HAR, you can call the getBundleInfoForSelf API to obtain the host application's targetVersion, and then execute different logic based on the obtained targetVersion.
Export ArkUI components using export. The code snippet is as follows:
- // library/src/main/ets/components/mainpage/MainPage.ets
- @Component
- export struct MainPage {
- @State message: string = 'HAR MainPage';
-
- build() {
- Column() {
- Row() {
- Text(this.message)
- .fontSize(32)
- .fontWeight(FontWeight.Bold)
- }
- .margin({ top: '32px' })
- .height(56)
- .width('624px')
-
- Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, alignContent: FlexAlign.Center }) {
- Column() {
- Image($r('app.media.pic_empty')).width('33%')
- Text($r('app.string.empty'))
- .fontSize(14)
- .fontColor($r('app.color.text_color'))
- }
- }.width('100%')
- .height('90%')
- }
- .width('100%')
- .height('100%')
- .backgroundColor($r('app.color.page_background'))
- }
- }
In the Index.ets file, declare the APIs that the HAR exposes to external systems. The code snippet is as follows:
- // library/Index.ets
- export { MainPage } from './src/main/ets/components/mainpage/MainPage';
Use export to export classes and methods. Multiple classes and methods can be exported. The code snippet is as follows:
- // library/src/main/ets/test.ets
- export class Log {
- static info(msg: string) {
- console.info(msg);
- }
- }
-
- export function func() {
- return 'har func';
- }
-
- export function func2() {
- return 'har func2';
- }
In the Index.ets file, declare the APIs that the HAR exposes to external systems. The code snippet is as follows:
- // library/Index.ets
- export { Log, func, func2 } from './src/main/ets/test';
The HAR can contain .so files written in C++. Native methods in the .so file can be exported from the HAR in the following way. In the example, the add API in the liblibrary.so file is exported.
- // library/src/main/ets/utils/nativeTest.ets
- import native from 'liblibrary.so';
-
- export function nativeAdd(a: number, b: number): number {
- let result: number = native.add(a, b);
- return result;
- }
In the Index.ets file, declare the APIs that the HAR exposes to external systems. The code snippet is as follows:
- // library/Index.ets
- export { nativeAdd } from './src/main/ets/utils/nativeTest';
Specifically, DevEco Studio collects resource files from the HAP module and its dependent modules, and overwrites the resource files with the same name (if any) based on the following priorities (in descending order):
Dependent HAR modules
If resource conflicts occur between dependent HAR modules, they are overwritten based on the dependency sequence indicated under dependencies in the oh-package.json5 file. The module that is higher in the dependency sequence list has a higher priority. For example, in the following example, if dayjs and lottie folders contain files with the same name, resources in dayjs are used preferentially.
With regard to resources in the internationalization folder of AppScope, HAP, and HAR directories, the preceding priority rules also apply to resources with the same internationalization qualifier. In addition, resources with internationalization qualifiers are prioritized over those in the base folder. For example, if resources with the same name are configured in both the base folder under AppScope and the en_US folder of a HAR, the one in the en_US folder is prioritized for internationalization purposes.
- {
- // ...
- "dependencies": {
- // ...
- "dayjs": "file:../dayjs",
- "lottie": "file:../lottie",
- },
- }
You can reference the ArkUI components, APIs, and resources in a HAR.
Before referencing the HAR, you need to configure the dependency on it. For details, see Referencing a Shared Package.
After configuring the dependency on the HAR, you can use import to import the ArkUI component exported from HAR. The following is an example:
- // entry/src/main/ets/pages/IndexSec.ets
- import { MainPage } from 'library';
-
- @Entry
- @Component
- struct IndexSec {
- build() {
- Row() {
- // Reference the ArkUI component in the HAR.
- MainPage()
- }
- .height('100%')
- }
- }
Use import to reference the classes and methods exported from the HAR. The code snippet is as follows:
- // entry/src/main/ets/pages/Index.ets
- import { Log, func } from 'library';
- // ...
- @Entry
- @Component
- struct Index {
- @State message: string = 'Hello World';
-
- build() {
- Column() {
- Text(this.message)
- .fontFamily('HarmonyHeiTi')
- .fontWeight(FontWeight.Bold)
- .fontSize(32)
-
- // Reference ETS classes and methods.
- Button($r('app.string.button'))
- .id('button')
- .height(48)
- .width('624px')
- .margin({ top: '4%' })
- .type(ButtonType.Capsule)
- .onClick(() => {
- // Reference ETS classes and methods in the HAR.
- Log.info('har msg');
- this.message = 'func return: ' + func();
- })
- // ...
-
- // ...
- }
- .width('100%')
- .backgroundColor($r('app.color.page_background'))
- .height('100%')
- }
- }
Use import to reference the native methods exported from the HAR. The code snippet is as follows:
- // entry/src/main/ets/pages/Index.ets
- import { nativeAdd } from 'library';
- // ...
- @Entry
- @Component
- struct Index {
- @State message: string = 'Hello World';
-
- build() {
- Column() {
- Text(this.message)
- .fontFamily('HarmonyHeiTi')
- .fontWeight(FontWeight.Bold)
- .fontSize(32)
-
- // ...
- // Reference the native method in the HAR.
- Button($r('app.string.native_add'))
- .id('nativeAdd')
- .height(48)
- .width('624px')
- .margin({ top: '4%', bottom: '6%' })
- .type(ButtonType.Capsule)
- .onClick(() => {
- this.message = 'result: ' + nativeAdd(1, 2);
- })
-
- // ...
- }
- .width('100%')
- .backgroundColor($r('app.color.page_background'))
- .height('100%')
- }
- }
Use $r to reference resources in the HAR. For example, add the name: hello_har string (defined in the string.json file) and icon_har.png image to the src/main/resources directory of the HAR module, and then reference the string and image in the entry module. The code snippet is as follows:
- // entry/src/main/ets/pages/Index.ets
- @Entry
- @Component
- struct Index {
- @State message: string = 'Hello World';
-
- build() {
- Column() {
- Text(this.message)
- .fontFamily('HarmonyHeiTi')
- .fontWeight(FontWeight.Bold)
- .fontSize(32)
-
- // ...
-
- // Reference the string in the HAR.
- Text($r('app.string.hello_har'))
- .id('stringHar')
- .fontFamily('HarmonyHeiTi')
- .fontColor($r('app.color.text_color'))
- .fontSize(24)
- .fontWeight(500)
- .margin({ top: '40%' })
-
- List() {
- ListItem() {
- // Reference the image in the HAR.
- Image($r('app.media.icon_har'))
- .id('iconHar')
- .borderRadius('48px')
- }
- .margin({ top: '5%' })
- .width('312px')
- }
- .alignListItem(ListItemAlign.Center)
- }
- .width('100%')
- .backgroundColor($r('app.color.page_background'))
- .height('100%')
- }
- }
For details, see Building a HAR.
HAR can be used as a second-party or third-party library for other applications. To protect code assets, you are advised to enable code obfuscation.
After code obfuscation is enabled, DevEco Studio compiles, obfuscates, and compresses code when building HARs to protect code assets.
The obfuscation capability is enabled by default for the HAR module. When the compilation module is release, simple code obfuscation is automatically performed for the HAR module of API version 10 or later. Since DevEco Studio 5.0.3.600, the code obfuscation is disabled by default when a project is created. You can enable this feature by setting enable in the ruleOptions field in the build-profile.json5 file of the HAR module. For details, see Using Obfuscation for Code Hardening. The configuration is as follows:
- {
- "apiType": "stageMode",
- "buildOption": {
- // ...
- },
- "buildOptionSet": [
- {
- "name": "release",
- "arkOptions": {
- "obfuscation": {
- "ruleOptions": {
- "enable": true,
- "files": [
- "./obfuscation-rules.txt"
- ]
- },
- "consumerFiles": [
- "./consumer-rules.txt"
- ]
- }
- },
- // ...
- },
- ],
- "targets": [
- {
- "name": "default"
- },
- // ...
- ]
- }
For details, see Publishing a Shared Package.