引言
在日常的开发中涉及到多签名 和多产物构建输出时手动切换签名文件和包名在开发中是容易出错且费时的一个操作,鸿蒙提供了自定义hvigor插件和多目标产物构建,那我们可以通过hvigor插件来动态修改不同项目配置所需要的代码,保证一套代码在不同的包名上切换且项目本身的功能是不变的,通过多目标产物构建输出自己想要的目标产物,实现定制化构建项目。
一、了解多目标产物构建是什么
1.什么是多目标产物构建
简单来说多目标产物就是输出自己高度定制化的模块,根据开发者自身的需求构建输出输出不同的HAP,HAR,HSP,APP等,通过不同构建配置来实现不同产物之间的差异化,多目标产物定制项介绍:developer.huawei.com/consumer/cn...
2.构建原理图

二、如何在项目里面实现多目标产物构建
(源码参考仓库分支:feature/multiTargetProduct)
1.在项目中实现多目标产物构建
构建多目标产物需要通过修改build-profile.json5、module.json5等配置文件,定义出不同的product和target。在这些配置文件中,开发者不仅可以为每个target指定不同的设备类型、源码集、资源等,并且还可以根据业务需要为不同的product分配不同的target。然后在构建过程中,构建工具会根据这些配置生成不同的target,然后通过不同的target搭配构建出不同的product产物。
为不同的项目配置不同的签名配置:default,demo_debug和demo_release,在开发项目中在这里可以配置为demo_debug携带调试证书用于调试使用,配置demo_release携带上架证书用于上架构建APP包使用。
typescript
"signingConfigs": [
{
"name": "default",//默认证书
"type": "HarmonyOS",
"material": {
"certpath": "C:\\Users\\admin\\.ohos\\config\\default_MultiBuildDemo_EoXj8aTamg_oidMu17Hf43iI41kuxPBK1f-SmO_d7e4=.cer",
"keyAlias": "debugKey",
"keyPassword": "0000001B881F7F910A6E276D***********************26C67BE265BF02384E2E97E",
"profile": "C:\\Users\\admin\\.ohos\\config\\default_MultiBuildDemo_EoXj8aTamg_oidMu17Hf43iI41kuxPBK1f-SmO_d7e4=.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": "C:\\Users\\admin\\.ohos\\config\\default_MultiBuildDemo_EoXj8aTamg_oidMu17Hf43iI41kuxPBK1f-SmO_d7e4=.p12",
"storePassword": "0000001B81AD92525EE***********************EDCCEEAF350252ABD455127B2E21C4E174"
}
},
{
"name": "demo_debug",//用于调试使用的证书
"type": "HarmonyOS",
"material": {
"storePassword": "000000193229BAE72AE854D*****************4B8124A2C67E90C36612B29AE",
"certpath": "./key/testDemo.cer",
"keyAlias": "testDemo",
"keyPassword": "000000197CB78D747AC**************A0B0A90DF10C7294EEBDF62C0BCE25969CD",
"profile": "./key/testDemoDebug.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": "./key/testDemo.p12"
}
},
{
"name": "demo_release",//用于上架使用的证书
"type": "HarmonyOS",
"material": {
"storePassword": "000000193229BAE72A*******************F1D92B4B8124A2C67E90C36612B29AE",
"certpath": "./key/testDemo.cer",
"keyAlias": "testDemo",
"keyPassword": "000000197CB78D747A****************294EEBDF62C0BCE25969CD",
"profile": "./key/testDemoDebug.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": "./key/testDemo.p12"
}
}
],
在products中配置不同的产物,每个产物构建不同的签名来实现构建不同的产物时使用签名的差异性
typescript
"products": [
{
"name": "default",
"signingConfig": "default",//默认产物对应默认证书
"compatibleSdkVersion": "5.0.1(13)",
"runtimeOS": "HarmonyOS",
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": false
}
}
},
{
"name": "products_debug",
"signingConfig": "demo_debug",//调试产物对应调试证书
"compatibleSdkVersion": "5.0.1(13)",
"runtimeOS": "HarmonyOS",
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": false
}
}
},
{
"name": "products_release",
"signingConfig": "demo_release",//正式产物对应正式签名
"compatibleSdkVersion": "5.0.1(13)",
"runtimeOS": "HarmonyOS",
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": false
}
}
}
],
构建出不同的产物过后还需要依赖在hap包下面(存在hsp也需要配置)的targets中
typescript
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [//建构建的产物都依赖在hap包,同样的如果出现hsp也需要进行依赖,hsp需要和主包一样有相同的配置
"default",
"products_debug",
"products_release"
]
}
]
}
]
2.如何切换不同的产物配置,以及输出的包

