Skip to content

Latest commit

 

History

History
448 lines (320 loc) · 20.5 KB

4.HarmonyOS应用开发初探.md

File metadata and controls

448 lines (320 loc) · 20.5 KB

4.HarmonyOS应用开发初探

因为OpenHarmony API 9开始新增的Stage模型,是目前主推且会长期演进的模型。 所以后面会全部使用Stage模型进行开发

开发IDE

DevEco Studio

DevEco是基于inteliJ开源项目进行开发的,所以和Android Studio基本一样。
开发工具整体来看和Android Studio基本类似。

直接下载安装即可。 整个使用和Android Studio基本一样。

接下来通过Create Project创建一个新项目。 image 这里选Empty Ablity的就可以。

Ability:应用的基本组成部分,是应用所具备能力的抽象。Ability是系统调度应用的最小单元,是能够完成一个独立功能的组件,一个应用可以包含一个或多个Ability。 在FA模型与Stage模型,分别定义了不同类型的Ability。
鸿蒙应用实际是通过Ability框架进行开发的,Ability在英文解释中是能力的意思。鸿蒙认为开发一个应用程序,其实是对设备能力的一种实现。
Ability是应用所具备能力的抽象,也是应用程序的重要组成部分。一个应用可以具备多种能力(即可以包含多个Ability),HarmonyOS支持应用以Ability为单位进行部署。

接下来就是和Android Studio一样,填项目名、Bundle name就是包名,是应用程序的唯一标识,一般用公司的域名 com.huawei.xxx这样。
Compatible SDK目前最新的就是API 9.
这里有个Enable Super Visual,这是一种低代码的开发模式,对于一些简单的app可以使用,一般不用使用。 image

接着就能看到整个项目的目录:

从上往下看:

  • AppScode中存放应用全局所需要的资源文件:

    • AppScope下的app.json5 :应用的全局配置信息,存放应用公共的配置信息。例如: bundleName、versionName、icon、appName等。
    • resource -> base -> element: 存放公众的字符串、布局文件等资源。
    • resource -> base -> media: 全局公共的多媒体资源文件。
{
  "app": {
    "bundleName": "com.example.harmonyapp",
    "vendor": "example",
    "versionCode": 1000000,
    "versionName": "1.0.0",
    "icon": "$media:app_icon",
    "label": "$string:app_name"
  }
}
  • entry:应用的主模块,存放Harmony OS应用的代码、资源等。编译构建生成一个HAP包。

    • oh-package.json5: 工程级依赖配置文件,用于记录引入包的配置信息。
    • src > main > ets:用于存放ArkTS源码。下面又分为entryability:应用/服务的入口和pages:应用/服务包含的页面。
    • src > main > resources:用于存放应用/服务所用到的资源文件,如图形、多媒体、字符串、布局文件等。关于资源文件,详见资源文件的分类。
    • src > main > module.json5:模块配置文件。主要包含HAP包的配置信息、应用/服务在具体设备上的配置信息以及应用/服务的全局配置信息。
{
	"module": {
	"name": "entry",
	"type": "entry",
	"description": "$string:module_desc",
	"mainElement": "EntryAbility",
	"deviceTypes": [
	  "phone",
	  "tablet"
	],
	"deliveryWithInstall": true,
	"installationFree": false,
	"pages": "$profile:main_pages",
	"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": [
	          "action.system.home"
	        ]
	      }
	    ]
	  }
	]
	}
}

每个应用项目的代码目录下必须包含应用配置文件,这些配置文件会向编译工具、操作系统和应用市场提供应用的基本信息。

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

app.json5(应用的全局配置文件)配置文件主要包含以下内容:

  • 应用的全局配置信息,包含应用的Bundle名称、开发厂商、版本号等基本信息。

  • 特定设备类型的配置信息。

module.json5(模块的配置文件)配置文件主要包含以下内容:

  • Module的基本配置信息,包含Module名称、类型、描述、支持的设备类型等基本信息。

  • 应用组件信息,包含UIAbility组件和ExtensionAbility组件的描述信息。

  • 应用运行过程中所需的权限信息。

  • build-profile.json5:当前的模块信息 、编译信息配置项,包括buildOption、targets配置等。

