HarmonyOS鸿蒙应用开发 (二、应用程序包结构理解及Ability的跳转,与Android的对比)

在进行应用开发前,对程序的目录及包结构的理解是有必要的。如果之前有过android开发经验的,会发现OpenHarmony的应用开发也很简单,有很多概念是相似的。下面对比android分析总结下鸿蒙的应用程序包结构,以及鸿蒙对比android的诸多亮点。从这些亮点上看,可以毫不客气的说,鸿蒙系统是对android系统的一种超越。

鸿蒙应用程序包结构

在基于Stage模型开发应用之前,开发者需要熟悉开发态的应用程序结构、以及编译打包后的应用程序包结构。

在开发中,一个应用包含一个或者多个Module,可以在DevEco Studio工程中创建一个或者多个Module。Module是应用/服务的基本功能单元,包含了源代码、资源文件、第三方库及应用/服务配置文件,每一个Module都可以独立进行编译和运行。Module分为“Ability”和“Library”两种类型,“Ability”类型的Module对应于编译后的HAP(Harmony Ability Package);“Library”类型的Module对应于HAR(Harmony Archive),或者HSP(Harmony Shared Package)。 一个Module可以包含一个或多个UIAbility组件,如Module与UIAbility组件关系示意图所示。

Module与UIAbility组件关系示意图

从图中可以看出,一个app可以包含一个或多个Module。每个Module内,又可以包含一个或多个Ability,一个Ability中可以包含多个page页面。 鸿蒙的app,把模块化做到了极致,有着不错的结构。其中的每个Module,都是单独的可独立运行的单元,每个Module都可以单独编译为.hap包。

Module是应用/服务的基本功能单元,包含了源代码、资源文件、第三方库及应用/服务配置文件,每一个Module都可以独立进行编译和运行。一个HarmonyOS应用/服务通常会包含一个或多个Module,因此,可以在工程中创建多个Module,每个Module分为Ability和Library两种类型。

HAP是应用安装的基本单位,包含了编译后的代码、资源、三方库及配置文件。

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

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

  • Entry类型的HAP:是应用的主模块,在module.json5配置文件中的type标签配置为“entry”类型。在同一个应用中,同一设备类型只支持一个Entry类型的HAP,通常用于实现应用的入口界面、入口图标、主特性功能等。
  • Feature类型的HAP:是应用的动态特性模块,在module.json5配置文件中的type标签配置为“feature”类型。一个应用程序包可以包含一个或多个Feature类型的HAP,也可以不包含;Feature类型的HAP通常用于实现应用的特性功能,可以配置成按需下载安装,也可以配置成随Entry类型的HAP一起下载安装(请参见module对象内部结构中的“deliveryWithInstall”)。

打包后的HAP结构包括ets、libs、resources等文件夹和resources.index、module.json、pack.info等文件。

  • ets目录用于存放应用代码编译后的字节码文件。
  • libs目录用于存放库文件。库文件是应用依赖的第三方代码(.so二进制文件)。
  • resources目录用于存放应用的资源文件(字符串、图片等),便于开发者使用和维护,详见资源文件的使用。
  • resources.index是资源索引表,由IDE编译工程时生成。
  • module.json是HAP的配置文件,是HAP中非常重要的组成部分,内容由工程配置中的module.json5和app.json5组成。IDE会自动生成一部分默认配置,开发者按需修改其中的配置。详细字段请参见应用配置文件。
  • pack.info是Bundle中用于描述每个HAP属性的文件,例如app中的bundleName和versionCode信息、module中的name、type和abilities等信息,由IDE工具构建Bundle包时自动生成。

