HAR

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.

Creating a HAR Module

You can create a HAR module in DevEco Studio.

To better protect your source code, enable obfuscation for the HAR module so that DevEco Studio compiles, obfuscates, and compresses code during HAR building.

NOTE

Obfuscation is only available for ArkTS projects in the stage model.

When obfuscation is enabled, the resource ID is -1, and APIs that obtain resources by ID, such as ResourceManager, do not take effect.

Whether obfuscation is enabled by default varies by version.

  • In API version 9, obfuscation is disabled by default, and can be enabled by setting artifactType to obfuscation in the build-profile.json5 file of the HAR module. The configuration is as follows:

    {
      "apiType": "stageMode",
      "buildOption": {
          "artifactType": "obfuscation"
      }
    }
    

    The value options of artifactType are as follows:

    • original (default value): Code is not obfuscated.
    • obfuscation: Code is obfuscated.
  • In API version 10, obfuscation is enabled by default, and can be set through the enable field under ruleOptions in the build-profile.json5 file of the HAR module. 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"
        }
      ]
    }
    

Adaptation Guide

The artifactType field is forward compatible, and the original functionality is not affected. Yet, it is deprecated since API version 10, and you are advised to use the substitute as soon as possible.

Precautions for HAR Development

  • The HAR does not support UIAbilities, ExtensionAbilities, or pages.
  • The HAR does not support worker configuration under buildOption in the build-profile.json5 file.
  • The HAR of the FA model and that of the stage model cannot be referenced by each other.
  • The HAR of the stage model cannot reference content in the AppScope folder. This is because the content in the AppScope folder is not packaged into the HAR during building.

Exporting ArkUI Components, APIs, and Resources in the HAR

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"
}

Exporting ArkUI Components

Use export to export the ArkUI components. 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';

Exporting TS Classes and Methods

Use export to export TS classes and methods. Multiple TS classes and methods can be exported at the same time. The code snippet is as follows:

// library/src/main/ts/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 } from './src/main/ts/test';
export { func } from './src/main/ts/test';
export { func2 } from './src/main/ts/test';

Exporting Native Methods

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 libnative.so file is exported.

// library/src/main/ets/utils/nativeTest.ts
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';

Resources

Resources are packed into the HAR during building. 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):

  • AppScope (only for the stage model of API version 9)
  • Modules in the HAP
  • 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.
// oh-package.json5
{
  "dependencies": {
    "dayjs": "^1.10.4",
    "lottie": "^2.0.0"
  }
}

Referencing ArkUI Components, APIs, and Resources in the HAR

To start with, configure dependency on the HAR.

Referencing ArkUI Components

After configuring the dependency on the HAR, you can reference ArkUI components exported from the HAR by using import. The code snippet is as follows:

// 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%')
  }
}

Referencing TS Classes and Methods

To reference the TS classes and methods exported from the HAR, use import as follows:

// entry/src/main/ets/pages/Index.ets
import { Log } from 'library';
import { func } from 'library';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';

  build() {
    Column() {
      Text(this.message)
        .fontFamily('HarmonyHeiTi')
        .fontWeight(FontWeight.Bold)
        .fontSize(32)
        .fontWeight(700)
        .fontColor($r('app.color.text_color'))
        .textAlign(TextAlign.Start)
        .margin({ top: '32px' })
        .width('624px')

      // Reference TS classes and methods in the HAR.
      Button($r('app.string.button'))
        .id('button')
        .height(48)
        .width('624px')
        .margin({ top: '4%' })
        .type(ButtonType.Capsule)
        .fontFamily('HarmonyHeiTi')
        .borderRadius($r('sys.float.ohos_id_corner_radius_button'))
        .backgroundColor($r('app.color.button_background'))
        .fontColor($r('sys.color.ohos_id_color_foreground_contrary'))
        .fontSize($r('sys.float.ohos_id_text_size_button1'))
        .onClick(() => {
          // Reference 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%')
  }
}

Referencing Native Methods

To reference the native methods exported from the HAR, use import 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)
        .fontWeight(700)
        .fontColor($r('app.color.text_color'))
        .textAlign(TextAlign.Start)
        .margin({ top: '32px' })
        .width('624px')

      // Reference native methods in the HAR.
      Button($r('app.string.native_add'))
        .id('nativeAdd')
        .height(48)
        .width('624px')
        .margin({ top: '4%', bottom: '6%' })
        .type(ButtonType.Capsule)
        .fontFamily('HarmonyHeiTi')
        .borderRadius($r('sys.float.ohos_id_corner_radius_button'))
        .backgroundColor($r('app.color.button_background'))
        .fontColor($r('sys.color.ohos_id_color_foreground_contrary'))
        .fontSize($r('sys.float.ohos_id_text_size_button1'))
        .onClick(() => {
          this.message = 'result: ' + nativeAdd(1, 2);
        })
    }
    .width('100%')
    .backgroundColor($r('app.color.page_background'))
    .height('100%')
  }
}

Referencing Resources

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() {
      // 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%')
  }
}

Releasing a HAR

Follow the instructions to release a HAR.