{
  "apiType": 'stageMode',
  "buildOption": {
  },
  "targets": [
    {
      "name": "default",
      "runtimeOS": "HarmonyOS"
    },
    {
      "name": "ohosTest",
    }
  ]
}
  • hvigorfile.ts:工程级编译构建任务脚本,hvigor是基于任务管理机制实现的一款全新的自动化构建工具,主要提供任务注册编排,工程模型管理、配置管理等核心能力。

  • obfuscation-rules.txt:混淆规则文件。混淆开启后,在使用Release模式进行编译时,会对代码进行编译、混淆及压缩处理,保护代码资产。

  • build-profile.json5:工程级级配置信息,包括签名signingConfigs、产品配置products等。

  • hvigorfile.ts:应用级编译构建任务脚本。

  • oh_modules:工程的依赖包,存放工程依赖的源文件。

  • src/main/resources/base/profile/main_pages.json: 保存的是页面page的路径配置信息,所有需要进行路由跳转的page页面都要在这里进行配置。

HarmonyOS的用户应用程序包以App Pack(Application Package)形式发布,它由一个或多个HAP(HarmonyOS Ability Package)以及描述每个HAP属性的pack.info组成。HAP是Ability的部署包,HarmonyOS应用代码围绕Ability组件展开。

很多应用由多个页面组成,比如用户可以从音乐列表页面单击歌曲,跳转到该歌曲的播放界面。开发者需要通过页面路由将这些页面串联起来,按需实现跳转。

装饰器:方舟开发框架定义了一些具有特殊含义的装饰器,用于装饰类、结构、方法和变量。例如,上例中的@Entry、@Component和@State都是装饰器。

import router from '@ohos.router'
// 装饰的自定义组件用作页面的默认入口组件,加载页面时,将首先创建并呈现@Entry装饰的自定义组件
@Entry
// 装饰的struct表示该接口提具有组件化能力,能够成为一个独立的组件
@Component
// 自定义组件内容
struct Index {
  // @State装饰的变量是组件内部的状态数据,当状态数据被修改时,会自动进行UI刷新
  @State message: string = 'Hello World'
  // 自定义组件必须定义build方法,在其中以声明式的方式进行UI描述
  build() {
    // ArkUI提供的容器行组件
    Row() {
      // ArkUI提供的容器列组件
      Column() {
        // ArkUI提供的容器基础组件,如文字、字体大小、字体加粗
        Text(this.message)
          // 设置组件UI样式的属性方法
          .fontSize(50)
          .fontWeight(FontWeight.Bold)

        // 添加按钮,以响应用户点击
        Button() {
          // 按钮文案、文字大小颜色、样式
          Text('戳我')
            .fontSize(40)
            .fontColor(Color.Red)
              // 比粗体更粗
            .fontWeight(FontWeight.Bolder)
        }.type(ButtonType.Capsule) // 按钮风格: 胶囊型按钮(圆角默认为高度的一半)
        .margin({
          // 距离上一个的高度
          top: 20
        })
        .onClick(() => {
          // 跳转到第二个页面
          // 页面路由router根据页面的uri找到目标页面,从而实现跳转。
          // 这个url路径就是main_pages.json中配置的路径
          router.pushUrl({url: 'pages/Second'}).then(() => {
            console.info('start second page')
          })
        })
        .backgroundColor('#0D9FFB')
        .width('40%')
        .height('5%')
      }
      // 列布局的宽为屏幕宽度
      .width('100%')
    }
    // 行布局的高度为屏幕高度
    .height('100%')
  }
}

ArkTS通过装饰器@Component和@Entry装饰struct关键字声明的数据结构,构成一个自定义组件。自定义组件中提供了一个build函数,开发者需在该函数内以链式调用的方式进行基本的UI描述.

image

  • 装饰器: 用于装饰类、结构、方法以及变量,并赋予其特殊的含义。 如上述示例中@Entry、@Component和@State都是装饰器,@Component表示自定义组件,@Entry表示该自定义组件为入口组件,@State表示组件中的状态变量,状态变量变化会触发UI刷新。
  • UI描述:以声明式的方式来描述UI的结构,例如build()方法中的代码块。
  • 自定义组件:可复用的UI单元,可组合其他组件,如上述被@Component装饰的struct Hello。
  • 系统组件:ArkUI框架中默认内置的基础和容器组件,可直接被开发者调用,比如示例中的Column、Text、Divider、Button。
  • 属性方法:组件可以通过链式调用配置多项属性,如fontSize()、width()、height()、backgroundColor()等。
  • 事件方法:组件可以通过链式调用设置多个事件的响应逻辑,如跟随在Button后面的onClick()。
  • 系统组件、属性方法、事件方法具体使用可参考基于ArkTS的声明式开发范式。