这样做的好处?

  • 方便开发者模块化的管理应用,好的应用一般都是模块化管理,模块之间属于松耦合关系。多HAP方便了开发者将业务划分成多个模块,每个模块放到独立的HAP中。例如支付类应用,有统一的主界面,主界面管理“扫一扫”、“收付款”、“消息”、“理财”等各个模块。其中主界面管理其他模块的逻辑在Entry包中实现,而“扫一扫”、“收付款”、“消息”和“理财”等模块在不同的Feature包中实现。可以同时开发多个Feature包,能够实现Feature包单独的开发测试,最终由Entry包统一集成Feature包的特性。

  • 方便开发者将多HAP合理地组合并部署到不同的设备上。例如应用程序包含一个Entry包和两个Featrue包(Feature1和Feature2)。其中Entry包可以部署到设备A和设备B,Feature1只能部署到设备A,Feature2包只部署到设备B上,那么开发者就可以方便的组合Entry和Feature1部署到设备A上,组合Entry和Feature2部署到设备B上。

  • 方便开发者按需加载所需模块,减少包大小。开发者可以将一个应用的某些HAP配置成按需加载。应用在启动阶段初始用不到的特性,可以配置暂不加载,当用户用到这些特性的时候,可由应用自动下载这些特性HAP,一定程度上减少应用包的大小。

多HAP的相关实例

针对多HAP开发,有以下相关实例可供参考:

多HAP(ArkTS)(API9)

鸿蒙中的Ability

鸿蒙操作系统(HarmonyOS)中的Ability是其应用程序组件模型的核心概念,它负责提供应用的特定功能和用户交互界面。在鸿蒙系统中,Ability被设计为一种更灵活、适应分布式设备间协同工作的组件,能够根据不同的设备形态和应用场景提供相应的服务。

基于Stage模型的Ability设计进一步体现了分布式和设备协同的能力。在Stage模型下,Ability主要负责提供应用程序的具体功能和服务,同时能够灵活地适应不同设备形态和用户交互场景。支持不同设备间的Ability无缝调用,例如手机上的PageAbility可以与智慧屏上的同类型Ability协同工作。

与Android的Activity对比

Activity是Android中四大组件之一,Android的应用是由一个或多个Activity组成的。活动(Activity)是一个可视化的用户界面,负责创建一个屏幕窗口,放置 UI 组件,供用户交互。假如我们打开一个应用,看到的整个界面就是一个Activity,当点击一个超链接,跳转到另一个界面,则又是一个新的Activity。

在android中的Activity的启动方法,也可以叫做Activity间的跳转,从一个Activity 跳转到另一个Activity。在Android中,Activity的启动是通过Intent来表达的,Intent是组件之间通信的媒介,专门提供组件互相调用的相关信息。

在android中,不同Activity之间的跳转,使用Intent组件。

Intent intent = new Intent(Activity.this,Activity2.class);
startActivity(intent);

//或者
Intent intent = new Intent(); 
intent.setClassName(FirstActivity.this,"com.xiaozeng.launchapplication.SecondActivity");
startActivity(intent);

例如:

鸿蒙Ability之间的跳转

在应用使用场景中,当用户点击某个按钮时,应用经常需要拉起指定UIAbility组件来完成某些特定任务。下面介绍如何通过显式Want拉起应用内一个指定UIAbility组件。

Want是对象间信息传递的载体, 可以用于应用组件间的信息传递。 Want的使用场景之一是作为startAbility的参数, 其包含了指定的启动目标, 以及启动时需携带的相关数据, 如bundleName和abilityName字段分别指明目标Ability所在应用的包名以及对应包内的Ability名称。当Ability A需要启动Ability B并传入一些数据时, 可使用Want作为载体将这些数据传递给Ability B。

涉及到的一些概念:

  • UIAbility:UIAbility组件是系统调度的基本单元,为应用提供绘制界面的窗口;一个UIAbility组件中可以通过多个页面来实现一个功能模块。每一个UIAbility组件实例,都对应于一个最近任务列表中的任务。
  • UIAbilityContext:UIAbilityContext模块提供允许访问特定Ability的资源的能力,包括对Ability的启动、停止的设置、获取caller通信接口、拉起弹窗请求用户授权等。关于获取UIAbilityContext的方法,推荐使用getContext(this)方式来获取UIAbilityContext。
  • Want:Want是对象间信息传递的载体, 可以用于应用组件间的信息传递。 Want的使用场景之一是作为startAbility的参数, 其包含了指定的启动目标, 以及启动时需携带的相关数据。
  • HiLog:HiLog日志系统,让应用可以按照指定类型、指定级别、指定格式字符串输出日志内容,帮助开发者了解应用的运行状态,更好地调试程序。

api接口模块名:@ohos.app.ability.Want (Want)

导入模块

import Want from '@ohos.app.ability.Want';

基础用法:

  let want = {
      'deviceId': '', // deviceId为空表示本设备
      'bundleName': 'com.extreme.test',
      'abilityName': 'MainAbility',
      'moduleName': 'entry' // moduleName非必选
  };
  this.context.startAbility(want, (error) => {
      // 显式拉起Ability,通过bundleName、abilityName和moduleName可以唯一确定一个Ability
      console.log('error.code = ' + error.code);
  })

传递参数:

let want = {
    bundleName: 'com.example.demo',
    abilityName: 'com.example.demo.MainAbility',
    parameters: {
        keyForString: 'str',
    },
};

当前支持类型:字符串,数字,数组,布尔,对象,文件描述符等。

具体可参考:Want的使用--文档中心

Ability之间的跳转举例:

同一个Module模块下,新建一个UIAbility:TestAbility.ts,在 modlue.json5中 abilities中添加TestAbility。

import common from '@ohos.app.ability.common'


const TAG = "Test"
@Entry
@Component
struct Index {
  @State message: string = 'Hello World'
  private  context = getContext(this) as common.UIAbilityContext
  private  MyNumber: number
  private  MyNString: string;


  // hello = globalThis.hello
  eventHub() {
    this.context.eventHub.emit("event", 1, "test", "hello")

    this.MyNString = globalThis.MyNString
    this.MyNumber = globalThis.MyNumber
    console.info(TAG, `MyNString, ${ this.MyNString}`);
    console.info(TAG, `MyNumber, ${ this.MyNumber}`);
  }

