HarmonyOS:向用户申请授权

[复制链接]
发表于 2025-7-1 14:00:08 | 显示全部楼层 |阅读模式
一、前言

           当应用需要访问用户的隐私信息或使用系统能力时,例如获取位置信息、访问日历、使用相机拍摄照片或录制视频等,应该向用户请求授权,这部分权限是user_grant权限。
      当应用申请user_grant权限时,需要完成以下步调:
      

  • 配置文件中,声明应用需要请求的权限。
  • 将应用中需要申请权限的目的对象与对应目的权限进行关联,让用户明白地知道,哪些操纵需要用户向应用授予指定的权限。
  • 运行应用时,在用户触发访问操纵目的对象时应该调用接口,精准触发动态授权弹框。该接口的内部会查抄当前用户是否已经授权应用所需的权限,如果当前用户尚未授予应用所需的权限,该接口会拉起动态授权弹框,向用户请求授权。
  • 查抄用户的授权结果,确认用户已授权才可以进行下一步操纵。
          二、束缚与限制

           

  • user_grant权限授权要基于用户可知可控的原则,需要应用在运行时主动调用系统动态申请权限的接口,系统弹框由用户授权,用户联合应用运行场景的上下文,识别出应用申请相应敏感权限的合理性,从而做出精确的选择。
  • 系统不鼓励频繁弹窗打扰用户,如果用户拒绝授权,将无法再次拉起弹窗,需要应用引导用户在系统应用“设置”的界面中手动授予权限。
  • 系统权限弹窗不可被遮挡。 系统权限弹窗不可被其他组件/控件遮挡,弹窗信息需要完整展示,以便用户识别并完成授权动作。- 如果系统权限弹窗与其他组件/控件同时同位置展示,系统权限弹窗将默认覆盖其他组件/控件。
  • 每次实行需要目的权限的操纵时,应用都必须查抄自己是否已经具有该权限。
  • 如需查抄用户是否已向您的应用授予特定权限,可以使用 checkAccessToken() 函数,此方法会返回PERMISSION_GRANTEDPERMISSION_DENIED。详细示例可参考下文。
  • 每次访问受目的权限保护的接口之前,都需要使用 requestPermissionsFromUser() 接口请求相应的权限。
  • 用户大概在动态授予权限后通过系统设置来取消应用的权限,因此不能将之前授予的授权状态恒久化。
  • 应用在onWindowStageCreate()回调中申请授权时,需要等候异步接口loadContent()/setUIContent()实行结束后或在loadContent()/setUIContent()回调中调用requestPermissionsFromUser(),否则在Content加载完成前,requestPermissionsFromUser会调用失败。
  • 应用在UIExtensionAbility申请授权时,需要在onWindowStageCreate函数实行结束后或在onWindowStageCreate函数回调中调用requestPermissionsFromUser(),否则在ability加载完成前,requestPermissionsFromUser会调用失败。
      GrantStatus 体现授权状态的枚举。
               
名称

说明
PERMISSION_DENIED
-1
体现未授权。
PERMISSION_GRANTED
0
体现已授权。
          三、开辟步调

                  以申请使用位置权限为例进行说明。       效果展示:            

      

  • 申请ohos.permission.LOCATION、ohos.permission.APPROXIMATELY_LOCATION权限,配置方式请参见下文。 应用需要在module.json5配置文件的requestPermissions标签中声明权限。示例如下图
  • 校验当前是否已经授权。 在进行权限申请之前,需要先查抄当前应用步伐是否已经被授予权限。可以通过调用checkAccessToken()方法来校验当前是否已经授权。如果已经授权,则可以直接访问目的操纵,否则需要进行下一步操纵,即向用户申请授权。
                                        登录后复制                        
  1. import { abilityAccessCtrl, bundleManager, Permissions } from '@kit.AbilityKit';
  2. import { BusinessError } from '@kit.BasicServicesKit';
  3. async function checkPermissionGrant(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {
  4.   let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
  5.   let grantStatus: abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
  6.   // 获取应用程序的accessTokenID
  7.   let tokenId: number = 0;
  8.   try {
  9.     let bundleInfo: bundleManager.BundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
  10.     let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
  11.     tokenId = appInfo.accessTokenId;
  12.   } catch (error) {
  13.     const err: BusinessError = error as BusinessError;
  14.     console.error(`获取应用程序的accessTokenID Failed to get bundle info for self. Code is ${err.code}, message is ${err.message}`);
  15.   }
  16.   // 校验应用是否被授予权限
  17.   try {
  18.     grantStatus = await atManager.checkAccessToken(tokenId, permission);
  19.   } catch (error) {
  20.     const err: BusinessError = error as BusinessError;
  21.     console.error(`校验应用是否被授予权限 Failed to check access token. Code is ${err.code}, message is ${err.message}`);
  22.   }
  23.   return grantStatus;
  24. }
  25. async function checkPermissions(): Promise<void> {
  26.   let grantStatus1: boolean = await checkPermissionGrant('ohos.permission.LOCATION') === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;// 获取精确定位权限状态
  27.   let grantStatus2: boolean = await checkPermissionGrant('ohos.permission.APPROXIMATELY_LOCATION') === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;// 获取模糊定位权限状态
  28.   // 精确定位权限只能跟模糊定位权限一起申请,或者已经有模糊定位权限才能申请精确定位权限
  29.   if (grantStatus2 && !grantStatus1) {
  30.      // 申请精确定位权限
  31.   } else if (!grantStatus1 && !grantStatus2) {
  32.      // 申请模糊定位权限与精确定位权限或单独申请模糊定位权限
  33.   } else {
  34.      // 已经授权,可以继续访问目标操作
  35.   }
  36. }
复制代码
      

  • 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.
                             

  • 动态向用户申请授权。
      动态向用户申请权限是指在应用步伐运行时向用户请求授权的过程。可以通过调用 requestPermissionsFromUser() 方法来实现。该方法吸收一个权限列表参数,例如位置、日历、相机、麦克风等。用户可以选择授予权限或者拒绝授权。
可以在UIAbility的onWindowStageCreate()回调中调用 requestPermissionsFromUser() 方法来动态申请权限,也可以根据业务需要在UI中向用户申请授权。
应用在onWindowStageCreate()回调中申请授权时,需要等候异步接口loadContent()/setUIContent()实行结束后或在loadContent()/setUIContent()回调中调用requestPermissionsFromUser(),否则在Content加载完成前,requestPermissionsFromUser会调用失败。
应用在UIExtensionAbility申请授权时,需要在onWindowStageCreate函数实行结束后或在onWindowStageCreate函数回调中调用requestPermissionsFromUser(),否则在ability加载完成前,requestPermissionsFromUser会调用失败。
      

  • 在UIAbility中向用户申请授权。
                                        登录后复制                        
  1. // 使用UIExtensionAbility:将import { UIAbility } from '@kit.AbilityKit' 替换为import { UIExtensionAbility } from '@kit.AbilityKit';
  2. import { abilityAccessCtrl, common, Permissions, UIAbility } from '@kit.AbilityKit';
  3. import { window } from '@kit.ArkUI';
  4. import { BusinessError } from '@kit.BasicServicesKit';
  5. const permissions: Array<Permissions> = ['ohos.permission.LOCATION','ohos.permission.APPROXIMATELY_LOCATION'];
  6. // 使用UIExtensionAbility:将common.UIAbilityContext 替换为common.UIExtensionContext
  7. function reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
  8.   let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
  9.   // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
  10.   atManager.requestPermissionsFromUser(context, permissions).then((data) => {
  11.     let grantStatus: Array<number> = data.authResults;
  12.     let length: number = grantStatus.length;
  13.     for (let i = 0; i < length; i++) {
  14.       if (grantStatus[i] === 0) {
  15.         // 用户授权,可以继续访问目标操作
  16.       } else {
  17.         // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
  18.         return;
  19.       }
  20.     }
  21.     // 授权成功
  22.   }).catch((err: BusinessError) => {
  23.     console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
  24.   })
  25. }
  26. // 使用UIExtensionAbility:将 UIAbility 替换为UIExtensionAbility
  27. export default class EntryAbility extends UIAbility {
  28.   onWindowStageCreate(windowStage: window.WindowStage): void {
  29.     // ...
  30.     windowStage.loadContent('pages/Index', (err, data) => {
  31.       reqPermissionsFromUser(permissions, this.context);
  32.     // ...
  33.     });
  34.   }
  35.   // ...
  36. }
复制代码
      

  • 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.
                             

  • 在UI中向用户申请授权。
                                        登录后复制                        
  1. import { abilityAccessCtrl, common, Permissions } from '@kit.AbilityKit';
  2. import { BusinessError } from '@kit.BasicServicesKit';
  3. const permissions: Array<Permissions> = ['ohos.permission.LOCATION','ohos.permission.APPROXIMATELY_LOCATION'];
  4. // 使用UIExtensionAbility:将common.UIAbilityContext 替换为common.UIExtensionContext
  5. function reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
  6.   let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
  7.   // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
  8.   atManager.requestPermissionsFromUser(context, permissions).then((data) => {
  9.     let grantStatus: Array<number> = data.authResults;
  10.     let length: number = grantStatus.length;
  11.     for (let i = 0; i < length; i++) {
  12.       if (grantStatus[i] === 0) {
  13.         // 用户授权,可以继续访问目标操作
  14.       } else {
  15.         // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
  16.         return;
  17.       }
  18.     }
  19.     // 授权成功
  20.   }).catch((err: BusinessError) => {
  21.     console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
  22.   })
  23. }
  24. @Entry
  25. @Component
  26. struct Index {
  27.   aboutToAppear() {
  28.     // 使用UIExtensionAbility:将common.UIAbilityContext 替换为common.UIExtensionContext
  29.     const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
  30.     reqPermissionsFromUser(permissions, context);
  31.   }
  32.   build() {
  33.     // ...
  34.   }
  35. }
复制代码
      

  • 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.
                             

  • 处置惩罚授权结果。 调用requestPermissionsFromUser()方法后,应用步伐将等候用户授权的结果。如果用户授权,则可以继续访问目的操纵。如果用户拒绝授权,则需要提示用户必须授权才能访问当前页面的功能,并引导用户到系统应用“设置”中打开相应的权限。
    路径:设置 > 隐私 > 权限管理 > 应用 > 目的应用

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表