手动切换不同的产物信息:
三、如何在多目标产物的基础上构建不同包名和包的配置信息
(源码参考仓库分支:feature/differentPackageConfigurations)
1.增加第二个应用的签名信息和products配置信息、自定义常量
增加签名
typescript
"signingConfigs": [
//...之前的签名信息不变
{
"name": "demo_debug_test2",//另外一个应用对应的签名信息
"type": "HarmonyOS",
"material": {
"storePassword": "000000193229BAE72AE854DF***********************2B4B8124A2C67E90C36612B29AE",
"certpath": "./key/testDemo2/testDemo2.cer",
"keyAlias": "testDemo",
"keyPassword": "000000197CB78D747A***********************10C7294EEBDF62C0BCE25969CD",
"profile": "./key/testDemo2/TestDemo2Debug.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": "./key/testDemo.p12"
}
}
]
增加产物配置信息,在新增产物中实现产物差异性需要配置label 、icon 、bundleName ,output 等不同应用的标识,如果还需要再项目里面获取不同的参数可以在buildOption 中的buildProfileFields里面配置自定义的信息
typescript
"products": [
//...之前的产物配置信息
{
"name": "products_debug_test2",
"signingConfig": "demo_debug_test2",//第二个应用对应签名
"compatibleSdkVersion": "5.0.1(13)",
"runtimeOS": "HarmonyOS",
"label": "$string:app_name_test2",//对应的第二个项目的名字,
"icon": "$media:app_icon_test2",
"bundleName": "com.atomicservice.6917571239128090930",//对应的第二个项目的包名
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": false
}
},
"output": {
"artifactName": 'products_debug_test2'//配置用于区分不同产物的输出目录
}
}
]
2.配置后的实现效果
切换不同的产物运行后的效果不同,同时也会根据不同配置信息生成不同的不同的产物包信息,配置生效之前要删除module.json5 中原有的icon 和label,不然不生效

输出产物信息

运行后配置生效,桌面图标和应用名生效

