前面总结了鸿蒙开发的调试环境配置,今天来看看相关配置规范
1 配置规范
1.1 工程结构
1.1.1 代码目录结构
目前新建项目可选内置的功能生成新项目,默认采用Stage模型构建
其目录结构如下

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| ├──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资源目录结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| 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
1 2 3 4 5 6 7 8 9 10
| { "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
1 2 3 4 5 6 7
| { "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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| { "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 需遵循以下原则
1
| [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
1 2 3 4 5 6 7 8 9
| { "module": { "deviceTypes": [ "phone", "tablet" ], } }
|
目前只需处理手机和平板
1.2.6 Module权限配置
Module访问系统或其他应用受保护部分所需的权限信息需要在module.json5配置文件中配置requestPermission标签。该标签用于声明需要申请权限的名称、申请权限的原因以及权限使用的场景。
module目录下的module.json5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| { "module": { "requestPermissions": [ { "name": "ohos.abilitydemo.permission.PROVIDER", "reason": "$string:reason", "usedScene": { "abilities": [ "FormAbility" ], "when": "inuse" } } ] } }
|
“reason”会直接体现在下图红线位置,根据当前应用需求,自行处理即可

2 权限
2.1 权限使用的基本原则
在进行权限的申请和使用时,需要满足以下基本原则:
- 应用申请的权限,都必须有明确、合理的使用场景和功能说明,确保用户能够清晰明了地知道申请权限的目的、场景、用途;禁止诱导、误导用户授权;应用使用权限必须与申请所述一致。
- 应用权限申请遵循最小化原则,只申请业务功能所必要的权限,禁止申请不必要的权限。
应用在首次启动时,避免频繁弹窗申请多个权限;权限须在用户使用对应业务功能时动态申请。
- 用户拒绝授予某个权限时,与此权限无关的其他业务功能应能正常使用,不能影响应用的正常注册或登录。
- 业务功能所需要的权限被用户拒绝且禁止后不再提示,当用户主动触发使用此业务功能或为实现业务功能所必须时,应用程序可通过界面内文字引导,让用户主动到“系统设置”中授权。
- 当前不允许应用自行定义权限,应用申请的权限应该从已有的权限列表中选择。
对于第三点,可根据实际情况,保证系统首次授权的完整性,自行决定。
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| 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'];
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 { hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); let context = this.context; let atManager = abilityAccessCtrl.createAtManager(); 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 { hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); }
onForeground(): void { hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); }
onBackground(): void { hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); } }
|
此处提供官方权限列表及说明
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/permission-list-0000001544464017-V2
未完待续…