下面新加一个页面Second.ets。 新加页面之后需要在resource-base-profile-main_pages.json文件中增加Second.ets页面的配置:

{
  "src": [
    "pages/Index",
    "pages/Second"
  ]
}

下面写第二个页面的内容:

// router 需要导包,写router后会自动导入
import router from '@ohos.router'
@Entry
@Component
struct Second {
  // 注意string是小写,不是String
  @State message: string = "Hello HarmonyOS"

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
        Button() {
          Text('Back')
            .fontSize(25)
            .fontWeight(FontWeight.Bold)
        }
        .type(ButtonType.Capsule)
        .margin({
          top: 20
        })
        .backgroundColor('#0D9FFB')
        .width('40%')
        .height('5%')
        .onClick(() => {
          // 点击按钮返回上一个页面
          router.back();
        })
      }
      .width('100%')
    }
    .height('100%')
  }
}

在开发态,一个应用包含一个或者多个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组件

  • 开发者通过DevEco Studio把应用程序编译为一个或者多个.hap后缀的文件,即HAP。HAP是应用安装的基本单位,包含了编译后的代码、资源、三方库及配置文件。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文件,一个应用中的.hap文件合在一起称为一个Bundle,而bundleName就是应用的唯一标识(请参见app.json5配置文件中的bundleName标签)。需要特别说明的是:在应用上架到应用市场时,需要把应用包含的所有.hap文件(即Bundle)打包为一个.app后缀的文件用于上架,这个.app文件称为App Pack(Application Package),其中同时包含了描述App Pack属性的pack.info文件;在云端分发和端侧安装时,都是以HAP为单位进行分发和安装的。

image

多HAP使用规则:

  • App Pack包不能直接安装到设备上,只是上架应用市场的单元。

  • App Pack包打包时会对每个HAP在json文件中的配置进行校验,确保bundleName、versionCode等标签取值相同,详见App打包时的HAP合法性校验。

  • App Pack包中同一设备类型的所有HAP中必须有且只有一个Entry类型的HAP,Feature类型的HAP可以有一个或者多个,也可以没有。

  • App Pack包中的每个HAP必须配置moduleName标签,同一设备类型的所有HAP对应的moduleName标签必须唯一。

  • 同一应用的所有HAP签名证书要保持一致。上架应用市场是以App Pack的形式上架,并对其进行了签名。应用市场分发时会将所有HAP从App Pack中拆分出来,同时对其中的所有HAP进行重签名,这样保证了所有HAP签名证书的一致性。在调试阶段,开发者通过命令行或IDE将HAP安装到设备上时要保证所有HAP签名证书一致,否则会出现安装失败的问题。

image

共享包概述

当前系统提供了两种共享包,HAR(Harmony Archive)静态共享包和HSP(Harmony Shared Package)动态共享包:

  • HAR(Harmony Archive)是静态共享包,可以包含代码、C++库、资源和配置文件。通过HAR可以实现多个模块或多个工程共享ArkUI组件、资源等相关代码。HAR不同于HAP,不能独立安装运行在设备上,只能作为应用模块的依赖项被引用。
  • HSP(Harmony Shared Package)是动态共享包,按照使用场景可以分为应用内HSP和应用间HSP。应用内HSP指的是专门为某一应用开发的HSP,只能被该应用内部其他HAP/HSP使用,用于应用内部代码、资源的共享。应用内HSP跟随其宿主应用的APP包一起发布,与宿主应用同进程,具有相同的包名和生命周期。(当前暂不支持应用间HSP)

HAR与HSP都是为了实现代码和资源的共享,都可以包含代码、C++库、资源和配置文件,最大的不同之处在于:HAR中的代码和资源跟随使用方编译,如果有多个使用方,它们的编译产物中会存在多份相同拷贝;而HSP中的代码和资源可以独立编译,运行时在一个进程中代码也只会存在一份。

image

HSP旨在解决多个模块引用相同的HAR,导致APP包大小膨胀的问题。

