DEV Community

SameX
SameX

Posted on

鸿蒙Next权限申请全攻略:系统授权与用户授权之道

本文旨在深入探讨华为鸿蒙HarmonyOS Next系统(截止目前 API12)在开发多语言电商平台方面的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。

在鸿蒙 Next 系统的应用开发中,权限申请是确保应用合法、安全且功能完备的关键环节。正确理解并运用系统授权与用户授权机制,不仅能保障用户数据隐私,还能提升应用的稳定性与用户体验。今天,我们就来深入探讨如何根据权限类型和应用需求,选择恰当的申请方式。

一、鸿蒙 Next 权限申请概览

鸿蒙 Next 系统为了保护用户数据和系统资源,对应用的权限进行了细致的分类管理。其中,系统授权和用户授权是两种主要的授权方式,它们各自适用于不同类型的权限,开发者需要根据应用的具体功能需求来选择合适的授权方式。这就好比在建造一座大厦时,需要根据不同区域的功能需求选择合适的建筑材料和施工工艺,以确保大厦的稳固与安全。

(一)系统授权:自动授予的便捷性

系统授权,正如其名,是由系统在应用安装过程中自动完成的权限授予操作。这种授权方式适用于那些对系统或其他应用影响较小、不涉及用户敏感信息的权限。例如,应用获取网络信息、查询自身基本信息等操作所需的权限,通常都采用系统授权方式。

(二)用户授权:以用户为中心的权限授予

与系统授权不同,用户授权则更加注重用户的知情权和选择权。当应用需要访问用户的敏感信息或执行可能影响用户隐私的操作时,如使用摄像头、麦克风、读取通讯录等,就必须通过用户授权方式获得用户的明确许可。这确保了用户始终对自己的数据拥有控制权,就像在自己的私人领地设置了一道道关卡,只有经过用户亲自授权的应用才能进入并使用相关资源。

二、系统授权流程解析

(一)权限判断与申请准备

在进行系统授权之前,开发者首先要明确应用所需的权限,并判断这些权限是否属于系统授权类型。这需要开发者对鸿蒙 Next 的权限体系有深入的了解,熟悉各种权限的分类和适用场景。可以将其类比为航海前的航线规划,只有明确目的地和路线,才能确保航行的顺利进行。

(二)系统自动授予权限的过程

一旦确定应用所需的权限为系统授权类型,开发者只需在应用的配置文件中正确声明这些权限。当用户安装应用时,系统会自动识别并授予相应的权限,整个过程无需用户进行额外的操作。这就像在一家自动化餐厅,顾客只需选择自己想要的菜品(声明权限),餐厅的自动化系统(鸿蒙 Next 系统)就会自动将菜品送到顾客面前(授予权限)。

(三)系统授权权限列表展示

以下是一些常见的系统授权权限及其说明:

权限名称 权限描述
ohos.permission.USE_BLUETOOTH 允许应用查看蓝牙的配置。
ohos.permission.GET_BUNDLE_INFO 允许查询应用的基本信息。
ohos.permission.PREPARE_APP_TERMINATE 允许应用关闭前执行自定义的预关闭动作。
ohos.permission.PRINT 允许应用获取打印框架的能力。
ohos.permission.DISCOVER_BLUETOOTH 允许应用配置本地蓝牙,查找远端设备且与之配对连接。

三、用户授权流程详解

(一)在配置文件中声明权限

  1. 配置文件的选择与定位 用户授权的第一步是在应用的配置文件中声明所需的权限。在鸿蒙 Next 项目中,通常使用“module.json5”配置文件来进行权限声明。这个配置文件就像是应用的“说明书”,告诉系统应用需要哪些权限才能正常运行。
  2. 权限声明的格式与规范 在“module.json5”文件中,通过“requestPermissions”字段来声明权限。每个权限声明都包含“name”(权限名称)、“reason”(申请权限的原因)和“usedScene”(权限使用的场景)等属性。例如:
{
"module": {
"requestPermissions":[
{
"name": "ohos.permission.CAMERA",
"reason": "$string:reason_camera",
"usedScene": {
"abilities": [
"MainAbility"
],
"when":"inuse"
}
}
]
}
}
Enter fullscreen mode Exit fullscreen mode

其中,“name”必须是系统定义的有效权限名称,“reason”需要用简洁明了的语言向用户说明申请该权限的原因,并且要遵循一定的文案规范,如使用直白、具体、易理解的完整短句,避免使用被动语态,以句号结尾,同时要确保字符串长度适中,以适应多语言适配的需求。“usedScene”则用于指定权限使用的场景,包括使用权限的 UIAbility 或 ExtensionAbility 组件名称以及调用时机(“inuse”表示使用时,“always”表示始终)。

(二)使用 API 动态请求用户授权

  1. 权限检查与准备 在动态请求用户授权之前,应用应该先检查当前是否已经获得了所需的权限。这可以通过调用“checkAccessToken()”函数来实现,该函数会返回“PERMISSION_GRANTED”或“PERMISSION_DENIED”,以指示当前权限的授予状态。这就好比在进入一个需要门票的场所之前,先检查自己是否已经购买了门票。
  2. 动态请求授权的 API 调用 如果应用尚未获得所需权限,就需要使用“requestPermissionsFromUser()”接口向用户发起授权请求。这个接口接收一个权限列表作为参数,例如,如果应用需要同时申请相机和麦克风权限,可以这样调用:
import { abilityAccessCtrl, common, Permissions } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

const permissions: Array<Permissions> = ['ohos.permission.CAMERA', 'ohos.permission.MICROPHONE'];

function reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
let atManager: abilityAccessCtrl.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) {
// 用户授权,可以继续访问目标操作
} else {
// 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
return;
}
}
// 授权成功
}).catch((err: BusinessError) => {
console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
});
}
Enter fullscreen mode Exit fullscreen mode

在上述代码中,首先创建了一个“AtManager”实例,然后调用“requestPermissionsFromUser()”方法向用户请求权限。根据用户的授权结果,应用可以采取相应的操作,如继续执行需要权限的功能或提示用户前往系统设置中手动授予权限。

(三)处理用户授权结果

  1. 授权成功后的操作 当用户授权成功后,应用可以继续执行需要该权限的操作。例如,如果应用申请了相机权限并获得授权,就可以打开相机进行拍照或录像操作。这就像获得了进入宝库的钥匙,可以顺利取出宝藏(执行相应功能)。
  2. 授权失败后的应对策略 如果用户拒绝授权,应用需要友好地提示用户授权的必要性,并引导用户前往系统设置中手动授予权限。同时,应用应该确保在用户未授权的情况下,不会影响其他无关功能的正常使用。这就好比在一扇紧闭的门前,向用户解释门后的精彩内容,并引导用户找到打开门的正确方法,而不是强行推门或影响周围环境的正常秩序。

(四)用户授权权限列表展示

以下是一些常见的用户授权权限及其说明:

权限名称 权限描述
ohos.permission.ACCESS_BLUETOOTH 允许应用接入蓝牙并使用蓝牙能力,例如配对、连接外围设备等。
ohos.permission.CAMERA 允许应用使用相机。
ohos.permission.MICROPHONE 允许应用使用麦克风。
ohos.permission.READ_CALENDAR 允许应用读取日历信息。
ohos.permission.WRITE_CALENDAR 允许应用添加、移除或更改日历活动。

四、不同权限类型申请方式总结

为了更清晰地展示不同权限类型的申请方式,我们通过以下表格进行总结:

权限类型 授权方式 操作路径
系统授权(system_grant) 自动授予 在配置文件中声明权限
用户授权(user_grant) 用户手动授权 在配置文件中声明权限 > 使用 API 动态请求用户授权 > 处理用户授权结果

五、示例代码:请求麦克风权限

以下是一个完整的示例代码,演示了如何在鸿蒙 Next 应用中请求麦克风权限:

import { abilityAccessCtrl, bundleManager, Permissions } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

// 定义需要申请的权限列表,这里仅包含麦克风权限
const permissions: Array<Permissions> = ['ohos.permission.MICROPHONE'];

// 检查当前应用是否已被授予指定权限
async function checkPermissionGrant(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
let grantStatus: abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
// 获取应用程序的 accessTokenID
let tokenId: number = 0;
try {
let bundleInfo: bundleManager.BundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
tokenId = appInfo.accessTokenId;
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`Failed to get bundle info for self. Code is ${err.code}, message is ${err.message}`);
}
// 校验应用是否被授予权限
try {
grantStatus = await atManager.checkAccessToken(tokenId, permission);
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`Failed to check access token. Code is ${err.code}, message is ${err.message}`);
}
return grantStatus;
}

// 检查权限并根据结果进行相应操作
async function checkPermissions(): Promise<void> {
let grantStatus: abilityAccessCtrl.GrantStatus = await checkPermissionGrant(permissions[0]);
if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
// 已经授权,可以继续访问目标操作,这里可以添加使用麦克风的相关代码
console.log('已获得麦克风权限,可以进行录音等操作。');
} else {
// 申请麦克风权限
reqPermissionsFromUser(permissions);
}
}

// 使用 API 动态请求用户授权
function reqPermissionsFromUser(permissions: Array<Permissions>): void {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
atManager.requestPermissionsFromUser(globalThis.context as common.UIAbilityContext, 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) {
// 用户授权,可以继续访问目标操作,这里可以添加使用麦克风的相关代码
console.log('用户已授权麦克风权限,可以进行录音等操作。');
} else {
// 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
console.log('用户拒绝授权麦克风权限,请前往系统设置中手动授予权限。');
return;
}
}
// 授权成功
}).catch((err: BusinessError) => {
console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
});
}

// 在应用启动或需要使用麦克风的地方调用 checkPermissions() 函数来检查和申请权限
checkPermissions();
Enter fullscreen mode Exit fullscreen mode

在上述代码中,首先定义了需要申请的麦克风权限。然后,通过“checkPermissionGrant()”函数检查应用当前是否已获得该权限。如果未获得权限,则调用“reqPermissionsFromUser()”函数向用户发起授权请求。根据用户的授权结果,应用会在控制台输出相应的提示信息,并在授权成功后可以继续执行使用麦克风的相关操作。

总之,在鸿蒙 Next 应用开发中,正确处理权限申请是至关重要的。开发者需要深入理解系统授权和用户授权的机制与流程,根据应用的实际需求合理选择授权方式,并严格按照规范进行权限声明和请求操作。只有这样,才能确保应用在保障用户数据安全的前提下,提供稳定、优质的服务。希望通过本文的介绍,能帮助我们开发者更加顺利地完成鸿蒙 Next 应用的权限申请工作,让我们一起打造更加安全、可靠的智能应用生态。

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs