当前位置: 首页 > article >正文

探秘鸿蒙 HarmonyOS NEXT:权限申请策略指南

鸿蒙 ArkTS 语言中 abilityAccessCtrl.createAtManager() 申请权限解析

1. 概述

本文章基于HarmonyOS NEXT操作系统,API12以上的版本。

在鸿蒙 HarmonyOS NEXT 系统中,abilityAccessCtrl.createAtManager() 提供了一种更细粒度的权限管理方式,用于程序访问控制提供程序的权限管理能力,包括鉴权、授权等,(App Trust List,简称 ATManager),即访问控制管理:获取访问控制模块对象。

1.1 ATManager 权限管理机制

在HarmonyOS开发中,应用访问如相机、麦克风、位置、图库等系统资源或系统能力时,需通过授权使用等方式来访问,以确保用户隐私安全。

1.2 ATManager 主要用途

ATManager 主要用于:

  • 动态管理应用权限,如特定应用间的访问控制。
  • 基于可信列表进行权限验证,确保只有受信任的应用能够访问特定资源。
  • 适用于系统级或高级安全需求,例如控制某些 API 调用是否允许特定应用执行。

2. 使用方式

2.1 权限申请时机

为了应用能够发挥其完整功能,可能需要访问系统的特定资源,而这些资源的访问通常需要获得相应的权限许可。在应用进行权限申请时,选择合适的权限申请时机是提升用户体验和保护用户隐私安全的关键。主要可分为两点:

按需请求权限

  • 核心原则:应用应遵循“最小权限原则”,即仅申请应用实际需要使用到的权限。
  • 实施策略:将权限请求与应用内的具体功能场景紧密结合。应避免在应用首次启动时,立即请求了大量权限,应在用户实际用到某项功能,而该功能又依赖于特定权限时,再向用户请求相应的权限。以示例代码为例,当用户点击“获取当前位置”按钮时,触发查看位置相关信息的场景,此时弹出请求位置权限的弹框。

尊重用户选择,避免强制请求

  • 核心原则:应尊重用户的选择权,不应强制用户授予权限。
  • 实施策略:若用户拒绝了某项权限申请,应用应避免二次弹框申请该权限,应该在页面内的合适位置添加清晰的提示语,引导用户开启权限或退出当前需要该权限的场景,直至用户再次触发时再引导用户进行授权。

2.2 系统弹框一般有三种操作

  • 仅使用期间允许:点击后应用直接获取该权限,且再次调用requestPermissionsFromUser()方法无法拉起该权限设置弹框;
  • 本次使用允许:点击后将会对应用授予临时的权限,向用户申请单次授权;若临时权限被取消,再次调用requestPermissionsFromUser()方法将会拉起该权限设置弹框;
  • 不允许:点击后应用无法获取该权限,且再次调用 requestPermissionsFromUser() 方法无法拉起该权限设置弹框。那就需要调用requestPermissionOnSetting()方法直接拉起权限设置弹框,引导用户授予权限。

2.3 具体流程

在这里插入图片描述

3. API 介绍

abilityAccessCtrl.createAtManager() 返回一个 ATManager 实例,用于管理应用权限。

API 方法说明
createAtManager()创建 ATManager 实例
checkAccessTokenSync(tokenID: number, permissionName: Permissions): GrantStatus校验应用是否被授予权限,同步返回结果
requestPermissionsFromUser(context: Context, permissionList: Array<Permissions>):Promise<PermissionRequestResult>用于UIAbility/UIExtensionAbility拉起弹框请求用户授权。使用promise异步回调
requestPermissionOnSetting(context: Context, permissionList: Array<Permissions>): Promise<Array<GrantStatus>>用于UIAbility/UIExtensionAbility二次拉起权限设置弹框

4. 权限申请示例

4.1 创建 ATManager 并校验是否已经授权

import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
  /**
   * 校验是否已经授权
   */
  private static checkAccessToken(permission: Permissions): abilityAccessCtrl.GrantStatus {
    let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager()
    let grantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED
    let tokenId: number = 0
    try {
      let bundleInfo: bundleManager.BundleInfo = bundleManager.getBundleInfoForSelfSync(
        bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION
      )
      let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo
      tokenId = appInfo.accessTokenId
    } catch (error) {
      console.error(TAG, "failed to get tokenId ,message = " + JSON.stringify(error))
    }
    //校验应用是否被授权
    try {
      grantStatus = atManager.checkAccessTokenSync(tokenId, permission)
    } catch (error) {
      console.error(TAG, "error = " + JSON.stringify(error))
    }
    return grantStatus
  }

4.2 创建 ATManager 请求授权权限

  /**
   * 向用户请求授权
   */
  async requestPermission(
    context: common.UIAbilityContext,
    permissions: Array<Permissions>
  ): Promise<PermissionResult> {
    let deniedArr: Array<Permissions> = permissions
    let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager()
    let permissionResult: PermissionRequestResult =
      await atManager.requestPermissionsFromUser(context, deniedArr)
    permissionResult.authResults.forEach((authResult, index) => {
      if (authResult === 0) {
        //授权成功,从未授权数组中删除
        deniedArr.splice(index, 1)
      }
    })
    if (deniedArr.length === 0) {
      //全部授权成功
      return {
        granted: true,
        deniedArr: deniedArr
      }
    } else {
      //部分授权失败
      return {
        granted: false,
        deniedArr: deniedArr
      }
    }
  }

4.3 用户拒绝授权后,直接拉起权限设置弹框,引导用户授予权限

  /**
   * 用户拒绝授权后,直接拉起权限设置弹框,引导用户授予权限
   */
  async requestPermissionOnSetting(
    context: common.UIAbilityContext,
    permissions: Array<Permissions>
  ): Promise<PermissionResult> {
    let deniedArr: Array<Permissions> = permissions
    let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager()
    let grantStatus: abilityAccessCtrl.GrantStatus[] =
      await atManager.requestPermissionOnSetting(context, permissions)
    grantStatus.forEach((status, index) => {
      if (status === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
        //授权成功,从未授权数组中删除
        deniedArr.splice(index, 1)
      }
    })
    return {
      granted: deniedArr.length === 0,
      deniedArr: deniedArr
    }
  }

4.4 在系统设置中打开App信息页

  /**
   * 在系统设置中打开App信息页
   */
  static openSystemSettings(context: common.UIAbilityContext) {
    let wantInfo: Want = {
      bundleName: 'com.huawei.hmos.settings',
      abilityName: 'com.huawei.hmos.settings.MainAbility',
      uri: 'application_info_entry',
      parameters: {
        pushParams: context.applicationInfo.name // 打开指定应用的详情页面  bundleId
      }
    }
    context.startAbility(wantInfo).then(() => {
    }).catch((err: BusinessError) => {
      console.error(TAG, "startAbility failed, error = " + err.message)
    })
  }

5. 总结

本文详细阐述了 HarmonyOS NEXT 操作系统中申请权限的机制,为开发者梳理出一套清晰的基本流程,并附上相关代码示例,助力开发者深入理解并高效实现申请权限功能。希望本文能成为开发者在鸿蒙开发过程中的得力助手,顺利攻克权限申请这一关键环节。


http://www.kler.cn/a/572782.html

相关文章:

  • Linux网络 NAT、代理服务、内网穿透
  • c语言中的主要知识点
  • Qt:事件
  • 大模型在呼吸衰竭预测及围手术期方案制定中的应用研究
  • C语言-一维数组及综合案例
  • 鸿蒙NEXT开发-端云一体化开发概念开发准备
  • mysql下载与安装
  • SpringMVC控制器定义:@Controller注解详解
  • 第3章:启动界面与主界面设计
  • 微信小程序中的全局事件总线,原生JS编写
  • Maven入门教程
  • Windows权限维持之利用安全描述符隐藏服务后门进行权限维持(八)
  • 初识Qt · 信号与槽 · 自定义和参数
  • 自然语言处理:文本分类
  • CS144 Lab Checkpoint 5: down the stack (the network interface)
  • Element UI-Select选择器结合树形控件终极版
  • Ruby爬虫如何控制并发数量:爬取京东电子产品
  • 如何在matlab中创建自己的库
  • CSS【实战】模拟 html 的 title 属性(鼠标悬浮显示提示文字)
  • OBOO鸥柏丨LCD液晶室外AI触控屏广告一体机,服务区交互新趋势