  startOtherAbility() {
    console.info(TAG, `startOtherAbility`);
    let want = {
      deviceId: '', // deviceId为空表示本设备
      bundleName: 'com.example.myapplication',
      abilityName: 'TestAbility',
    }
    try {
      this.context.startAbility(want)
        .then(() => {
          console.info(TAG, `startAbility Success`);
        })
        .catch((err) => {
          console.info(TAG, `Failed: ${JSON.stringify(err)}}`);
        })
    } catch (error) {
      console.log("startAbility error: " + error)
    }
  }
  build() {
    Row() {
      Column() {
        Text("enter Ability")
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(()=>{
            this.startOtherAbility()
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

也可以在不同的模块中发起调用,但在不同的模块中调用时,需要注意些问题:

want,一定要写正确:

 let want = {
      deviceId: '', // deviceId为空表示本设备
      bundleName: 'com.example.myapplication',
      abilityName: 'Module1Ability',
      moduleName: 'module1', // moduleName非必选
    }

另外,还需要在菜单栏 Run->edit configureation, 选择entry,Deploy Multi Hap,选中 Deploy Multil Hap Packages,添加模块。

鸿蒙Ability的优势

尽管鸿蒙中的Ability和Android中的Activity两者都承担着展示UI和响应用户交互的功能,但鸿蒙系统的Ability更加侧重于分布式环境下的能力解耦和服务化,强调跨设备的一致性和协同性,而Android Activity则是在单一设备上构建应用的基本单元,其生命周期管理和页面跳转逻辑相对集中于单个设备内部。

基于Stage模型的Ability设计进一步体现了分布式和设备协同的能力。在Stage模型下,Ability主要负责提供应用程序的具体功能和服务,同时能够灵活地适应不同设备形态和用户交互场景。
鸿蒙 Ability基于Stage模型的特点:

Stage模型:

在鸿蒙系统中,引入了AbilityStage的概念,它是一个容器级别的组件,用于管理和调度多个Ability Slice(页面片段或子能力),类似于Android中的Fragment集合。

AbilityStage可以将一个复杂的界面划分为多个独立的功能模块(AbilitySlice),每个模块都能够独立更新和展示,并且能够在不同的设备之间进行分布式的协同工作。

多设备适配:

鸿蒙系统的Ability不仅局限于单一设备,而是支持跨设备运行和迁移,比如一个PageAbility可以在手机、平板、智慧屏等不同设备上无缝切换和运行。

生命周期管理与通信:

基于Stage模型的Ability具有更为精细和动态的生命周期管理机制,例如AbilitySlice可以根据需要激活和挂起,更加高效地利用系统资源。

Stage模型下的Ability通过Ability框架实现与其他Ability间的高效、灵活通信,支持分布式数据流和事件处理。

对比Android Activity的优势:

分布式特性:鸿蒙Ability的一个显著优势在于它的分布式能力,能更好地支持跨设备的应用开发和部署,打破单个设备的边界,实现服务在不同设备间自由流动和共享。
轻量化与灵活性:

AbilitySlice可以更细粒度地组织应用逻辑,相比于Activity,开发者可以根据实际需求将应用界面分割成更小的功能单元,这些单元可以在同一设备的不同窗口或跨设备间独立加载和呈现。

统一接口与低耦合:

鸿蒙的Ability体系结构强调的是服务化和解耦,通过统一的AbilityContext接口,使得各类型Ability之间的相互调用和数据交互更为简洁和标准化。

总结来说,鸿蒙的Ability在Stage模型的支持下,实现了对传统Activity模型的超越,尤其是在跨设备协同和资源优化方面展现出了更强的优势,更适合未来物联网环境下多形态智能设备的应用开发。

鸿蒙对比android的诸多亮点

为何说鸿蒙系统对android系统来说是一种超越?

鸿蒙系统(HarmonyOS)相较于Android系统,具有以下亮点和超越之处:

分布式架构:

鸿蒙系统的核心优势在于其分布式操作系统设计,能够实现跨设备、跨平台的无缝协同。不同形态的智能终端可以通过鸿蒙系统的分布式能力自由组合和联动,形成一个超级终端网络。相比之下,Android系统在原生状态下并未提供如此深入的分布式支持。

微内核技术:

鸿蒙系统采用微内核设计,相比Android基于Linux宏内核,它更轻量级且安全性更高。微内核仅包含操作系统最基本的服务,能更好地满足物联网设备对实时性和安全性的需求。

统一性与兼容性:

鸿蒙系统强调“万物互联”的理念,同一套系统可运行于各种不同类型的硬件设备上,包括智能手机、智能穿戴、智能家居、车机等,实现真正的全场景覆盖。而Android虽也可应用于多种设备,但往往需要针对不同设备进行深度定制和优化。

性能与流畅度提升:

鸿蒙系统采用了全新的方舟编译器(Ark Compiler),从应用编译阶段就实现了对运行效率和资源占用的优化,使得应用程序在鸿蒙系统上运行更为流畅、响应速度更快。

生态构建与拓展:

鸿蒙系统通过开放HMS Core(华为移动服务)和HarmonyOS SDK等方式,鼓励开发者创建适用于多设备环境的应用程序,以构建更加丰富多元的生态系统,并积极寻求与其他操作系统的兼容。

用户交互创新:

鸿蒙系统引入了原子化服务卡片、万能卡片等新的交互方式,使用户能够更便捷地管理和使用各类服务,同时也为开发者提供了更多的创新空间。

鸿蒙系统在设计理念和技术实现上确实展现出了对传统Android系统的超越,尤其是在跨设备协同、系统架构、性能优化以及未来IoT场景适应性等方面表现突出。不过,Android作为成熟的移动操作系统,在全球拥有庞大的用户基数和丰富的应用生态,对于鸿蒙来说,生态如果起来的话,android将没有可比性。

鸿蒙与Android 其他对比

一、APP

Android:Android应用以APK(Android Package)格式打包,包含DEX字节码、资源文件、清单文件以及其他必要的组件。

鸿蒙:鸿蒙应用以HAP(HarmonyOS Ability Package)的形式打包。一个HAP可以包含一个或多个Ability,以及描述每个Ability属性的pack.info文件。HAP是轻量化和模块化的,支持跨设备分布式部署。HarmonyOS的应用软件包以APP Pack(Application Package)形式发布,它是由一个或多个HAP(HarmonyOS Ability Package)以及描述每个HAP属性的pack.info组成。HAP是Ability的部署包,HarmonyOS应用代码围绕Ability组件展开。

鸿蒙 安卓 对应关系
HAP(entry 、feature) -> module(主模块、子模块),类似于App Bundle,feature可以动态下发
 HAP。

二、Ability

Activity/Ability:
Android:Activity是Android应用程序的基本构建块,用于展示用户界面并与用户交互。生命周期包括onCreate()、onStart()、onResume()等阶段。

鸿蒙:鸿蒙系统的对应概念是Ability,它也承担着显示UI、处理事件等功能,但具有更灵活的设计。Ability包括PageAbility、ServiceAbility等多种类型,并且支持基于Stage模型的AbilitySlice,适合跨设备场景。

Ability是应用所具备的能力的抽象,一个应用可以包含一个或多个Ability。Ability分为两种类型:FA(Feature Ability)和PA(Particle Ability)。FA/PA是应用的基本组成单元,能够实现特定的业务功能。FA有UI界面包括Page,而PA无UI界面包括Service、Data

Page、Service、Data  ->类似android的 activity、service 、contentprovider

AbilitySlice->fragment

三、Intent/Want

Android:Intent用于启动Activity、发送广播或者传递数据,在组件间进行通信。

鸿蒙:在鸿蒙系统中,Intent的概念被扩展为Want,除了基本的启动和通信功能外,还支持更多的分布式能力,如跨设备启动Ability和传输数据。

四、库文件

1.库文件是应用依赖的第三方代码(例如so、jar、bin、har等二进制文件)

2.har->aar

五、资源文件

应用的资源文件(字符串、图片、音频等)存放于resources目录下
1.element->values
2.media->drawable-xhdpi
3.animation->anim
4.layout->layout
5.graphic->drawalbe
6.profile->raw

六、配置文件存储

Android:通常使用SharedPreferences、SQLite数据库、ContentProvider等方式存储配置信息,对于简单的键值对存储,SharedPreferences是一个常用选项。

鸿蒙:鸿蒙提供了ohos.data.storage API,支持轻量级的数据存储服务,开发者可以通过这个API实现配置文件的读写操作。

七、应用配置文件

1.配置文件 (config.json) 是应用的Ability信息,用于声明应用的Ability,以及应用所需权限等信息。

2.config.json->android的是 androidmanifest.xml

八、分布式和跨设备轮转

Android:原生Android系统对跨设备协同的支持相对有限,通过Google Play Services的一些API可实现部分跨设备功能,但并未像鸿蒙那样提供深度集成的分布式架构。

鸿蒙:鸿蒙系统的核心优势之一就是其分布式技术架构,能够轻松实现跨设备间的服务流转、资源共享及任务迁移。例如,一个应用可以在手机上启动,然后无缝切换到智慧屏上继续运行。

九、App的运行方式

Android:Android应用主要在单一设备内运行,尽管有远程控制、多屏协作等功能,但在原生层面并没有实现真正的分布式运行环境。

鸿蒙:鸿蒙系统支持应用在不同形态的智能终端之间自由迁移和联动,实现跨设备的统一管理和调度,从而适应全场景的智能生活体验。

十、pack.info

1.描述应用软件包中每个HAP的属性,由IDE编译生成
2.类似于 BuildConfig 

十一、权限管理

config.json 显示声明,动态申请。

总结来说,鸿蒙操作系统在设计之初就充分考虑了物联网和全场景智能化的需求,因此在分布式能力、跨设备协同等方面表现出更强的适应性和创新性。

其他资源

docs: OpenHarmony documentation | OpenHarmony开发者文档 - Gitee.com

docs: OpenHarmony documentation | OpenHarmony开发者文档 - Gitee.com

ArkTs接口参考--文档中心

使用显式Want启动Ability

文档中心

Stage模型下Ability的创建和使用

HarmonyOS开发(四):UIAbility组件_uiability oncreate参数详解-CSDN博客

HarmonyOS-AppStorage:应用全局的UI状态存储-CSDN博客