手动设置授权
当应用需要访问用户的隐私信息或使用敏感系统能力时,如拦截键盘输入事件,应向用户申请授权。这些权限属于manual_settings权限。
当应用申请manual_settings权限时,需完成以下步骤:
- 在应用市场(AGC)侧申请Profile文件并在Profile内添加ACL权限。申请Profile的操作需在应用市场(AGC)完成,详细步骤请参阅申请发布Profile。
- 在module.json5配置文件中声明权限。
- 运行应用时,用户触发访问目标对象时应检查用户的授权结果,若未授权,引导用户跳转到系统应用“设置”中进行授权。
- 检查用户的授权结果,确认用户已授权后,再进行下一步操作。
本章节将详细介绍如何完成步骤3和4。
开发步骤
以申请拦截键盘输入事件权限为例进行说明,目前该权限仅在PC/2in1设备上生效。
-
申请ohos.permission.HOOK_KEY_EVENT权限,配置方式请参见申请发布Profile与声明权限。
-
校验当前是否已经授权。
在进行权限申请之前,需要先检查当前应用程序是否已经被授予权限。可以通过调用checkAccessToken()方法来校验当前是否已经授权。如果已经授权,则可以直接访问目标操作,否则需要进行下一步操作,即引导用户跳转到系统应用“设置”中进行授权。
import { abilityAccessCtrl, bundleManager, Permissions } from '@kit.AbilityKit';import { BusinessError } from '@kit.BasicServicesKit';async function checkPermissionGrant(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();let grantStatus: abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;// 获取应用程序的accessTokenIDlet 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: ${err.code}, message: ${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: ${err.code}, message: ${err.message}`);}return grantStatus;}async function checkPermissions(): Promise<void> {let grantStatus: boolean = await checkPermissionGrant('ohos.permission.HOOK_KEY_EVENT') === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;// 获取拦截键盘输入事件权限状态。if (grantStatus) {// 已经授权,可以继续访问目标操作console.info(`permission is granted.`);} else {// 未授权,引导用户跳转到系统应用“设置”中进行授权console.info(`permission is not granted.`);}} -
引导用户跳转到系统应用“设置”中进行授权。
若用户未授权,则需要提示用户必须授权才能访问当前页面的功能,并引导用户到系统应用“设置”中打开相应的权限;或通过调用openPermissionOnSetting()方法拉起弹窗,引导用户授权。
在“设置”中的路径如下:
路径一:设置 > 隐私和安全 > 权限类型(如键盘输入辅助) > 某个应用

路径二:设置 > 应用和元服务 > 某个应用 > 权限类型(如键盘输入辅助)

应用在UIAbility的onWindowStageCreate()回调中调用openPermissionOnSetting()方法引导用户跳转到“设置”,或根据业务需要在UI中引导用户跳转到“设置”。
应用在onWindowStageCreate()回调中申请授权时,需要等待异步接口loadContent()/setUIContent()执行结束后或在loadContent()/setUIContent()回调中调用openPermissionOnSetting(),否则在Content加载完成前,openPermissionOnSetting会调用失败。
效果展示:

-
在UIAbility中引导用户跳转到系统应用“设置”中的对应路径。
import { abilityAccessCtrl, common, Permissions, UIAbility } from '@kit.AbilityKit';import { window } from '@kit.ArkUI';import { BusinessError } from '@kit.BasicServicesKit';function openPermOnSetting(permission: Permissions, context: common.UIAbilityContext): void {let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();// openPermissionOnSetting会判断权限的授权状态来决定是否唤起弹窗atManager.openPermissionOnSetting(context, permission).then((data) => {if (data === abilityAccessCtrl.SelectedResult.REJECTED) {// 用户不允许跳转到“设置”console.info(`user not allowed.`);} else if (data === abilityAccessCtrl.SelectedResult.OPENED) {// 用户选择跳转到“设置”console.info(`user allowed to setting.`);} else {// 权限已授权,无需弹窗console.info(`permission is granted.`);}}).catch((err: BusinessError) => {console.error(`Failed to openPermissionOnSetting, code: ${err.code}, message: ${err.message}`);})}export default class OpenPermAbility extends UIAbility {onWindowStageCreate(windowStage: window.WindowStage): void {// ···windowStage.loadContent('openpermpages/Index', (err) => {openPermOnSetting('ohos.permission.HOOK_KEY_EVENT', this.context);// ···});}// ···} -
在UI中引导用户跳转到系统应用“设置”中的对应路径。
import { abilityAccessCtrl, common, Permissions } from '@kit.AbilityKit';import { BusinessError } from '@kit.BasicServicesKit';function openPermOnSetting(permission: Permissions, context: common.UIAbilityContext): void {let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();// openPermissionOnSetting会判断权限的授权状态来决定是否唤起弹窗atManager.openPermissionOnSetting(context, permission).then((data) => {if (data === abilityAccessCtrl.SelectedResult.REJECTED) {// 用户不允许跳转到“设置”console.info(`user not allowed.`);} else if (data === abilityAccessCtrl.SelectedResult.OPENED) {// 用户选择跳转到“设置”console.info(`user allowed to setting.`);} else {// 权限已授权,无需弹窗console.info(`permission is granted.`);}}).catch((err: BusinessError) => {console.error(`Failed to openPermissionOnSetting, code: ${err.code}, message: ${err.message}`);})}@Entry@Componentstruct Index {aboutToAppear() {const context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;openPermOnSetting('ohos.permission.HOOK_KEY_EVENT', context);}build() {// ···}}
-
-
处理授权结果。
调用openPermissionOnSetting()方法后,应用程序需重新校验是否已经授权。
如果用户授权,则可以继续访问目标操作。
如果用户拒绝授权,则需要提示用户必须授权才能访问当前页面的功能,重新引导用户跳转到系统应用“设置”中的对应路径打开权限。