Harmony系列之 工程结构与应用配置的理解

2,445 阅读7分钟

这篇文章主要讲鸿蒙应用的工程结构及应用配置,讲述期间穿插 Android 工程作为对比及迁移理解。

直入主题,先看下图(左鸿蒙右安卓)

file

无论是鸿蒙工程还是安卓工程,其结构相似,按内容可划分为:项目构建模块内容

项目构建

这部分内容对于安卓开发者来说,Gradle 构建系统很是熟悉。

项目构建的内容包含依赖文件(位于 gradle/Wrapper 文件夹),以 .gradle 结尾的脚本文件,.properties 结尾的配置文件,可执行文件及 settings.gradle

settings.gradle 定义项目模块包含信息等元数据信息,且每个模块内部也定义了 .gradle 脚本文件用于描述模块编译信息。

如下图编译信息概要(左鸿蒙右安卓)

file

编译信息大致包含插件声明模块信息声明依赖声明

在安卓侧构建模块,分别使用以下插件:

  1. com.android.application 插件构建 Application 模块,最终产物为 .apk 可执行文件
  2. com.android.library 插件构建 Library 模块,最终产物为 .aar 文件

而鸿蒙侧也有类 Application 的概念,鸿蒙应用以 APP Pack(Application Package)形式发布,它是由一个或多个 HAP(HarmonyOS Ability Package)以及描述每个 HAP 属性的 pack.info 组成。

简单理解就是鸿蒙应用由一个或多个 HAP 构建,每一个 HAP 可对应一个工程模块

在鸿蒙侧,HAP 是支持独立运行的,划分两种类型模块。

  1. entry,描述应用的主模块。一个 APP 中,对于同一设备类型必须有且只有一个 entry 类型的 HAP。
  2. feature,应用的动态特性模块。一个 APP 可以包含一个或多个 feature 类型的 HAP,也可以不含。只要包含 Ability (暂且理解为安卓侧的四大组件)的 HAP 就能够独立运行。

而上述两种模块使用的是 com.huawei.ohos.hap 插件构建,最终产物为 .hap 文件。

而针对 Library 库的构建,使用的是 com.huawei.ohos.library 插件,最终产物为 .har 文件,对应安卓侧的 .aar 文件。

鸿蒙侧应用支持 feature 模块独立运行,在组件化工程上协作开发调试变得更为简便,不再需要动态更改模块 Gradle 脚本切换插件。

模块内容

从上文可知,每一个模块会有对应的 Gradle 脚本定义编译信息。

模块内对应的业务文件都存放在 src 目录中,如下图展示 src 目录结构(左鸿蒙右安卓)

file

src 目录下资源可分为三部分

  1. 代码文件,如 main/java 目录下的代码文件;
  2. 资源文件,定义在 main/resource 目录下;
  3. 配置文件,定义在 main/config.json 文件内。

代码文件同安卓侧一致,同时 src 同目录的 libs 目录也同样用于存放外部依赖,不做多余描述。

重点放在资源文件配置文件的理解上。

资源文件

应用的资源文件(字符串、图片、音频等)统一存放于 resources 目录下,包括两大类目录

  • base目录与限定词目录
  • rawfile 目录

如下演示一个简单的目录结构。

resources
|---base  // 默认存在的目录
|   |---element
|   |   |---string.json
|   |---media
|   |   |---icon.png
|---en_GB-vertical-car-mdpi // 限定词目录示例,需要开发者自行创建   
|   |---element
|   |   |---string.json
|   |---media
|   |   |---icon.png
|---rawfile  // 默认存在的目录

其中,base目录与限定词目录按照两级目录形式来组织,目录命名必须符合官方规范,以便根据设备状态去匹配相应目录下的资源文件。

一级子目录为base目录限定词目录

base目录 是默认存在的目录,当应用的 resources 资源目录中没有与设备状态匹配的限定词目录时,会自动引用该目录中的资源文件。

限定词目录 需要开发者自行创建,如例子中的 en_GB-vertical-car-mdpi,目录名称由一个或多个表征应用场景或设备特征的限定词组合而成。

相似于安卓侧 res 目录及资源限定符的理解,但鸿蒙侧提供的限定词更为丰富,也意味场景更广,使用更灵活。支持从语言文字国家、地区横竖屏设备类型以及屏幕密度多维度自由组合。

二级子目录为资源目录,用于存放 字符串颜色布尔值 等基础元素,以及媒体、动画、布局等资源文件。

支持以下多种资源

|---base 
|   |---element //元素资源
|   |   |---boolean.json
|   |   |---string.json
|   |---media   //媒体资源
|   |   |---icon.png
|   |---animation //动画资源
|   |   |---zoom_in.xml
|   |---layout //布局资源
|   |   |---main_layout.xml
|   |---graphic //可绘制资源
|   |   |---dark.xml
|   |---profile //以原始文件形式存放,不限制文件名
|   |   |---yummylau.txt

比如定义一个 boolean.json

{
  "boolean":[
      {
        "name":"follow_me",
        "value":true
      },
      {
        "name":"you_are_happy",
        "value":"$boolean:follow_me"
      }
  ]
}

这些资源文件最终会被编译成二进制文件,并赋予资源文件ID。

rawfile 目录,支持创建多层子目录,目录名称可以自定义,文件夹内可以自由放置各类资源文件。

该目录的文件不会根据设备状态去匹配不同的资源,资源文件会被直接打包进应用,不经过编译,也不会被赋予资源文件 ID。

配置文件

每个模块都会有一个 config.json 配置文件,以 JSON 格式形式定义了三部分信息,缺一不可。

{
  //应用的全局配置信息
  "app":{}
  //应用在具体设备上的配置信息
  "deviceConfig":{}
  //模块配置信息
  "module":{}
}

app,包含应用的包名、生产厂商、版本号等基本信息,如下。

{
  //应用包名,用于标识应用的唯一性,类安卓侧 applicationId
  "bundleName": "com.effective.harmony.study",
  //应用开发厂商的描述
  "vendor": "effective",
  //应用版本信息
  "version": {
    "code": 1,
    "name": "1.0"
  },
  //依赖的鸿蒙 API 版本
  "apiVersion": {
    "compatible": 4,
    //应用运行需要的 API 目标版本
    "target": 4,
    "releaseType": "Beta1"
  }
}

这部分信息对应安卓侧 build.gradle 脚本内 android 节点的声明信息、

deviceConfig,包含 defaultcartvwearableliteWearablesmartVisionphonetablet等属性,其用于描述某个设备场景的配置。

default 标签内的配置是适用于所有设备通用,为必须设置项。其他设备类型如果有特殊的需求,则需要在该设备类型的标签下进行配置。

 {
    "default": {
        //应用进程名
        "process": "com.huawei.harmony.study", 
        //是否支持在设备未解锁状态直接启动
        "directLaunch": false, 
        //是否支持备份和恢复
        "supportBackup": false,
        //网络安全性配置
        "network": {}
    }
}

这部分是安卓侧所没有的。由于鸿蒙应用可适配多终端,deviceConfig 提供了多终端定制化的能力。比如你希望手表或车机设备在没有解锁场景下接听来电,则可配置 directLaunch 值为 true 等。

module,包含每个 Ability 必须定义的基本属性(如包名、类名、类型以及 Ability 提供的能力),以及应用访问系统或其他应用受保护部分所需的权限等。

这里我们简单理解鸿蒙的Ability等同于安卓的四大组件,它可支撑前台交互,也可后台运行。针对 Ability 后续会有专门一篇文章细讲。

以核心属性为例子。

 {
    //HAP 的包结构名称,在应用内应保证唯一性
    "package": "com.effective.hramony.study",
    //HAP 的入口类名,类 application
    "name": ".MyApplication",
    //可选,HAP 描述信息
    "description":"",   
    //允许 Ability 运行的设备类型,比如 tv,car,phone等
    "deviceType": [],
    //HAP 发布信息
    "distro": {},
    //可选,申明当前模块内所有 ability
    "abilities": [],
    //可选,申明运行时所需要申请的权限
    "reqPermissions": []
    ...
  }
}

这部分内容包含了安卓侧 AndroidManifest.xml 绝大部分核心功能,包括包名信息,应用入口四大组件申明及权限申明。

到这里,内容就没了,真没了!难道你不觉得挺简单的么。

建一个新工程看看呗。

从下一期起,开始讲讲开发相关内容了,欢迎关注追更。

欢迎关注 「Android之禅」公众号,和你分享有价值有思考的技术文章。
可添加微信 「Ming_Lyan」备注 “进群” 加入技术交流群,讨论技术问题严禁一切广告灌水。
如有 Android 领域有遇到技术难题亦或对未来职业规划有疑惑,一起讨论交流。
欢迎来扰。