前言 之前需要发版时都是在开发机上修改一下相关配置,比如签名文件、三方SDK参数等,然后打包上传到应用商店。略显繁琐,也担心某次打包会有漏改错改的配置。现在使用jenkins搭建了构建流水线,希望可以根据传入的参数不同,替换配置文件中的字段。翻看文档后发现可以在hvigorfile.ts
中接收部分编译配置。
BuildProfile 该类和 Android 项目中的 BuildConfig类很像,也是在编译构建时生成的。我们可以通过该类在运行时获取编译构建参数,也可以在build-profile.json5
中通过buildProfileFields增加自定义字段,从而在运行时获取自定义的参数。
实践 项目代码已经迭代了将近10年,有些功能的添加没有办法做到完美向下兼容,只能在请求参数中添加当前应用版本号,服务端根据版本号来判断需要下发哪些数据。但鸿蒙版本是刚开发开发,在一个版本内无法完成全部功能,需要分版本按紧急程度开发,因此版本号也不能直接和 Android、iOS 对齐,也是从 1.0.0 版本开始发版。所以无法在请求参数中直接传递应用版本号。因此我们将当前适配的版本号写入到BuildProfile.ets
文件中,方便各个业务调用。
我们在项目根目录下的build-profile.json5
文件中添加如下内容就可以将自定义的字段写入到该文件中.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { app : { products : [{ name : "default" , signingConfig : "default" , compatibleSdkVersion : "5.0.0(12)" , runtimeOS : "HarmonyOS" , buildOption : { arkOptions : { buildProfileFields : { online : false , version_to_servier : "5.11.10" , }, } }, }, ] } }
自定义参数可以在buildOption
、buildOptionSet
、targets
节点下的arkOptions
子节点中通过增加buildProfileFields
字段实现,自定义参数通过key-value
键值对的方式配置,其中value
取值仅支持number
、string
、boolean
类型。 当然,该配置也可以在模块下的build-profile.json5
中配置。优先级如下:
模块级target > 模块级buildOptionSet > 模块级buildOption > 工程级product > 工程级buildModeSet
这里我们添加了version_to_servier
字段来表示当前应用适配到了哪个版本。 正常情况下,我们运行代码就可以在${moduleName} / build / ${productName} / generated / profile / ${targetName}
目录下生成BuildProfile.ets
文件。 也可以在命令行执行hvigorw GenerateBuildProfile
。 也可以选中需要编译的模块,在菜单栏选择Build > Generate Build Profile ${moduleName}
。 也可以在菜单栏选择Build > Build Hap(s)/APP(s) > Build Hap(s)”或“Build > Build Hap(s)/APP(s) > Build APP(s)
。
使用时可以这么用
1 2 import BuildProfile from './BuildProfile' ;const VERSION_TO_SERVER : string = BuildProfile .version_to_servier ;
替换模块module.json5字段的值 我们使用了某三方SDK,需要在模块 下module.json5
文件中添加对应的id
1 2 3 4 5 6 7 8 9 10 { "module" : { "metadata" : [ { "name" : "xxx_APPID" , "value" : "1234567" } ], } }
为了区分测试环境和生产环境,xxx_APPID
配置了不一样的值,我们期望是打包时通过命令行参数来修改这个值,避免认为配置出现错误。
实践 使用命令行hvigorw
打包时除了buildMode
、debuggable
等参数外,还支持--config properties.key=value
进行自定义参数。并且在模块下、工程下的hvigorfile.ts
中都可以接收到该参数。
这里我们定义了布尔类型的online
参数来表示是否为发版包,当模块下的hvigorfile.ts
文件中根据该字段的值来区分配置的参数。 具体代码如下,在模块下的hvigorfile.ts
文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import { hapTasks, OhosHapContext , OhosPluginId } from '@ohos/hvigor-ohos-plugin' ;import { getNode } from '@ohos/hvigor' const entryNode = getNode (__filename); entryNode.afterNodeEvaluate (node => { let online = false let propertyOnline = hvigor.getParameter ().getProperty ('online' ); if (propertyOnline != undefined ) { online = propertyOnline } console .log ("entry online-> " + propertyOnline); const hapContext = node.getContext (OhosPluginId .OHOS_HAP_PLUGIN ) as OhosHapContext ; const moduleJsonOpt = hapContext.getModuleJsonOpt (); let metaDateList = moduleJsonOpt['module' ]['metadata' ] metaDateList.forEach (element => { if (element['name' ] === 'xxx_APPID' ) { if (online) { console .log ('线上环境,修改xxx_APPID配置为 abcdefg' ) element['value' ] = 'abcdefg' }else { console .log ('测试环境,修改xxx_APPID配置为 1234567' ) element['value' ] = '1234567' } } }); hapContext.setModuleJsonOpt (moduleJsonOpt); })export default { system : hapTasks, plugins :[] }
在打包构建时只需要执行
1 hvigorw clean assembleApp -p buildMode=release --config properties.online=true
就可以直接替换为生产环境的配置了。因为平时开发都是直接点 IDE 中的 run 进行调试,不会传入该参数,也就不会影响文件中原本配置的值。
打包签名 上面也提到自定义的参数也可以在工程下的hvigorfile.ts
接收到该参数,上面BuildProfile
中也提到在工程下的build-profile.json5
添加了自定义字段online
。我们同样可以根据命令行参数替换掉。同时也将配置的测试签名文件删除,只构建产物,随后再使用命令行进行签名。
代码如下,在工程根目录下的hvigorfile.ts
文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import { appTasks, OhosAppContext , OhosPluginId } from '@ohos/hvigor-ohos-plugin' ;import { hvigor,getNode } from '@ohos/hvigor' const rootNode = getNode (__filename); rootNode.afterNodeEvaluate (node => { let online = false let propertyOnline = hvigor.getParameter ().getProperty ('online' ); if (propertyOnline != undefined ) { online = propertyOnline } console .log ("online-> " + propertyOnline); const appContext = node.getContext (OhosPluginId .OHOS_APP_PLUGIN ) as OhosAppContext ; const buildProfileOpt = appContext.getBuildProfileOpt (); buildProfileOpt['app' ]['products' ][0 ]['buildOption' ]['arkOptions' ]['buildProfileFields' ]['online' ] = online if (online) { buildProfileOpt['app' ]['signingConfigs' ] = [] } appContext.setBuildProfileOpt (buildProfileOpt); })export default { system : appTasks, plugins :[] }
打包的时候,由于上架需要 app 文件,所以我们需要打 release 模式的 app 文件。测试时需要打release 模式的hap 文件:
1 2 3 4 5 6 //先安装一下依赖 ohpm install --all //发版包 hvigorw clean assembleApp -p buildMode=release --config properties.online=true //测试包 hvigorw clean assembleHap -p buildMode=release --config properties.online=false
这样我们就将BuildProfile
文件中的online
值改为传入的值,同时也清除了签名文件配置。
这里需要注意的是,如果执行的是assembleApp
,则产物是在项目根目录build/outputs/${productName}/xxx-default-unsigned.app
。如果执行的是assembleHap
,则会在${moduleName}/build/${productName}/outputs/${productName}/entry-default-unsigned.hap
.
下面我们对产物进行签名。
1 2 3 4 /Applications/DevEco-Studio.app/Contents/jbr/Contents/Home/bin/java -jar /Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/lib/hap-sign-tool.jar sign-app -keyAlias "keyAlias" -signAlg "SHA256withECDSA" -mode "localSign" -appCertFile "release.cer" -profileFile "release.p7b" -inFile "build/outputs/default/xxx-default-unsigned.app" -keystoreFile "default.p12" -outFile "xxx-default-signed.app" -keyPwd "keyPwd" -keystorePwd "keystorePwd" -signCode "1" /Applications/DevEco-Studio.app/Contents/jbr/Contents/Home/bin/java -jar /Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/lib/hap-sign-tool.jar sign-app -keyAlias "keyAlias" -signAlg "SHA256withECDSA" -mode "localSign" -appCertFile "debug.cer" -profileFile "debug.p7b" -inFile "entry/build/default/outputs/default/entry-default-unsigned.hap" -keystoreFile "default.p12" -outFile "entry-default-signed.hap" -keyPwd "keyPwd" -keystorePwd "keystorePwd" -signCode "1"
我们可以把打包签名的流程写在文件(build.sh)中,每次去执行这个文件就好了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 # 初始化build_type为release online=true# 解析命令行参数 while [[ $# -gt 0 ]]; do case $1 in --debug) online=false echo "需要构建测试包" shift ;; --release) # 实际上这个选项是多余的,因为默认就是release # 但如果你希望明确指定release以覆盖其他可能设置默认值的逻辑,可以保留 online=true echo "需要构建线上包" shift ;; *) # 未知选项,打印帮助信息或错误消息 echo "Usage: $0 [--debug|--release]" exit 1 ;; esac done# 安装依赖 ohpm install --all if [ "$online" == true ]; then # 打线上 app 包 echo "Executing online release build commands..." hvigorw clean assembleApp -p buildMode=release --config properties.online=true elif [ "$online" == false ]; then # 打测试 hap 包 echo "Executing not online release build commands..." hvigorw clean assembleHap -p buildMode=release --config properties.online=false else # 理论上不应该走到这里,除非build_type被设置为非预期的值 echo "Unknown build type: $build_type" exit 1 fi# 签名 if [ "$online" == true ]; then # 打线上 app 包 echo "签名 app 文件" /Applications/DevEco-Studio.app/Contents/jbr/Contents/Home/bin/java -jar /Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/lib/hap-sign-tool.jar sign-app -keyAlias "keyAlias" -signAlg "SHA256withECDSA" -mode "localSign" -appCertFile "release.cer" -profileFile "release.p7b" -inFile "build/outputs/default/xxx-default-unsigned.app" -keystoreFile "default.p12" -outFile "xxx-default-signed.app" -keyPwd "keyPwd" -keystorePwd "keystorePwd" -signCode "1" elif [ "$online" == false ]; then # 打测试 hap 包 echo "签名 hap 文件" /Applications/DevEco-Studio.app/Contents/jbr/Contents/Home/bin/java -jar /Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/lib/hap-sign-tool.jar sign-app -keyAlias "keyAlias" -signAlg "SHA256withECDSA" -mode "localSign" -appCertFile "debug.cer" -profileFile "debug.p7b" -inFile "entry/build/default/outputs/default/entry-default-unsigned.hap" -keystoreFile "default.p12" -outFile "entry-default-signed.hap" -keyPwd "keyPwd" -keystorePwd "keystorePwd" -signCode "1" else # 理论上不应该走到这里,除非build_type被设置为非预期的值 echo "Unknown build type: $build_type" exit 1 fi
打包时,如果需要打测试包,则执行 build.sh --debug
,如果要打发版包,则执行build.sh --release