3.查询并使用自定义常量
在项目中不同的包名配置使用的域名或者代码里面存在差异,仅依靠配置当前的配置信息是不够的,可以使用buildProfileFields来自定义不同产物下面的参数信息
配置自定义常量:
typescript
"products": [
{
"name": "default",
"signingConfig": "default",//默认产物对应默认证书
"compatibleSdkVersion": "5.0.1(13)",
"runtimeOS": "HarmonyOS",
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": false
},
"arkOptions": {
"buildProfileFields": {//配置的参数可以在项目中引用这部分常量,
"isStartNet": false,
"isDebug": true,
"buildTime": "",
"buildMode": "cheng_tu_test;cheng_tu_debug;api-pre",
"apiUrl": "",
"trackApiUrl": "",
"productsName": 'default'
}
}
}
},
{
"name": "products_debug",
"signingConfig": "demo_debug",//调试产物对应调试证书
"compatibleSdkVersion": "5.0.1(13)",
"runtimeOS": "HarmonyOS",
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": false
},
"arkOptions": {
"buildProfileFields": {//配置的参数可以在项目中引用这部分常量,
"isStartNet": false,
"isDebug": true,
"buildTime": "",
"buildMode": "cheng_tu_test;cheng_tu_debug;api-pre",
"apiUrl": "",
"trackApiUrl": "",
"productsName": 'products_debug'
}
}
},
"output": {
"artifactName": 'products_debug'//配置用于区分不同产物的输出目录
}
},
{
"name": "products_release",
"signingConfig": "demo_release",//正式产物对应正式签名
"compatibleSdkVersion": "5.0.1(13)",
"runtimeOS": "HarmonyOS",
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": false
},
"arkOptions": {
"buildProfileFields": {//配置的参数可以在项目中引用这部分常量,
"isStartNet": false,
"isDebug": true,
"buildTime": "",
"buildMode": "cheng_tu_test;cheng_tu_debug;api-pre",
"apiUrl": "",
"trackApiUrl": "",
"productsName": 'products_release'
}
}
},
"output": {
"artifactName": 'products_release'//配置用于区分不同产物的输出目录
}
},
{
"name": "products_debug_test2",
"signingConfig": "demo_debug_test2",//第二个应用对应签名
"compatibleSdkVersion": "5.0.1(13)",
"runtimeOS": "HarmonyOS",
"label": "$string:app_name_test2",//对应的第二个项目的名字,
"icon": "$media:app_icon_test2",
"bundleName": "com.atomicservice.6917571239128090930",//对应的第二个项目的包名
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": false
},
"arkOptions": {
"buildProfileFields": {//配置的参数可以在项目中引用这部分常量,
"isStartNet": false,
"isDebug": true,
"buildTime": "",
"buildMode": "cheng_tu_test;cheng_tu_debug;api-pre",
"apiUrl": "",
"trackApiUrl": "",
"productsName": 'products_debug_test2'
}
}
},
"output": {
"artifactName": 'products_debug_test2'//配置用于区分不同产物的输出目录
},
}
],
查询自定义配置信息
在目录build/products_debug/generated/profile/default/BuildProfile.ets中可以查看响应的构建信息

使用自定义配置信息
typescript
import BuildProfile from 'BuildProfile';//无法导入时尝试重新构建
Column() {
Text(`isStartNet:${BuildProfile.isStartNet}`)
Text(`isDebug:${BuildProfile.isDebug}`)
Text(`buildTime:${BuildProfile.buildTime}`)
Text(`buildMode:${BuildProfile.buildMode}`)
Text(`apiUrl:${BuildProfile.apiUrl}`)
Text(`trackApiUrl:${BuildProfile.trackApiUrl}`)
Text(`productsName:${BuildProfile.productsName}`)
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Start)
.padding({left:20})
UI界面实现效果

四、总结
针对不同的构建模式来输出不同的产物可以在开发中快速切换项目,也可以实现不同主体之间的上架主题切换问题,目前的AG上架分为国外主体 和国内主体 、这两个主体的上架流程会影响到代码的切换使用问题,例如国外主体不支持邀请测试需要国内主体来使用邀请测试来验证线上问题,此时切换包名信息就格外的重要,当然仅仅使用多目标多产物构建是远远不够的,想要高度自定义定制项目还需要配合hvigor插件来使用,比如client_id 和app_id 这种在module.json5 中的硬配置目前不支持自动切换和配置,需要使用自定义的hvigor插件 在构建的时候进行修改,项目的构建时间buildTime等需要实时更新的信息也是需要在脚本中去实现的。这篇文章为大家介绍多产物项目如何构建以及使用,在后续的文章中将配合自定义脚本来实现更改项目中module.json5中无法自动配置修改的信息。
六、源码仓库
仓库地址:gitee.com/qq196386172...
七、文章参考
多目标产物构建开发实践-编译构建 - 华为HarmonyOS开发者
HarmonyOS多环境+多渠道+自定义路径输出+自定义名称一键打app和hap包前言 做移动端开发时,不可避免的会遇到 - 掘金