[鸿蒙开发] 4 – 鸿蒙应用程序包结构了解一下?

前言:之前的文章中,我们算是入门了,成功构建了一个非常简单的鸿蒙应用。现在我们来了解一下鸿蒙应用程序包的一些概念性的知识,这会贯穿于我们整个开发流程。另外说明一下:这个文章几乎都是官方文档中的内容,跟着写一遍加深记忆。

1. Stage应用程序包结构

HarmonyOS提供了应用程序包开发、安装、查询、更新、卸载的管理机制,方便开发者开发和管理HarmonyOS应用。

基于Stage开发模型开发的应用,经过编译打包之后,如下图所示:

[鸿蒙开发] 4 - 鸿蒙应用程序包结构了解一下?

1.1 Module的介绍

我们之前简单介绍过Stage模型的包结构,并且也尝试创建了一个新的Module,这次再来深入的了解一下:

  • 一个应用包含一个或者多个Module;
  • Module是HarmonyOS应用/服务的基本功能单元,包含了源代码、资源文件、三方库应用/服务配置文件;
  • 每个Module都可以独立编译和运行;
  • Module分为Ablity和Library两种类型:
    • Ablity类型的Module对应于编译后的HAP(Harmony Ability Package)
    • Library类型的Module对应于HAR(Harmony Archive)或者HSP(Harmony Shared Package)

在前期我们接触的更多的是Ablity类型的Module。

一个Module可以包含一个或多个UIAbility组件,如下图所示:

[鸿蒙开发] 4 - 鸿蒙应用程序包结构了解一下?

1.2 UIAbility组件是什么?

UIAblity组件是一种包含UI界面的应用组件,用于和用户交互。在一个UIAbility组件中可以通过多个页面来实现一个功能模块。每一个UIAbility组件实例,都对应于一个最近任务列表中的任务,就是是手机上的最近任务列表。

理解如下:UIAbility主要是提供界面展示和用户交互,可以将单个功能模块中的页面构建成一个UIAbility,在一个Module中也是可以有多个UIAbility的。

1.3 .hap文件

DevEco Studio会把工程中的Module,编译成对应的.hap后缀的文件,即HAP。HAP是HarmonyOS应用安装的基本单位,包含了编译后的代码、资源、三方库及配置文件。

HAP可以分为Entry和Feature两种类型:

  • Entry类型:应用的主模块,在module.json5配置文件中的type标签配置为“entry”类型。同一个应用中,只支持一个Entry类型的HAP,通常用于实现应用的入口界面、入口图标、主特性功能等。

下面是之前应用中的Entry的module.json5文件:
[鸿蒙开发] 4 - 鸿蒙应用程序包结构了解一下?

  • Feature类型:动态特性模块,配置文件中的type为feature,在一个应用程序中可以有0个或多个。通常用于实现应用的特性功能,可以配置成按需下载安装,也可以配置成随Entry类型的HAP一起下载安装

下面是之前新创建的Module的配置文件:
[鸿蒙开发] 4 - 鸿蒙应用程序包结构了解一下?

配置文件中的deliveryWithInstall就是控制是否随Entry一起下载安装。

1.4 Bundle

每个鸿蒙应用都可以包含多个.hap文件,一个应用中的.hap文件合在一起就称为一个Bundle,而bundleName就是应用的唯一标识(app.json5文件中进行配置)。

在应用上架到应用市场时,需要把所有的.hap文件(即Bundle)打包为一个.app后缀的文件用于上架,这个.app文件成为App Pack(Application Package),其中同时包含了描述App Pack属性的pack.info文件。

另外需要注意一点:在云端分发和终端设备安装时,都是以HAP为单位进行分发和安装的。相当于本地开发的生成的.app文件中会包括所有的HAP,但是可能会针对于不同的设备使用部分HAP,最后下载到用户手机的只是部分HAP。.app文件的作用只是聚合这些HAP,用于上架应用市场。