使用HSP的约束条件:

  • HSP及其使用方都必须是Stage模型。
  • HSP及其使用方都必须使用esmodule编译模式。
  • HSP不支持在配置文件中声明abilities、extensionAbilities标签。

导出native方法

在HAR中也可以包含C++编写的so。对于so中的native方法,HAR通过以下方式导出,以导出libnative.so的加法接口add为例:

// library/src/main/ets/utils/nativeTest.ts
import native from "libnative.so"

export function nativeAdd(a: number, b: number) {
    let result: number = native.add(a, b);
    return result;
}

资源访问

应用资源

对于应用资源,在工程中,通过"$r('app.type.name')"形式引用。其中,app为应用内resources目录中定义的资源;type为资源类型或资源的存放位置,取值包含“color”、“float”、“string”、“plural”、“media”;name为资源命名,由开发者定义资源时确定。

对于rawfile目录资源,通过"$rawfile('filename')"形式引用。其中,filename为rawfile目录下文件的相对路径,文件名需要包含后缀,路径开头不可以以"/"开头。

对于rawfile目录的descriptor,可通过资源管理的getRawFd接口引用,其返回值descriptor.fd为hap包的fd。此时,访问rawfile文件需要结合{fd, offset, length}一起使用。

说明:

  • 资源描述符不能拼接使用,仅支持普通字符串如'app.type.name'。

  • $r返回值为Resource对象,可通过getStringValue 方法获取对应的字符串。

资源组目录下的“资源文件示例”显示了.json文件内容,包含color.json文件、string.json文件和plural.json文件,访问应用资源时需先了解.json文件的使用规范。 资源的具体使用方法如下:

Text($r('app.string.string_hello'))
  .fontColor($r('app.color.color_hello'))
  .fontSize($r('app.float.font_hello'))

Text($r('app.string.string_world'))
  .fontColor($r('app.color.color_world'))
  .fontSize($r('app.float.font_world'))

// 引用string.json资源。Text中$r的第一个参数指定string资源,第二个参数用于替换string.json文件中的%s。
//如下示例代码value为"We will arrive at five of the clock"。
Text($r('app.string.message_arrive', "five of the clock"))
  .fontColor($r('app.color.color_hello'))
  .fontSize($r('app.float.font_hello'))

// 引用plural$资源。Text中$r的第一个指定plural资源,第二个参数用于指定单复数(在中文,单复数均使用other。在英文,one:代表单数,取值为1;other:代表复数,取值为大于等于1的整数),第三个参数用于替换%d
// 如下示例代码为复数,value为"5 apples"。
Text($r('app.plural.eat_apple', 5, 5))
  .fontColor($r('app.color.color_world'))
  .fontSize($r('app.float.font_world'))

Image($r('app.media.my_background_image'))  // media资源的$r引用

Image($rawfile('test.png'))                 // rawfile$r引用rawfile目录下图片

Image($rawfile('newDir/newTest.png'))       // rawfile$r引用rawfile目录下图片

系统资源

除了自定义资源,开发者也可以使用系统中预定义的资源,统一应用的视觉风格。可以查看应用UX设计中关于资源的介绍,获取支持的系统资源ID及其在不同配置下的取值。

在开发过程中,分层参数的用法与资源限定词基本一致。对于系统资源,可以通过“$r('sys.type.resource_id')”的形式引用。其中,sys为系统资源;type为资源类型,取值包括“color”、“float”、“string”、“media”;resource_id为资源id。

说明:

  • 仅声明式开发范式支持使用系统资源。

  • 对于系统预置应用,建议使用系统资源;对于三方应用,可以根据需要选择使用系统资源或自定义应用资源。

Text('Hello')
  .fontColor($r('sys.color.ohos_id_color_emphasize'))
  .fontSize($r('sys.float.ohos_id_text_size_headline1'))
  .fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
  .backgroundColor($r('sys.color.ohos_id_color_palette_aux1'))

Image($r('sys.media.ohos_app_icon'))
  .border({
    color: $r('sys.color.ohos_id_color_palette_aux1'),
    radius: $r('sys.float.ohos_id_corner_radius_button'), width: 2
  })
  .margin({
    top: $r('sys.float.ohos_id_elements_margin_horizontal_m'),
    bottom: $r('sys.float.ohos_id_elements_margin_horizontal_l')
  })
  .height(200)
  .width(300)