3

鸿蒙APP开发学习01 - 项目结构说明

 6 months ago
source link: https://blog.devwiki.net/2024/02/27/Harmony-app-dev-01-project-struct.html#cl-12
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

image-20240227102300858

鉴于国内情况, 鸿蒙开发也是一个技术方向, 现在就开始一起学习一下鸿蒙App开发。

实际上,可以当成一个Android App项目开发学习, 其开发工具DevEco 和 Android Studio都很相似,都是定制的IDEA。

项目工程结构以及模式也和Android App类似,区别在于使用的语言以及 Application 模型。

花不多少,let`s code ~

1. 新建项目

打开DevEco Studio, 选择 Create Project:

1.1 选择模版

Create Project - Choose Template

image-20240226161318013

1.2 配置项目

Create Project - Configure Project

如果使用的是 DevEco 3.X 版本, 可以根据 Compile SDK版本选择不同的模式, 比如:

  • 3.0.0(API 8)及更早 - 仅支持 FA模式, 支持 ArkTS语言和 JS语言

image-20240227105005739
  • 3.1.0(API 9) - 支持Stage 和 FA 模式, 仅支持ArkTS语言

image-20240227104834924

如果使用的DevEco 4.X 版本,则默认就是 Stage模式和ArkTS语言, 且不支持切换模式和语言, 但是支持选择nodejs 版本:

image-20240227104711683

从工具默认选择看:

  • Satge 模式 是官网主推模式
  • ArkTS语言是官方主推语言, 后续不再支持创建选择JS语言
  • 不再默认支持低代码模式(Enable Super Visual)
  • 支持的Device从 Phone到 Tablet 以及 2in1.
  • 支持自定义主入口名称 entry, 可更像 Android那样设置为 app
  • 支持选择 nodejs 版本

2. 项目结构

2.1 Stage模型应用

根据官方的表述 Stage模型的应用包结构如下,

  • 一个应用入口 Entry.hap
  • 一到多个功能Feature.hap
@startuml
node "App Pack(xxx.app)"{
    
    node "Entry.hap" {
        [ets] as 0
        [resources] as 1
        [libs] as 2
        [resources.index] as 3
        [module.json] as 4
    }
    
    node  "FeatureA.hap" {
        [ets] as 5
        [resources] as 6
        [libs] as 7
        [resources.index] as 8
        [module.json] as 9
    }
    
    node "FeatureB.hap" {
        [ets] as 10
        [resources] as 11
        [libs] as 12
        [resources.index] as 13
        [module.json] as 14
    }
    
    component pak.info
    
    Entry.hap -d[hidden]- FeatureA.hap
    FeatureA.hap -d[hidden]- FeatureB.hap
    FeatureB.hap -d[hidden]- pak.info
    
}
@enduml
Plantuml

image-20240227112501242

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

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

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

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

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

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

具体到上面的项目, app.json5如下:

{
  "app": {
    "bundleName": "net.devwiki.hmdemo", // 类似于包名
    "vendor": "example", // id
    "versionCode": 1000000, // 版本号
    "versionName": "1.0.0", // 版本名称
    "icon": "$media:app_icon", // 图标
    "label": "$string:app_name" // 名称
  }
}
  • icon 为 AppScope/resources/base/media 文件夹下的 app_icon.png
  • label 为 AppScope/resources/base/string.json 中的 app_name
{
  "string": [
    {
      "name": "app_name",
      "value": "HMDemo"
    }
  ]
}

其他的字段说明参见:

app.json5配置文件-应用配置文件(Stage模型)-开发基础知识-入门 | 华为开发者联盟
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/app-configuration-file-0000001427584584-V2

image-20240227140155406

此处以 HM3Demo为例,项目文件夹结构如下:

image-20240227105731933

各个文件夹及文件说明如下:

  • .hvigor : 项目编译构建文件夹(可忽略)
  • .idea : IDEA项目配置文件夹(可忽略)
  • AppScope > app.json5:应用的全局配置信息。
  • entry:HarmonyOS工程模块,编译构建生成一个HAP包。

    • src > main > ets:用于存放ArkTS源码。
    • src > main > ets > entryability:应用/服务的入口。
    • src > main > ets > pages:应用/服务包含的页面。
    • src > main > resources:用于存放应用/服务所用到的资源文件,如图形、多媒体、字符串、布局文件等。关于资源文件,详见资源分类与访问
    • src > main > module.json5:Stage模型模块配置文件。主要包含HAP包的配置信息、应用/服务在具体设备上的配置信息以及应用/服务的全局配置信息。具体的配置文件说明,详见module.json5配置文件
    • build-profile.json5:当前的模块信息、编译信息配置项,包括buildOption、targets配置等。其中targets中可配置当前运行环境,默认为HarmonyOS。
    • hvigorfile.ts:模块级编译构建任务脚本,开发者可以自定义相关任务和代码实现。
  • hvigor : 项目插件配置

2.2 程序入口entry

DevEco 3.x 的项目中程序入口为默认的 entry 模块, 在DevEco 4.x 版本可以自定义名称为 app。

在 entry(app)模块的ets/entryability目录下的 EntryAbility.ts为程序入口:

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';

export default class EntryAbility extends UIAbility {
  onCreate(want, launchParam) {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  }

  onDestroy() {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage) {
    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    windowStage.loadContent('pages/Index', (err, data) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
    });
  }

  onWindowStageDestroy() {
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground() {
    // Ability has brought to foreground
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
  }

  onBackground() {
    // Ability has back to background
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

此处为 UIAbility的子类, UIAbility组件是一种包含UI界面的应用组件,主要用于和用户交互。

UIAbility组件是系统调度的基本单元,为应用提供绘制界面的窗口;一个UIAbility组件中可以通过多个页面来实现一个功能模块。每一个UIAbility组件实例,都对应于一个最近任务列表中的任务。

在 entry 的 module.json5 配置中配置了入口, "mainElement": "EntryAbility",,

{
  "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"
            ]
          }
        ]
      }
    ]
  }
}

具体的属性说明参见:

module.json5配置文件-应用配置文件(Stage模型)-开发基础知识-入门 | 华为开发者联盟
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/module-configuration-file-0000001427744540-V2

image-20240227140244707

在 EntryAbility 的 onWindowStageCreate 函数中 指定了启动页面:

  onWindowStageCreate(windowStage: window.WindowStage) {
    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    windowStage.loadContent('pages/Index', (err, data) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
    });
  }

入口页面的内容为一个文本框:

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
    }
    .height('100%')
  }
}
TypeScript

image-20240227115507052

2.3 资源文件

资源文件存储在 entry/src/main/resources目录内,包含:

  • base : 通用的文件目录

    • element : 包含字符串,颜色等资源文件
    • media: 包含多媒体资源文件
    • profile : 包含 page里面的UI路由配置文件
  • 语言_国家: I18N资源文件

    • 子目录和base 类似
  • rawfile : raw 资源文件目录

更详细的参见:

资源分类与访问-入门 | 华为开发者联盟
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/resource-categories-and-access-0000001711674888-V2

3. 构建配置

和Android项目类似, 鸿蒙APP项目有应用级别构建配合和模块级别构建配置:

  • 根目录的 build-profile.json5
  • module 目录下的 build-profile.json5

3.1 应用构建配置

项目根目录 build-profile.json5文件为构建配置:

{
  "app": {
    "signingConfigs": [],
    "compileSdkVersion": 9,
    "compatibleSdkVersion": 9,
    "products": [
      {
        "name": "default",
        "signingConfig": "default",
      }
    ]
  },
  "modules": [
    {
      "name": "entry",
      "srcPath": "./entry",
      "targets": [
        {
          "name": "default",
          "applyToProducts": [
            "default"
          ]
        }
      ]
    }
  ]
}

API Version 9、API Version 8与API Version 4~7的构建体系不同,因此在设置编译构建信息时也存在差异:

  • API Version 9:需要对构建配置文件、构建脚本、应用依赖的共享包等信息进行设置。

    • build-profile.json5:应用/服务构建配置文件。
    • hvigorfile.ts:自定义编译构建脚本。
    • oh-package.json5:应用的三方包依赖,支持共享包的依赖。
  • API Version 8:需要对构建配置文件、构建脚本、应用依赖的npm包等信息进行设置。

    • build-profile.json5:HarmonyOS应用/服务构建配置文件。
    • hvigorfile.ts:自定义编译构建脚本。
    • package.json:应用的三方包依赖,支持HAR(遵循npm标准规范)和npm包的依赖。
  • API Version 4~7:需要通过build.gradle来对工程编译构建参数进行设置。

常用的字段说明如下:

{
  "app": { 
    //工程的签名信息,可包含多个签名信息
    "signingConfigs": [  
      {
        "name": "default",  //标识签名方案的名称
        "type": "HarmonyOS",  //标识HarmonyOS应用
        //该方案的签名材料
        "material": {  
          "certpath": "D:\\SigningConfig\\debug_hos.cer",  //调试或发布证书文件,格式为.cer
          "storePassword": "******",  //密钥库密码,以密文形式呈现
          "keyAlias": "debugKey",  //密钥别名信息
          "keyPassword": "******",  //密钥密码,以密文形式呈现
          "profile": "D:\\SigningConfig\\debug_hos.p7b",  //调试或发布证书Profile文件,格式为.p7b
          "signAlg": "SHA256withECDSA",  //密钥库signAlg参数
          "storeFile": "D:\\SigningConfig\\debug_hos.p12"  //密钥库文件,格式为.p12
        }
      }
    ],
    "compileSdkVersion": 9,  //指定HarmonyOS应用/服务编译时的SDK版本
    "compatibleSdkVersion": 9,  //指定HarmonyOS应用/服务兼容的最低SDK版本
    //定义构建的产品品类,如通用默认版、付费版、免费版等
    "products": [  
      {
        "name": "default",  //定义产品的名称,支持定制多product目标产物,具体请参考定制多目标构建产物
        "signingConfig": "default",  //指定当前产品品类对应的签名信息,签名信息需要在signingConfigs中进行定义
      }
    ]
  },
  "modules": [
    {
      "name": "entry",  //模块名称
      "srcPath": "./entry",  //标明模块根目录相对工程根目录的相对路径
      "targets": [  //定义构建的APP产物,由product和各模块定义的targets共同定义
        {
          "name": "default",  //target名称,由各个模块的build-profile.json5中的targets字段定义
          "applyToProducts": [  
            "default"   //表示将该模块下的“default” Target打包到“default” Product中
          ]
        }
      ]
    }
  ]
}

更具体的信息参见:

配置编译构建信息-编译构建-DevEco Studio使用指南-工具 | 华为开发者联盟 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/build_config-0000001052902431-V2

3.2 module构建配置

在 entry 模块的目录也有一个 build-profile.json文件:

{
  "apiType": 'stageMode',
  "buildOption": {
  },
  "targets": [
    {
      "name": "default",
      "runtimeOS": "HarmonyOS"
    },
    {
      "name": "ohosTest",
    }
  ]
}

详细的字段说明如下:

{
  "apiType": 'faMode',  //API类型,支持FA和Stage模型
  "showInServiceCenter": true,  //是否在服务中心展示
  "buildOption": {
    //配置筛选har依赖.so资源文件的过滤规则
    "napiLibFilterOption": {
      //按照.so文件的优先级顺序,打包最高优先级的.so文件
      "pickFirsts": [
        "**/1.so"
      ],
      //按照.so文件的优先级顺序,打包最低优先级的.so 文件
      "pickLasts": [
        "**/2.so"
      ],
      //排除的.so文件
      "excludes": [
        "**/3.so"
      ],
      //允许当.so重名冲突时,使用高优先级的.so文件覆盖低优先级的.so文件
      "enableOverride": true
    },
    //cpp相关编译配置
    "externalNativeOptions": {
      "path": "./src/main/cpp/CMakeLists.txt",  //CMake配置文件,提供CMake构建脚本
      "arguments": "",  //传递给CMake的可选编译参数
      "abiFilters": [  //用于设置本机的ABI编译环境
        "armeabi-v7a",
        "arm64-v8a"
      ],
      "cppFlags": ""  //设置C++编译器的可选参数
    },
  },
  "targets": [  //定义的Target,开发者可以定制不同的Target,具体请参考定制多目标构建产物
    {
      "name": "default",
      "runtimeOS": "HarmonyOS",
    },
    {
      "name": "ohosTest",
    }    
  ]
}

更具体的信息参见:

配置编译构建信息-编译构建-DevEco Studio使用指南-工具 | 华为开发者联盟 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/build_config-0000001052902431-V2

至此, 一个默认的人 鸿蒙App 项目结构已经学习完毕, 通过对比和 Android有很多相似之处。可以说是照着Android的工程来对标的。

后续会进一步学习UI组件等相关知识。 关注我持续学习~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK