• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

One-Click Multi-Environment Build - Mastering HarmonyOS 5 with Hvigor

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155
Introduction


In HarmonyOS 5 application development, there is often a need to output multiple APP/HAP packages for different environments (test, pre-release, production) or different signatures (debug, release). Although HarmonyOS provides Multi-Target Build capability, allowing multiple products to be configured in the same project to generate multiple artifacts with different package names, certain deep customizations (such as dynamically modifying client_id and app_id in module.json5, or rewriting output package names based on build time) still require custom Hvigor plugins.

Combined with a sample project, this article demonstrates how to use Hvigor plugins with multi-target builds to achieve:

  1. Unified management of configuration such as API URLs and tracking URLs for each environment;
  2. Dynamic injection of application information like clientId and appId;
  3. Customized output package names based on build time and product name for easier subsequent release and production troubleshooting.
Ⅰ. Using Custom Hvigor Plugins in Projects

1. Entry Point of Hvigor Plugins


In the root directory of a HarmonyOS project, there is an entry file hvigorfile.ts where custom tasks are registered in plugins:


// File: hvigorfile.ts
import { buildSchemaProcessing } from './scripts/build-schema-processing';

export default {
system: appTasks, // Built-in Hvigor tasks, do not modify
plugins: [
buildSchemaProcessing() // Custom plugin: dynamically modify module.json5, build-profile.json5, etc.
]
};

Click Sync Now in DevEco Studio or run hvigor sync to load the plugin into the build process.

2. Overview of Common Hvigor APIs


In custom plugin code, we typically use the following core APIs:

  • hvigor.getRootNode(): Get the root node to access plugin contexts
  • rootNode.getContext(pluginId): Get the context object of a specified plugin, e.g., OHOS_APP_PLUGIN, OHOS_HAP_PLUGIN
  • context.getAppJsonOpt() / getModuleJsonOpt(): Read the AST object of app.json5 or module.json5
  • context.getBuildProfileOpt(): Read the AST object of the root directory build-profile.json5
  • context.setAppJsonOpt() / setBuildProfileOpt(): Write modified AST back into the build process

// Example: Reading context
const root = hvigor.getRootNode();
const appCtx = root.getContext(OhosPluginId.OHOS_APP_PLUGIN) as OhosAppContext;
const hapCtx = root.getContext(OhosPluginId.OHOS_HAP_PLUGIN) as OhosAppContext;
const appJson = appCtx.getAppJsonOpt();
const modJson = hapCtx.getModuleJsonOpt();
const buildProfile = appCtx.getBuildProfileOpt();

// Need to re-set after modification
appCtx.setAppJsonOpt(appJson);
appCtx.setBuildProfileOpt(buildProfile);


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Ⅱ. Combining Multi-Target Builds with Custom Plugins for Environment Switching

1. Standardizing Product Naming


To facilitate script parsing, we stipulate that the name of product uses underscore-separated fixed format:


<app-identifier>_<signing-identifier>_<environment-identifier>

e.g.: demo1_debug_test, demo1_release_preRelease, demo2_debug_official

Configure multiple products in build-profile.json5:


"products": [
{
"name": "demo1_debug_test",
"signingConfig": "debug",
"buildOption": {
"arkOptions": {
"buildProfileFields": {
"productsName": "demo1",
"buildTime": "",
"apiUrl": "",
"trackApiUrl": ""
}
}
}
},
{
"name": "demo1_release_officiallyReleased",
"signingConfig": "release",
"buildOption": { /* Same as above */ }
},
/* More product configurations... */
]
Tip: Fields under buildProfileFields are injected at runtime for easy environment information retrieval in code.
2. Local Configuration File: config.json


Centralize API URLs for each environment and clientId/appId information for each application:


{
"environmentInfo": {
"test": {
"apiUrl": "

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

",
"trackApiUrl": "

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

"
},
"preRelease": {
"apiUrl": "

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

",
"trackApiUrl": "

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

"
},
"officiallyReleased": {
"apiUrl": "

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

",
"trackApiUrl": "

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

"
}
},
"appConfigInfo": {
"demo1": {
"clientId": "111898773",
"appId": "5765880207855284373"
},
"demo2": {
"clientId": "6917571239128090930",
"appId": "6917571239128090930"
}
}
}

Provide two helper functions for use in plugins:


// scripts/config.ts
import cfgRaw from '../config.json';
import { format } from 'date-fns';

export function formatBuildTime(date = new Date()): string {
const pad = (n: number) => String(n).padStart(2, '0');
return `${date.getFullYear()}-${pad(date.getMonth()+1)}-${pad(date.getDate())}`
+ `_${pad(date.getHours())}-${pad(date.getMinutes())}-${pad(date.getSeconds())}`;
}

export function getLocalConfig() {
const cfg = JSON.parse(JSON.stringify(cfgRaw));
cfg.buildTime = formatBuildTime();
return cfg;
}
3. Core Logic of Plugin Implementation


In build-schema-processing.ts, use Hvigor lifecycle hooks to complete configuration injection and artifact renaming:


// scripts/build-schema-processing.ts
import { getLocalConfig } from './config';

export function buildSchemaProcessing() {
const localCfg = getLocalConfig();
let currentProduct = '', versionName = '', bundleName = '', appConfig: any;

return {
pluginId: 'custom-build-processor',
apply(hvigor) {
hvigor.getRootNode().afterNodeEvaluate(root => {
// Get context
const appCtx = root.getContext(OhosPluginId.OHOS_APP_PLUGIN) as OhosAppContext;
const hapCtx = root.getContext(OhosPluginId.OHOS_HAP_PLUGIN) as OhosAppContext;
const buildProfile = appCtx.getBuildProfileOpt();
const appJson = appCtx.getAppJsonOpt();
const modJson = hapCtx.getModuleJsonOpt();

// Current product info
currentProduct = appCtx.getCurrentProduct().getProductName() || '';
versionName = appJson.app.versionName;
const productKeys = currentProduct.split('_');
const appKey = productKeys[0];
const envKey = productKeys[2];
appConfig = localCfg.appConfigInfo[appKey];
const envConfig = localCfg.environmentInfo[envKey];

// Inject clientId and appId into app.json5
if (modJson) {
modJson['module']['appId'] = appConfig.appId;
modJson['module']['clientId'] = appConfig.clientId;
hapCtx.setModuleJsonOpt(modJson);
}

// Traverse products to inject environment/time and rename artifacts
(buildProfile.app.products || []).forEach((prd: any) => {
prd.buildOption.arkOptions.buildProfileFields.buildTime = localCfg.buildTime;
prd.buildOption.arkOptions.buildProfileFields.apiUrl = envConfig.apiUrl;
prd.buildOption.arkOptions.buildProfileFields.trackApiUrl= envConfig.trackApiUrl;

const suffix = `${appKey}_${versionName}_${localCfg.buildTime}`;
if (prd.name === currentProduct) {
bundleName = prd.bundleName || appJson.app.bundleName;
}
prd.output.artifactName = `AtomicPlatform-${suffix}`;
});

appCtx.setBuildProfileOpt(buildProfile);
});

hvigor.buildFinished(() => {
console.log(`? Build Time: ${localCfg.buildTime}`);
console.log(`? Current Artifact: ${currentProduct}`);
console.log(`? Bundle Name: ${bundleName}`);
console.log(`? ClientID: ${appConfig.clientId}`);
console.log(`? AppID: ${appConfig.appId}`);
});
}
};
}


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Ⅲ. Operation Results and Log Verification


Run hvigor build to see injection and renaming results in logs:


====================== Build Package Information ======================
? Build Time: 2025-04-24_09-32-05
? Current Artifact: demo2_debug_test
? Bundle Name: com.atomicservice.6917571239128090930
? ClientID: 6917571239128090930
? AppID: 6917571239128090930
====================================================

Meanwhile, the output HAP package will be named:


AtomicPlatform-demo2_1.0.0_2025-04-24_09-32-05.hap

This approach automatically completes configuration injection and artifact renaming for each build in different products/environments, significantly improving multi-environment development and release efficiency.

Ⅳ. Conclusion

  • Unified Management: Centralize environment and application information in config.json for easy maintenance and extension;
  • Automatic Injection: Use Hvigor plugins to dynamically modify module.json5 and build-profile.json5 during build, eliminating manual switching;
  • Custom Artifacts: Customize output package names based on build time and product name for easier version tracking and production troubleshooting.

Future enhancements to the plugin could include:

  1. Automatic upload of build reports to CI/CD platforms;
  2. Auto-generation of HTML reports for build difference comparison;
  3. Integration with Git commit and release workflows to trigger reviews or pushes after builds.
Ⅴ. Source Code Repository

Repository Branch: feature/hvigorfileBuild


Repository URL:

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Ⅵ. Reference Documentation



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.


[One-Click Building of APP and HAP Packages with Multi-Environment, Multi-Channel, Custom Path Output, and Custom Names in HarmonyOS](


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу