HarmonyOS Developer DevEco Studio使用指南-编译构建

丶龙八夷
发布于 2023-4-4 11:42
浏览
0收藏

HAP唯一性校验逻辑

HAP是应用安装的基本单位,在DevEco Studio工程目录中,一个HAP对应一个Module。应用打包时,每个Module生成一个.hap文件。

应用如果包含多个Module,在应用市场上架时,会将多个.hap文件打包成一个.app文件(称为Bundle),但在云端分发和端侧安装时,仍然是以HAP为基本单位。

为了能够正常分发和安装应用,需要保证一个应用安装到设备时,Module的名称、Ability的名称不重复,并且只有一个Entry类型的Module与目标设备相对应。

DevEco Studio会在编译构建时,对HAP进行上述唯一性校验,如果校验不通过,将会编译失败或给出告警。

说明

当前仅在API 8的工程中,针对distrofilter进行打包校验。

Module校验逻辑

校验目的:同一目标设备上Module唯一。

  1. 校验Module的Name。如果多个Module的Name不同,则校验通过。如果Name相同,继续校验deviceType。
  2. 校验设备类型deviceType。如果deviceType不相交,则校验通过。如果deviceType相交,继续校验distroFilter。deviceType不相交是指两个Module的deviceType中配置了完全不同的设备,例如:

//Module1和Module2配置了完全不同的设备,deviceType不相交。
//Module1
{
    "deviceType": ["TV", "tablet"]
}
//Module2
{
    "deviceType": ["car", "router"]
}

deviceType相交是指两个Module的deviceType中包含了相同的设备,例如:

//Module1和Module2因为都包含“tablet”设备,导致deviceType相交。
//Module1
{
    "deviceType": ["TV", "tablet"]
}
//Module2
{
    "deviceType": ["car", "tablet"]
}
  1. 校验分发规则distroFilter。如果distroFilter不相交,则校验通过。如果distroFilter相交,则无法保证Module唯一性,校验失败,打包失败。

distroFilter中包含属性apiVersion、screenShape、screenWindow、screenDensity和countryCode。相交的相关含义如下:

  • distroFilter不相交:如果两个distroFilter中任意一个属性不相交,则两个distroFilter不相交。
  • distroFilter相交:如果两个distroFilter中所有属性都相交,则两个distroFilter相交。

例如,两个Module中的apiVersion、screenShape、screenWindow、screenDensity都相交,但countryCode不相交,则可以区分两个Module,校验通过。

//Module1和Module2的两个distroFilter中,countryCode不相交,则两个distroFilter不相交。
//Module1
{
  "distroFilter": {
    "apiVersion" : {
      "policy": "include",
      "value": [8,9]
    },
    "screenShape": {
      "policy": "include",
      "value": ["rect"]
    },
    "screenWindow": {
      "policy": "include",
      "value": ["454*454", "466*466"]
    },
    "screenDensity": {
      "policy": "include",
      "value": ["ldpi", "xldpi"]
    },
    "countryCode": {
      "policy": "include",
      "value": ["CN", "HK"]
    }
  }
}
//Module2
{
  "distroFilter": {
    "apiVersion" : {
      "policy": "include",
      "value": [8,9]
    },
    "screenShape": {
      "policy": "include",
      "value": ["rect"]
    },
    "screenWindow": {
      "policy": "include",
      "value": ["454*454", "466*466"]
    },
    "screenDensity": {
      "policy": "include",
      "value": ["ldpi", "xldpi"]
    },
    "countryCode": {
      "policy": "include",
      "value": ["USA", "UK"]
    }
  }
}

Ability校验逻辑

校验目的:同一目标设备上Ability唯一。

  1. 校验Ability的Name。如果多个Ability的Name不同,则校验通过。如果Name相同,继续校验Ability所属Module的deviceType。
  2. 校验Ability所属Module的deviceType。如果deviceType不相交,校验通过。如果deviceType相交,继续校验Ability所属Module的distroFilter。例如,两个Ability的Name相同,但其所属Module的deviceType不相交,校验通过。

//Ability1和Ability2虽然名称相同,但由于其所属Module的deviceType不相交,所以可以区分两个Ability,校验通过。
//Ability1
{
    "module": {
        "name": "module_sample1",
        "deviceType": ["TV", "tablet"],
        "abilities": [
    {
        "name": "ability_sample"
    }
        ]
    }
}
//Ability2
{
     "module": {
        "name": "module_sample2",
        "deviceType": ["car", "router"],
        "abilities": [
    {
        "name": "ability_sample"
    }
        ]
    }
}
  1. 校验Ability所属Module的distroFilter。如果distroFilter不相交,校验通过。如果distroFilter相交,校验失败,抛出告警。

例如,两个Ability的Name相同,其所属Module的deviceType也相交,但其所属Module的distroFilter不相交,校验通过。

//Ability1和Ability2的Name相同,而且其所属Module的deviceType相交,但其所属Module的DistroFilter不相交,所以可以区分两个Ability,校验通过。
//Ability1
{
    "module": {
        "name": "module_sample",
        "deviceType": ["TV", "tablet"],
        "metadata": [
            {
                "name": "distroFilter_config"
                "resource": "$profile:distroFilter_config_sample1"
            }
        ],
        "abilities": [
            {
                "name": "ability_sample"
            }
        ]
    }
}
//Ability1所属Module的distroFilter
{
  "distroFilter": {
    "apiVersion" : {
      "policy": "include",
      "value": [8,9]
    },
    "screenShape": {
      "policy": "include",
      "value": ["rect"]
    },
    "screenWindow": {
      "policy": "include",
      "value": ["454*454", "466*466"]
    },
    "screenDensity": {
      "policy": "include",
      "value": ["ldpi", "xldpi"]
    },
    "countryCode": {
      "policy": "include",
      "value": ["CN", "HK"]
    }
  }
}

//Ability2
{
    "module": {
        "name": "module_sample2",
        "deviceType":  ["TV", "tablet"],
        "metadata": [
            {
                "name": "distroFilter_config"
                "resource": "$profile:distroFilter_config_sample2"
            }
        ],
        "abilities": [
            {
                "name": "ability_sample"
            }
        ]
    }
}
//Ability2所属Module的distroFilter
{
  "distroFilter": {
    "apiVersion" : {
      "policy": "include",
      "value": [8,9]
    },
    "screenShape": {
      "policy": "include",
      "value": ["rect"]
    },
    "screenWindow": {
      "policy": "include",
      "value": ["454*454", "466*466"]
    },
    "screenDensity": {
      "policy": "include",
      "value": ["ldpi", "xldpi"]
    },
    "countryCode": {
      "policy": "include",
      "value": ["USA", "UK"]
    }
  }
}

Entry校验逻辑

校验目的:目标设备只有一个Entry类型的Module与之对应,Feature类型的Module经过deviceType及distroFilter指明的目标设备都需要存在Entry类型的Module。

  1. 校验Feature类型的Module经过deviceType及distroFilter指明的目标设备都存在Entry类型的Module。例如,Bundle中存在一个Entry类型Module1,其支持设备为tablet和wearable,其分发规则为circle和rect形状的屏幕,同时存在一个Feature类型的Module2,通过分发规则可知,其可以分发到rect形状的tablet和wearable设备上,而rect形状的tablet和wearable设备上存在Entry类型的Module1,校验通过。

//Entry类型Module1
{
    "module": {
        "name": "module_sample1",
        "type": "entry",
        "deviceType": ["tablet", "wearable"],
        "metadata": [
            {
                "name": "distroFilter_config",
                "resource": "$profile:distroFilter_config1"
            }
        ]
    }
}
//Module1的distroFilter,distroFilter_config1.json
{
    "screenShape":{
        "policy": "include",
        "value": ["circle", "rect"]
    }
}
//Feature类型Module2
{
     "module": {
        "name": "module_sample2",
        "type": "feature",
        "deviceType": ["tablet", "wearable"],
         "metadata": [
            {
                "name": "distroFilter_config",
                "resource": "$profile:distroFilter_config2"
            }
        ]
    }
}
//Module2的distroFilter,distroFilter_config2.json
{
    "screenShape":{
        "policy": "include",
        "value": ["rect"]
    }
}
  1. 校验目标设备只有一个Entry类型的Module与之对应。

    a. 校验Entry类型Module的deviceType。如果deviceType不相交,校验通过。如果deviceType相交,继续校验Entry类型Module的distroFilter。

例如,同一个Bundle中存在两个Entry类型的Module,分别为Module1和Module2,两者的deviceType不相交,可以有效区分两个Module,校验通过。

//Entry类型Module1
{
    "module": {
        "name": "module_sample1",
        "type": "entry",
        "deviceType": ["tablet"]
    }
}
//Entry类型Module2
{
     "module": {
        name: "module_sample2",
        "type": "entry",
        "deviceType": ["wearable"]
    }
}

    b. 校验Entry类型Module的distroFilter。如果distroFilter不相交,校验通过。如果distroFilter相交,校验失败,打包失败。

例如,同一个Bundle中存在两个Entry类型的Module,分别为Module1和Module2,两者的deviceType相交,但两者的distroFilter不相交,可以有效区分两个Module,校验通过。

//Entry类型Module1
{
    "module": {
        "name": "module_sample1",
        "type": "entry",
        "deviceType": ["wearable"],
        "metadata": [
    {
        "name":"distroFilter_config"
        "resource": "$profile:distroFilter_sample1"
    }
        ]
    }
}
//Module1的distroFilter,distroFilter_sample1.json
{
    "distroFilter": {
         "screenShape":{
            "policy": "include",
            "value": ["rect"]
        }
    }
}
//Entry类型Module1
{
     "module": {
        "name": "module_sample2",
        "type": "entry",
        "deviceType": ["wearable"],
        "metadata": [
    {
        "name":"distroFilter_config"
        "resource": "$profile:distroFilter_sample2"
    }
        ]
    }
}
//Module2的distroFilter,distroFilter_sample2.json
{
    "distroFilter": {
         "screenShape":{
            "policy": "include",
            "value": ["circle"]
        }
    }
}

通过命令行方式构建应用或服务

说明

该功能适用于构建API Version 4至7的HarmonyOS应用/服务。

除了使用DevEco Studio一键式构建HarmonyOS应用或原子化服务(简称应用或服务)外,还可以使用命令行工具来调用gradle任务进行构建。通过命令行的方式构建应用或服务,可用于构筑CI(Continuous Integration)持续集成流水线,按照计划时间自动化的构建HAP、APP、签名、安装部署等操作,降低开发者负担。

通过命令行方式构建应用或服务,可在Windows、Ubuntu和macOS下调用相应命令来执行,本文将以Ubuntu系统为例进行讲解,包括准备构建环境、构建HAP、构建APP、签名等操作。Windows和macOS系统,仅在搭建构建环境上存在差异,其余调用的命令行任务与Ubuntu系统没有区别。

下表是命令行构建HarmonyOS应用或服务依赖的工具版本配套表信息。

工具

版本要求

JDK

JDK 11

Node.js

v14.19.1及以上,且只支持14系列版本

Gradle

7.3

sdkmgr

1.0.0.300及以上版本

编译构建插件

3.0.5.2及以上版本

准备HAP/APP构建环境

安装JDK
  1. 下载JDK,只支持JDK 11版本。
  2. 进入JDK软件包目录,执行如下命令,解压已经下载好的安装包,其中jdk_x64_linux_11.0.13_8.tar.gz为软件包名称,请根据实际进行修改。

tar -xvf jdk_x64_linux_11.0.13_8.tar.gz
  1. 配置JDK环境变量。

    a. 执行如下命令,打开当前用户下的配置文件.bashrc。

vim ~/.bashrc

    b. 在配置文件中,添加JDK的环境变量信息,文件目录和软件包名称请根据实际情况进行修改。

#jdk
export JAVA_HOME=/opt/jdk11.0.13_8
export PATH=$PATH:$JAVA_HOME/bin
  1. 执行source命令使配置文件立即生效。

source ~/.bashrc 
  1. 执行如下命令,检查JDK安装结果。

java -version

HarmonyOS Developer DevEco Studio使用指南-编译构建-鸿蒙开发者社区

安装node.js
  1. 访问​​Node.js官方网站​​,下载Node.js,版本为v14.19.1及以上,且只支持14系列版本。
  2. 进入Node.js软件包目录,执行如下命令,解压已经下载好的安装包,其中node-v14.19.1-linux-x64.tar.xz为软件包名称,请根据实际进行修改。

tar -xvf node-v14.19.1-linux-x64.tar.xz
  1. 配置Node.js环境变量。

    a. 执行如下命令,打开当前用户下的配置文件.bashrc。

vim ~/.bashrc

    b. 在配置文件中,添加Node.js的环境变量信息,文件目录和软件包名称请根据实际情况进行修改。

#nodejs
export NODE_HOME=/opt/node-v14.19.1-linux-x64
export PATH=$NODE_HOME/bin:$PATH
  1. 执行source命令使配置文件立即生效。

source ~/.bashrc  
  1. 执行如下命令,检查Node.js安装结果。

node -v
下载HarmonyOS SDK

通过sdkmgr命令行工具来统一下载和管理HarmonyOS SDK。

  1. 下载​​HarmonyOS SDK命令行工具​​:command-line-tools.zip
  2. 执行如下命令,解压命令行工具,工具名称请根据实际情况进行修改。

unzip command-line-tools.zip
  1. 执行如下命令,打开SDK工具配置文件config.properties,并设置HarmonyOS SDK存储路径,请注意,指定HarmonyOS路径时请使用绝对路径。

说明

HarmonyOS SDK存储目录请提前创建好,并为当前用户赋予写权限。

vim command-line-tools/sdkmanager/conf/config.properties

HarmonyOS Developer DevEco Studio使用指南-编译构建-鸿蒙开发者社区

  1. 进入到command-line-tools/sdkmanager/bin下,安装HarmonyOS SDK。例如,同时安装Java和Js API 6的SDK、toolchains。关于sdkmgr的详细命令说明,请参考

命令行工具使用说明

./sdkmgr install java:6 js:6 toolchains --accept-license
配置环境变量

配置HDC命令行工具和HarmonyOS SDK以及的环境变量信息。其中:

  • HDC命令行工具用于HarmonyOS应用/服务调试所需的工具,该工具存放在SDK的toolchains目录中。为方便使用HDC命令行工具,请将其添加到环境变量中。
  • HarmonyOS SDK中包含JS、Java、ArkTS及Native SDK(C/C++),如果工程中涉及C/C++,还需要单独设置Native SDK环境变量。
  1. 执行如下命令,打开当前用户下的配置文件.bashrc。

vim ~/.bashrc
  1. 在配置文件中,添加HDC工具、HarmonyOS SDK和Native SDK的环境变量信息,文件目录和软件包名称请根据实际情况进行修改。

#HDC工具环境变量
export HDC_HOME=/opt/HarmonyOS/SDK/toolchains
export PATH=$PATH:$HDC_HOME
#如果工程中涉及C/C++,才需要设置,需要注意的是,设置Native环境变量的路径,需要设置到版本号层级。
export OHOS_NATIVE_HOME=/opt/HarmonyOS/SDK/native/2.1.1.21
#编译构建插件版本是3.0.3.2及后续版本,请配置如下环境变量
export HOS_SDK_HOME=/opt/HarmonyOS/SDK
#编译构建插件版本是2.4.5.5及以前版本,请配置如下环境变量
export OHOS_SDK_HOME=/opt/HarmonyOS/SDK
  1. 执行source命令使配置文件立即生效。

source ~/.bashrc  
检查工程中gradle版本

当前配套的gradle版本为7.3版本,在进行构建HAP或APP前,应确认工程中对应的gradle版本是否正确。检查和修改方法如下:

打开命令行工具,请在工程根目录下执行如下命令,查看distributionUrl中指引的gradle版本号。

vim gradle/wrapper/gradle-wrapper.properties

如果gradle版本不是7.3版本,请修改为7.3,gradle的Url可以设置为Web端下载路径、也可以设置为本地路径。

图1 下载路径方式

HarmonyOS Developer DevEco Studio使用指南-编译构建-鸿蒙开发者社区

图2 本地路径方式

HarmonyOS Developer DevEco Studio使用指南-编译构建-鸿蒙开发者社区

构建应用或服务

通过命令行工具可以构建出HAP或APP,用于应用或服务的测试、上架等。

如下图所示,一般通过CI流水线构建生成不带签名信息的APP,然后通过命令行工具将该APP拆分为HAP并对HAP进行签名(调试签名),最后将签名后的HAP部署到设备上进行测试;HAP测试完成后,可使用签名工具对APP进行签名(发布签名),用于将HarmonyOS应用发布到AGC(AppGallery Connect)或者将原子化服务发布到HAG(HUAWEI Ability Gallery)。

HarmonyOS Developer DevEco Studio使用指南-编译构建-鸿蒙开发者社区

构建不带签名信息的APP

构建不带签名信息APP,请在工程根目录下执行如下命令:

说明

执行gradlew任务,需要具备执行权限,如果没有权限,可执行chmod u+x gradlew添加权限。

./gradlew packageReleaseApp
将APP拆分为HAP

将APP(带签名信息和不带签名信息APP均可)拆包为HAP,需要使用APP拆包工具​​hmos_app_unpacking_tool.jar​​进行拆包:

说明

也可以直接使用命令行工具构建HAP,具体请参考​​构建不带签名信息的HAP​​。

java -jar 'home/harmonyos/HarmonyOS/APP/hmos_app_unpacking_tool.jar' --mode app --app-path 'home/harmonyos/HarmonyOS/APP/harmonyos-demo.app' --out-path 'home/harmonyos/HarmonyOS/HAP' --force true --unpackapk false

关于该命令中需要修改的参数说明如下,其余参数不需要修改:

  • jar:指定APP拆包工具。
  • app-path:指定需要拆分的APP包。
  • out-path:指定HAP存储路径,该路径不能与APP存放路径相同。
  • force:取值为true,表示强制删除输出文件夹中的所有文件。

使用调试证书对HAP进行签名

通过APP拆包获得的HAP,无论APP是否签名,HAP都不会携带签名信息,因此要在真机设备上运行HAP,需要使用命令行工具对HAP进行签名。同时,需要提前申请签名所需文件,具体请参考​​申请调试证书​​。

  1. 下载HAP签名工具​​hapsigntoolv2.jar​​。
  2. 使用如下命令对HAP进行签名。

java -jar 'home/harmonyos/HarmonyOS/APP/hapsigntoolv2.jar' sign -mode localjks -privatekey harmonyos-demo -inputFile 'home/harmonyos/HarmonyOS/APP/unsign-harmonyos-demo.hap' -outputFile 'home/harmonyos/HarmonyOS/APP/sign-harmonyos-demo.hap' -signAlg SHA256withECDSA -keystore harmonyos-demo-debug.p12 -keystorepasswd ab123456 -keyaliaspasswd ab123456 -profile harmonyos-demo-debug.p7b -certpath harmonyos-demo-debug.cer -profileSigned 1

关于该命令中需要修改的参数说明如下,其余参数不需要修改:

  • privatekey:密钥的别名信息,与创建密钥库文件时“Alias”取值保持一致。
  • inputFile:需要签名的HAP名称。
  • outputFile:签名后的HAP名称。
  • keystore:密钥库文件,格式为.p12。
  • keystorepasswd:密钥库密码。
  • keyaliaspasswd:密钥密码。
  • profile:申请的调试Profile文件,格式为.p7b。
  • certpath:申请的调试证书文件,格式为.cer。

在真机设备中安装HAP

通过HDC工具将HAP推送到真机设备上进行安装,需要注意的是,推送的HAP必须是携带签名信息的,否则会导致HAP安装失败。

  • 推送单个HAP的命令如下:

hdc app install signed_entry-release-rich.hap
  • 推送多个HAP的命令如下:

hdc app install-multiple --hap xxx01.hap xxx02.hap xxx03.hap

使用发布证书为APP签名

HAP测试完成后便可以启动上架,将HarmonyOS应用发布到AGC或者将原子化服务发布到HAG。在上架APP前,需要使用发布证书对APP进行签名,可以使用​​hapsigntoolv2.jar​​工具对未签名的APP包进行签名。

在使用命令行工具进行APP包签名前,需要提前申请签名所需文件,具体请参考​​申请发布证书​​。

使用如下命令对APP进行签名。

java -jar 'home/harmonyos/HarmonyOS/APP/hapsigntoolv2.jar' sign -mode localjks -privatekey harmonyos-demo -inputFile 'home/harmonyos/HarmonyOS/APP/unsign-harmonyos-demo.app' -outputFile 'home/harmonyos/HarmonyOS/APP/sign-harmonyos-demo.app' -signAlg SHA256withECDSA -keystore harmonyos-demo-release.p12 -keystorepasswd ab123456 -keyaliaspasswd ab123456 -profile harmonyos-demo-release.p7b -certpath harmonyos-demo-release.cer -profileSigned 1

关于该命令中需要修改的参数说明如下,其余参数不需要修改:

  • privatekey:密钥的别名信息,与创建密钥库文件时“Alias”取值保持一致。
  • inputFile:需要签名的HAP名称。
  • outputFile:签名后的HAP名称。
  • keystore:密钥库文件,格式为.p12。
  • keystorepasswd:密钥库密码。
  • keyaliaspasswd:密钥密码。
  • profile:申请的调试Profile文件,格式为.p7b。
  • certpath:申请的调试证书文件,格式为.cer。

发布APP

使用发布证书签名后的APP可用于上架。

参考信息

构建不带签名信息的HAP

使用命令行工具,也可以直接构建出HAP,可以通过如下命令构建debug类型和release类型的HAP。如果需要构建携带签名信息的HAP,请参考​​构建携带签名的HAP或APP​​。

  • 构建debug类型的HAP,请在工程根目录下执行如下命令:

./gradlew assembleDebug
  • 构建release类型的HAP,请在工程根目录下执行如下命令:

./gradlew assembleRelease

构建携带签名的HAP或APP

要想直接构建出带签名信息的APP或HAP,您也可以提前将签名信息配置到工程中的build.gradle文件中,然后再调用构建命令生成APP或HAP。

使用在工程build.gradle中签名方案时,由于“storePassword”和“keyPassword”不支持明文密码,需要使用DevEco Studio签名后,将签名相关文件(包括p12、p7b、cer文件及material文件夹)拷贝至Ubuntu服务器中,再配置签名信息。

HarmonyOS Developer DevEco Studio使用指南-编译构建-鸿蒙开发者社区

  1. 将签名文件拷贝到Ubuntu服务器后,打开工程级build.gradle文件,在ohos闭包中,添加如下代码块。

ohos {
    signingConfigs {
        debug {   //签名类型,调试HAP使用debug,APP使用Release
            storeFile file('storefile-file.p12')
            storePassword 'storepassword'
            keyAlias = 'alias'
            keyPassword  'keypassword'
            signAlg = 'SHA256withECDSA'
            profile file('profile-file.p7b')
            certpath file('certpath-file.cer')
        }
    }
    ...
}
  1. 使用命令行工具构建HAP或APP。
  • 构建debug类型的HAP。

./gradlew assembleDebug
  • 构建release类型的HAP。

./gradlew assembleRelease
  • 构建APP。

./gradlew signReleaseApp




文章转载自:​​https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/command-line-building-app-hap-0000001193655754-V3​

分类
标签
已于2023-4-4 11:42:14修改
收藏
回复
举报
回复
    相关推荐