1.5 HAP包结构

打包后的HAP中有以下文件:

  • ets:用于存放应用代码编译后的字节码文件
  • libs:用于存放库文件。库文件是鸿蒙应用依赖的第三方代码(.so)
  • resources:资源文件(字符串、图片)
  • module.json:配置文件。内容由工程配置中的module.json5和app.json5组成
  • pack.info:是Bundle中用于描述每个HAP属性的文件,例如app中的bundleName和versionCode信息、module中的name、type和abilities等信息,由IDE工具生成Bundle包时自动生成。

目前暂时没有找到办法直接打开鸿蒙.app文件夹进行验证,只能通过官网上的描述去了解了。

2.多HAP机制

2.1 设计目标

上面提到一个应用会有多个HAP,那为何要这样设计呢?

1.方便模块化管理应用:

将应用划分多个模块,每个模块的实现放到独立的HAP中。Entry中统一集成和管理Feature包,Feature包去进行单独的开发和测试;

2.可以灵活的组合和部署HAP:

比如应用程序有一个Entry包和两个Feature包,其中Feature1只能部署到设备A,Feature2只能部署到设备B,那开发者就可以方便的组合Entry和Feature部署到不同的设备上;

3.方便资源共享,减少程序包大小

多个HAP需要用到的资源以及so文件可以放到单独的HAP中,其他HAP可以到该HAP中访问资源和so文件;

2.2 构建视图

[鸿蒙开发] 4 - 鸿蒙应用程序包结构了解一下?

从开发态到编译态,Module中的文件会发生以下变更:

  • ets目录:ArkTS源码编译生成.abc文件
  • resources目录:AppScope目录下的资源文件会合入到Module下面资源目录中,如果两个目录下存在重名文件,编译打包后只会保留AppScope目录下的资源文件
  • module配置文件:AppScope目录下的app.json5文件字段会合入到Module下面的module.json5文件中,编译后生成HAP或HSP最终高的module.json文件

一个开发态的Module编译后生成一个部署态的HAP,Module和HAP一一对应。所有的HAP最终都会编译到一个App Pack中(以.app为后缀的文件),用于发布到应用市场。

2.3 多HAP的开发调试和发布流程

[鸿蒙开发] 4 - 鸿蒙应用程序包结构了解一下?

开发阶段:

按照业务逻辑创建多个Module,在各自的Module中完成自身业务的开发。

调试阶段:
通过Studio编译打包,生成单个or多个HAP,就可以基于HAP进行调试。在调试前,需要先安装或更新HAP:

  • 使用DevEco Studio进行调试:应用程序包调试方法
  • 使用hdc工具(通过HarmonyOS SDK获取,在SDK的toolchains目录下)进行调试

在调试前,需要先安装或更新HAP,此处有两种方式:

  1. 直接使用hdc安装、更新HAP,HAP的路径为开发平台上的文件路径:
// 安装、更新,多HAP可以指定多个文件路径
hdc install C:\entry.hap C:\feature.hap
// 执行结果
install bundle successfully.
// 卸载
hdc uninstall com.example.myapplication
// 执行结果
uninstall bundle successfully.

2.先执行hdc shell,再使用bm工具安装、更新HAP:

HAP的文件路径为真机上的文件路径,命令参考如下:

// 先执行hdc shell才能使用bm工具
hdc shell
// 安装、更新,多HAP可以指定多个文件路径
bm install -p /data/app/entry.hap /data/app/feature.hap
// 执行结果
install bundle successfully.
// 卸载
bm uninstall -n com.example.myapplication
// 执行结果
uninstall bundle successfully.

完成HAP安装或更新后,即可参考相关调试命令进行调试。

发布阶段
当开发的程序包满足发布要求时,可以在工具中打包编译生成App包。将该App包上架到应用市场云端,应用市场会对上架的App包校验签名,校验签名通过后会将App包中的HAP拆分出来,同时对拆分出的HAP重新添加签名,然后对HAP进行分发。

