前面总结了鸿蒙开发的调试环境配置,今天来看看相关配置规范

# 1 配置规范

# 1.1 工程结构

# 1.1.1 代码目录结构

目前新建项目可选内置的功能生成新项目,默认采用 Stage 模型构建

其目录结构如下

├──entry/src/main/ets                        // 代码区
│  ├──common
│  │  ├──constants
│  │  │  └──CommonConstant.ets               // 常量集合文件
│  │  └──utils
│  │     ├──BroadCast.ets                    // 事件发布订阅管理器
│  │     └──Log.ets                          // 日志打印
│  ├──entryability
│  │  └──EntryAbility.ts                     // 应用入口,承载应用的生命周期
│  ├──model
│  │  ├──EventSourceManager.ets              // 事件资源管理器
│  │  ├──TaskInfo.ets                        // 任务信息存放
│  │  └──TaskInitList.ets                    // 初始化数据
│  ├──pages
│  │  ├──ListIndexPage.ets                   // 页面入口
│  │  └──TaskEditPage.ets                    // 编辑任务页
│  ├──view
│  │  ├──CustomDialogView.ets                // 自定义弹窗统一入口
│  │  ├──TaskDetail.ets                      // 任务编辑详情组件
│  │  ├──TaskEditListItem.ets                // 任务编辑详情Item组件
│  │  ├──TaskList.ets                        // 任务列表组件
│  │  └──TaskSettingDialog.ets               // 弹窗组件
│  └──viewmodel
│     ├──FrequencySetting.ets                // 频率范围设置
│     └──TaskTargetSetting.ets               // 任务目标设置
└──entry/src/main/resources
   ├──base
   │  ├──element                             // 字符串以及颜色的资源文件
   │  ├──media                               // 图片等资源文件
   │  └──profile                             // 页面配置文件存放位置
   ├──en_US
   │  └──element
   │     └──string.json                      // 英文字符存放位置
   ├──rawfile                                // 大体积媒体资源存放位置
   └──zh_CN
       └──element
          └──string.json                     // 中文字符存放位置
# 1.1.2 资源目录结构
resources
|---base
|   |---element
|   |   |---string.json
|   |---media
|   |   |---icon.png
|   |---profile
|   |   |---test_profile.json
|---en_US  // 默认存在的目录,设备语言环境是美式英文时,优先匹配此目录下资源
|   |---element
|   |   |---string.json
|   |---media
|   |   |---icon.png
|   |---profile
|   |   |---test_profile.json
|---zh_CN  // 默认存在的目录,设备语言环境是简体中文时,优先匹配此目录下资源
|   |---element
|   |   |---string.json
|   |---media
|   |   |---icon.png
|   |---profile
|   |   |---test_profile.json
|---en_GB-vertical-car-mdpi // 自定义限定词目录示例,由开发者创建
|   |---element
|   |   |---string.json
|   |---media
|   |   |---icon.png
|   |---profile
|   |   |---test_profile.json
|---rawfile // 其他类型文件,原始文件形式保存,不会被集成到resources.index文件中。文件名可自定义。

# 1.2 应用 / 组件级配置

在开发应用时,需要配置应用的一些标签,例如应用的包名、图标等标识特征的属性。

图标和标签通常一起配置,可以分为应用图标、应用标签和入口图标、入口标签,分别对应 app.json5 配置文件和 module.json5 配置文件中的 icon 和 label 标签。应用图标和标签是在设置应用中使用,例如设置应用中的应用列表。入口图标是应用安装完成后在设备桌面上显示出来的,如下图所示。

AppScope 目录下的 app.json5

{
  "app": {
    "bundleName": "com.wuhanins.hrlocation",
    "vendor": "example",
    "versionCode": 1000000,
    "versionName": "1.0.0",
    "icon": "$media:ins_logo",
    "label": "$string:app_name"
  }
}

入口图标是以 UIAbility 为粒度,支持同一个应用存在多个入口图标和标签,点击后进入对应的 UIAbility 界面。此类图标显示在手机桌面。

# 1.2.1 应用包名配置

应用需要在工程的 AppScope 目录下的 app.json5 配置文件中配置 bundleName 标签,该标签用于标识应用的唯一性。推荐采用反域名形式命名(如 com.example.demo,建议第一级为域名后缀 com,第二级为厂商 / 个人名,第三级为应用名,也可以多级)。

# 1.2.2 应用图标和标签配置

Stage 模型的应用需要配置应用图标和应用标签。应用图标和标签是在设置应用中使用,例如设置应用中的应用列表,会显示出对应的图标和标签。

应用图标需要在工程的 AppScope 目录下的 app.json5 配置文件中配置 icon 标签。应用图标需配置为图片的资源索引,配置完成后,该图片即为应用的图标。

应用标签需要在工程的 AppScope 模块下的 app.json5 配置文件中配置 label 标签。标识应用对用户显示的名称,需要配置为字符串资源的索引。

AppScope 目录下的 app.json5

{
    "app": {
      "icon": "$media:app_icon",
      "label": "$string:app_name"
      // ...
    }
  }
# 1.2.3 入口图标和标签配置

Stage 模型支持对组件配置入口图标和入口标签。入口图标和入口标签会显示在桌面上。

入口图标需要在 module.json5 配置文件中配置,在 abilities 标签下面有 icon 标签。例如希望在桌面上显示该 UIAbility 的图标,则需要在 skills 标签下面的 entities 中添加 "entity.system.home"、actions 中添加 "action.system.home"。同一个应用有多个 UIAbility 配置上述字段时,桌面上会显示出多个图标,分别对应各自的 UIAbility。

module 目录下的 module.json5

{
  "module": {
    // ...
    "abilities": [
      {
        // $ 开头的为资源值
        "icon": "$media:icon",
        "label": "$string:EntryAbility_label",
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ],
      }
    ]
  }
}

目前开发只有一个入口,应用图标和标签应该与入口图标和标签一致。

# 1.2.4 应用版本声明配置

未完待续... 应用版本声明需要在工程的 AppScope 目录下的 app.json5 配置文件中配置 versionCode 标签和 versionName 标签。versionCode 用于标识应用的版本号,该标签值为 32 位非负整数。此数字仅用于确定某个版本是否比另一个版本更新,数值越大表示版本越高。versionName 标签标识版本号的文字描述。

versionCode 每次更新版本需要手动增加

versionName 需遵循以下原则

[v][大版本号][.][过度版本号][.][自增版本号].[当前日期][_某天多版本号区分]

[_某天多版本号] 为可选项,当天仅有一个版本时可以不需要

例如:v1.0.27.20240521 v1.0.27.20240521_1

# 1.2.5 Module 支持的设备类型配置

Module 支持的设备类型需要在 module.json5 配置文件中配置 deviceTypes 标签,如果 deviceTypes 标签中添加了某种设备,则表明当前的 Module 支持在该设备上运行。

类似于 android 项目中的 abiFilters

module 目录下的 module.json5

{
  "module": {
    // ...
     "deviceTypes": [
      "phone",
      "tablet"
    ],
  }
}

目前只需处理手机和平板

# 1.2.6 Module 权限配置

Module 访问系统或其他应用受保护部分所需的权限信息需要在 module.json5 配置文件中配置 requestPermission 标签。该标签用于声明需要申请权限的名称、申请权限的原因以及权限使用的场景。

module 目录下的 module.json5

{
  "module": {
    // ...
     "requestPermissions": [
      {
        "name": "ohos.abilitydemo.permission.PROVIDER",
        "reason": "$string:reason",
        "usedScene": {
          "abilities": [
            "FormAbility"
          ],
          "when": "inuse"
        }
      }
    ]
  }
}

“reason” 会直接体现在下图红线位置,根据当前应用需求,自行处理即可

# 2 权限

# 2.1 权限使用的基本原则

在进行权限的申请和使用时,需要满足以下基本原则:

  1. 应用申请的权限,都必须有明确、合理的使用场景和功能说明,确保用户能够清晰明了地知道申请权限的目的、场景、用途;禁止诱导、误导用户授权;应用使用权限必须与申请所述一致。
  2. 应用权限申请遵循最小化原则,只申请业务功能所必要的权限,禁止申请不必要的权限。
  3. 应用在首次启动时,避免频繁弹窗申请多个权限;权限须在用户使用对应业务功能时动态申请。
  4. 用户拒绝授予某个权限时,与此权限无关的其他业务功能应能正常使用,不能影响应用的正常注册或登录。
  5. 业务功能所需要的权限被用户拒绝且禁止后不再提示,当用户主动触发使用此业务功能或为实现业务功能所必须时,应用程序可通过界面内文字引导,让用户主动到 “系统设置” 中授权。
  6. 当前不允许应用自行定义权限,应用申请的权限应该从已有的权限列表中选择。

对于第三点,可根据实际情况,保证系统首次授权的完整性,自行决定。

# 2.2 权限等级说明

根据接口所涉数据的敏感程度或所涉能力的安全威胁影响,ATM 模块定义了不同开放范围的权限等级来保护用户隐私。

# 2.2.1 应用 APL 等级说明

元能力权限等级 APL(Ability Privilege Level)指的是应用的权限申请优先级的定义,不同 APL 等级的应用能够申请的权限等级不同。

应用的等级可以分为三个等级,分别是:

APL 级别说明
system_core 等级该等级的应用服务提供操作系统核心能力。
system_basic 等级该等级的应用服务提供系统基础服务。
normal 等级普通应用。
# 2.2.2 权限等级说明

根据权限对于不同等级应用有不同的开放范围,权限类型对应分为以下三种,等级依次提高。

normal 权限

normal 权限允许应用访问超出默认规则外的普通系统资源。这些系统资源的开放(包括数据和功能)对用户隐私以及其他应用带来的风险很小。

该类型的权限仅向 APL 等级为 normal 及以上的应用开放。

system_basic 权限

system_basic 权限允许应用访问操作系统基础服务相关的资源。这部分系统基础服务属于系统提供或者预置的基础功能,比如系统设置、身份认证等。这些系统资源的开放对用户隐私以及其他应用带来的风险较大。

该类型的权限仅向 APL 等级为 system_basic 及以上的应用开放。

system_core 权限

system_core 权限涉及到开放操作系统核心资源的访问操作。这部分系统资源是系统最核心的底层服务,如果遭受破坏,操作系统将无法正常运行。

鉴于该类型权限对系统的影响程度非常大,目前暂不向任何三方应用开放。

# 2.2.3 权限类型说明

根据授权方式的不同,权限类型可分为 system_grant(系统授权)和 user_grant(用户授权)。

system_grant

system_grant 指的是系统授权类型,在该类型的权限许可下,应用被允许访问的数据不会涉及到用户或设备的敏感信息,应用被允许执行的操作不会对系统或者其他应用产生大的不利影响。

如果在应用中申请了 system_grant 权限,那么系统会在用户安装应用时,自动把相应权限授予给应用。应用需要在应用商店的详情页面,向用户展示所申请的 system_grant 权限列表。

user_grant

user_grant 指的是用户授权类型,在该类型的权限许可下,应用被允许访问的数据将会涉及到用户或设备的敏感信息,应用被允许执行的操作可能对系统或者其他应用产生严重的影响。

该类型权限不仅需要在安装包中申请权限,还需要在应用动态运行时,通过发送弹窗的方式请求用户授权。在用户手动允许授权后,应用才会真正获取相应权限,从而成功访问操作目标对象。

应用需要在应用商店的详情页面,向用户展示所申请的 user_grant 权限列表。

# 2.2.4 不同权限类型的授权流程

权限申请

开发者需要在配置文件中声明目标权限。

权限授权

如果目标权限是 system_grant 类型,开发者在进行权限申请后,系统会在安装应用时自动为其进行权限预授予,开发者不需要做其他操作即可使用权限。

如果目标权限是 user_grant 类型,开发者在进行权限申请后,在运行时触发动态弹窗,请求用户授权。

ohos.permission.LOCATION 权限

申请条件:使用 API version 9 以下版本的 SDK 开发的应用,可以直接申请此权限。使用 API version 9 及 API version 9 以上版本的 SDK 开发的应用,需要先申请权限 ohos.permission.APPROXIMATELY_LOCATION,才可申请此权限。

动态请求授权实例

module 目录下的 module.json5

import type AbilityConstant from '@ohos.app.ability.AbilityConstant';
import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility';
import type Want from '@ohos.app.ability.Want';
import type window from '@ohos.window';
import Package from '@system.package';
import bundleManager from '@ohos.bundle.bundleManager';
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
const permissions: Array<Permissions> = ['ohos.permission.READ_CALENDAR'];
/**
 * Lift cycle management of Ability.
 */
export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  }
  onDestroy(): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  }
  onWindowStageCreate(windowStage: window.WindowStage): void {
    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
    let context = this.context;
    let atManager = abilityAccessCtrl.createAtManager();
    //requestPermissionsFromUser 会判断权限的授权状态来决定是否唤起弹窗
    atManager.requestPermissionsFromUser(context, permissions).then((data) => {
      let grantStatus: Array<number> = data.authResults;
      let length: number = grantStatus.length;
      for (let i = 0; i < length; i++) {
        if (grantStatus[i] === 0) {
          // 用户授权,可以继续访问目标操作
          this.loadSplash(windowStage)
        } else {
          // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
          return;
        }
      }
      // 授权成功
      this.loadSplash(windowStage)
    }).catch((err) => {
      console.error(`requestPermissionsFromUser failed, code is ${err.code}, message is ${err.message}`);
    })
  }
  loadSplash(windowStage: window.WindowStage){
    windowStage.loadContent("pages/SplashScreenPage", (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(): void {
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }
  onForeground(): void {
    // Ability has brought to foreground
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
  }
  onBackground(): void {
    // Ability has back to background
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

此处提供官方权限列表及说明

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/permission-list-0000001544464017-V2

未完待续...

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

Logan 微信支付

微信支付

Logan 支付宝

支付宝

Logan 贝宝

贝宝