所以用户设备上下载的是HAP,并不是.app文件。

部署阶段

用户在设备上的应用市场客户端能够看到各种各样的应用,这些应用均由云端分发而来,有些是多HAP应用,有些是单HAP应用。用户选择某个应用后,应用市场将下载应用所包含的全部deliveryWithInstall设置为“true”的HAP。

安装

下载完成后,应用市场客户端再调用系统中包管理服务的安装接口安装下载的HAP,包管理服务以应用为单位将其中所有HAP部署到指定目录下,以完成应用的安装。

2.4 多HAP使用规则

  • App Pack包不能直接安装到设备上,只是打包上传到应用市场;
  • App Pack包中所有的HAP的配置文件中的bundleName和versionCode标签必须一致;
  • App Pack包中同一设备类型的所有HAP中,只能有一个entry类型的HAP;
  • App Pack包中的每个HAP必须配置moduleName标签,同一设备类型的所有HAP对应的moduleName标签必须唯一;
  • 同一应用的所有HAP签名证书要一致,应用市场分发时会将所有HAP从App Pack中拆分出来,同时对其中的所有HAP进行重签名,这样保证了所有HAP签名证书的一致性。在调试阶段,开发者通过命令行或IDE将HAP安装到设备上时要保证所有HAP签名证书一致,否则会出现安装失败的问题;

3. 应用程序包更新流程

HarmonyOS包管理服务提供了应用程序包更新能力,更新方式如下。

  • 应用市场内更新:新版本应用通过应用市场上架后,应用市场通知终端用户该应用有新版本,终端用户可以根据通知到应用市场(客户端)进行应用升级;
  • 应用内检测升级:终端用户启动应用时,应用市场检测到该应用有新版本会通知终端用户,可以到应用市场进行应用的下载更新;

4.共享包

鸿蒙OS提供了两种共享包:HAR(Harmony Archive)静态共享包和HSP(Harmony Shared Package)动态共享包。

他们都是为了实现代码和资源的共享,不同之处在于:

  • HAR中的代码和资源跟随使用方编译,如果有多个使用方,它们的编译产物中会存在多份相同拷贝;
  • HSP中的代码和资源可以独立编译,运行时在一个进程中代码也只会存在一份;

[鸿蒙开发] 4 - 鸿蒙应用程序包结构了解一下?

HSP的一些约束:

  • HSP和使用方都需要是Stage模型
  • HSP和使用方都需要使用esmodule编译模式
  • HSP不支持在配置文件中声明abilities、extensionAbilities标签
  • HSP按场景可以分为应用内HSP和应用间HSP,后者还不支持

这里目前只了解一下共享包,等之后需要用的时候在补充相关使用记录,有兴趣的可以直接看官方文档:developer.huawei.com/consumer/cn…

5.应用热修复

支持动态发布补丁修复线上版本的问题:
developer.huawei.com/consumer/cn…

用的时候再仔细研究。

6.应用配置文件

在基于Stage模型开发的应用项目代码下,都存在一个app.json5及一个或多个module.json5这两种配置文件。

app.json5主要包含以下内容:

  • 应用的全局配置信息,包含应用的包名、开发厂商、版本号等基本信息。
  • 特定设备类型的配置信息。

module.json5主要包含以下内容:

  • Module的基本配置信息,例如Module名称、类型、描述、支持的设备类型等基本信息。
  • 应用组件信息,包含UIAbility组件和ExtensionAbility组件的描述信息。
  • 应用运行过程中所需的权限信息。

6.1 app.json5配置文件

{
  "app": {
    "bundleName": "com.application.myapplication",
    "vendor": "example",
    "versionCode": 1000000,
    "versionName": "1.0.0",
    "icon": "$media:app_icon",
    "label": "$string:app_name",
    "description": "$string:description_application",
    "minAPIVersion": 9,
    "targetAPIVersion": 9,
    "apiReleaseType": "Release",
    "debug": false,
    "car": {
      "minAPIVersion": 8,
    }
  },
}
属性名称 描述
bundleName 包名,用于标识应用的唯一性。eg. com.example.demo
bundleType 类型。app or atomicService(元服务)
debug 应用是否可以调试
icon 应用图标
label 应用名称
description 应用的描述信息
vendor 标识对应用开发厂商的描述
versionCode 用于比较两个版本,和Android一样
versionName 四段式:A.B.C.D 主版本号、次版本号、特性版本号、修订版本号
minCompatible VersionCode 标识应用能够兼容的最低历史版本号,用于跨设备兼容性判断(当前不支持)
minAPIVersion 标识应用运行需要的SDK的API最小版本,由build-profile中compatibleSdkVersion生成
targetAPIVersion 标识应用运行需要的API目标版本,由build-profile中compileSdkVersion生成
apiReleaseType 标识应用需要的API目标版本的类型,不需要填写,IDE生成
multiProjects 当前工程是否支持多工程联合开发
tablet 可不填,对tablet设备做特殊支持
tv 可不填,对tv设备做特殊支持
wearable 可不填,对wearable设备做特殊支持
car 可不填,对car设备做特殊支持
phone 可不填,对phone设备做特殊支持

6.2 module.json5配置文件

{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": [
      "tv",
      "tablet"
    ],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "virtualMachine": "ark",
    "metadata": [
      {
        "name": "string",
        "value": "string",
        "resource": "$profile:distributionFilter_config"
      }
    ],
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ts",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:icon",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:icon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "ohos.want.action.home"
            ]
          }
        ]
      }
    ],
    "requestPermissions": [
      {
        "name": "ohos.abilitydemo.permission.PROVIDER",
        "reason": "$string:reason",
        "usedScene": {
          "abilities": [
            "FormAbility"
          ],
          "when": "inuse"
        }
      }
    ]
  }
}

其中module对应的是模块的配置信息,一个模块对应一个打包后的hap包。具体属性如下:

属性名称 介绍
name 当前Module的名称
type 当前Module的类型。entry or feature
scrEntry 当前Module的对应的代码路径,默认值为空
description 当前Module的描述,默认值为空
process 当前Module的进程名,默认值为bundleName
mainElement 当前Module的入口UIAbility名称或ExtensionAbility名称,默认值为空
deviceTypes 当前Module支持的设备
deliveryWithInstall 表示该Module对应的HAP是否跟随应用一块安装
installationFree 表示是否支持免安装特性
virtualMachine 当前Module运行的目标虚拟机类型,IDE自动插入
pages 当前Module的profile资源,列举每个页面信息
metadata 当前Module的自定义元信息,默认为空
abilities 当前Module的UIAbility的配置信息,默认为空
extensionAbilities 当前Module的ExtensionAbility的配置信息,默认为空
requestPremissions 当前应用运行时向系统申请的权限集合,默认为空
testRunner 当前Module用于支持对测试框架的配置,默认为空

6.1.1 deviceTypes

支持的设备类型:

  • 平板 tablet
  • 智慧屏 tv
  • 智能手表 wearable
  • 车机 car
  • 手机 phone
{
  "module": {
    "name": "myHapName",
    "type": "feature",
    "deviceTypes" : [
       "tablet"
    ]
  }
}

6.1.2 pages标签

用于指定描述页面信息的配置文件:

{
  "module": {
    // ...
    "pages": "$profile:main_pages", // 通过profile下的资源文件配置,main_pages名称可修改
  }
}

pages配置文件标签:

  • src:描述所有路由信息
  • window:定义与窗口显示相关的配置,可为空
    • designWidth:页面设计基准宽度,以此为基准,根据实际设备宽度来缩放元素,默认时720px
    • autoDesignWidth:页面设计基准宽度是否自动计算,由设备宽度与屏幕密度计算得出,默认为false

6.1.3 metadata标签

标识HAP的自定义元信息,标签为数组,包含name value resource:

  • name:名称
  • value:数据项的值
  • resource:定义用户自定义数据格式,标签值为该数据的资源的索引
{
  "module": {
    "metadata": [{
      "name": "module_metadata",
      "value": "a test demo for module metadata",
      "resource": "$profile:shortcuts_config",
    }],

    "abilities": [{
      "metadata": [{
        "name": "ability_metadata",
        "value": "a test demo for ability",
        "resource": "$profile:config_file"
      },
      {
        "name": "ability_metadata_2",
        "value": "a string test",
        "resource": "$profile:config_file"
      }],
    }],

    "extensionAbilities": [{
      "metadata": [{
        "name": "extensionAbility_metadata",
        "value": "a test for extensionAbility",
        "resource": "$profile:config_file"
      },
      {
        "name": "extensionAbility_metadata_2",
        "value": "a string test",
        "resource": "$profile:config_file"
      }],
    }]
  }
}

6.1.4 abilities标签

描述UIAbility组件的配置信息,标签值为数组类型,该标签下的配置只对当前UIAbility生效:

属性名 描述
name 当前UIAbility组件的名称,整个应用内要唯一
srcEntry 入口UIAbility的代码路径
launchType 启动模式:multiton 每次启动都新建,singleton 单例,specified 运行时由开发者决定
description 描述
icon 图标
label 显示的名称,支持多语言,唯一
permissions 权限信息
metadata 当前UIAbility组件的元信息
exported 是否可以被其他应用调用
continuable 是否可以前一
skills 能否接受Want的特征集
backgroundModes 后台长任务类型
startWindowIcon 当前UIAbility组件启动页面图标资源文件的索引
removeMissionAfterTerminate 标识销毁后是否从任务列表中移除
orientation 组件启动时的方向
supportWindowMode 窗口模式:fullscreen split floating
priority 优先级,0 -> 10
maxWindowRatio 支持的最大的窗口宽高比
minWindowRatio 支持的最小的窗口宽高比
maxWindowWidth 支持的最大的窗口高度 vp
minWindowWidth 支持的最小的窗口宽度 vp
maxWindowHeight 支持的最大的窗口高度 vp
minWindowHeight 支持的最小的窗口高度 vp
excludeFromMissions 是否在最近任务列表中展示,仅支持系统应用
{
  "abilities": [{
    "name": "EntryAbility",
    "srcEntry": "./ets/entryability/EntryAbility.ts",
    "launchType":"singleton",
    "description": "$string:description_main_ability",
    "icon": "$media:icon",
    "label": "Login",
    "permissions": [],
    "metadata": [],
    "exported": true,
    "continuable": true,
    "skills": [{
      "actions": ["ohos.want.action.home"],
      "entities": ["entity.system.home"],
      "uris": []
    }],
    "backgroundModes": [
      "dataTransfer",
      "audioPlayback",
      "audioRecording",
      "location",
      "bluetoothInteraction",
      "multiDeviceConnection",
      "wifiInteraction",
      "voip",
      "taskKeeping"
    ],
    "startWindowIcon": "$media:icon",
    "startWindowBackground": "$color:red",
    "removeMissionAfterTerminate": true,
    "orientation": " ",
    "supportWindowMode": ["fullscreen", "split", "floating"],
    "maxWindowRatio": 3.5,
    "minWindowRatio": 0.5,
    "maxWindowWidth": 2560,
    "minWindowWidth": 1400,
    "maxWindowHeight": 300,
    "minWindowHeight": 200,
    "excludeFromMissions": false
  }]
}

原文链接:https://juejin.cn/post/7347911150335574016 作者:沉江小鱼

(0)
上一篇 2024年3月20日 上午10:05
下一篇 2024年3月20日 上午10:17

相关推荐

发表评论

登录后才能评论