纯血鸿蒙——如何申请权限

权限管理

1. 引言

先了解应用权限的基本概念,知道:权限级别授权方式

在鸿蒙开发中,调用部分 API 时需要申请权限后,才能调用,如:网络请求,获取网络信息等。

部分 API 调用的时候还会弹窗,如:麦克风(录音)、日历、相册。

2. 应用APL等级分三种

(Ability Privilege Level,元能力权限等级)应用的 APL 等级可以分为以下三个等级,等级依次提高。

APL级别 说明 大白话
normal 默认情况下,应用的APL等级都为normal等级。 都能用
system_basic 该等级的应用服务提供系统基础服务。 要签名证书
system_core 该等级的应用服务提供操作系统核心能力。 仅对系统应用开放 不开放

3. 应用授权方式分两种

根据授权方式的不同,权限类型可分为 system_grantuser_grant

大白话:授权方式为 user_grant 会弹窗,而 system_grant 自动授权。

system_grant(系统授权)

system_grant指的是系统授权类型,在该类型的权限许可下,应用被允许访问的数据不会涉及到用户或设备的敏感信息,应用被允许执行的操作对系统或者其他应用产生的影响可控。

如果在应用中申请了system_grant 权限,那么系统会在用户安装应用时,自动把相应权限授予给应用。

user_grant(用户授权)

user_grant指的是用户授权类型,在该类型的权限许可下,应用被允许访问的数据将会涉及到用户或设备的敏感信息,应用被允许执行的操作可能对系统或者其他应用产生严重的影响。

该类型权限不仅需要在安装包中申请权限,还需要在应用动态运行时,通过发送弹窗的方式请求用户授权。在用户手动允许授权后,应用才会真正获取相应权限,从而成功访问操作目标对象。

4. 应用权限列表

在应用权限列表中,分为:

  • 对所有应用开放的权限 - 都能用
  • 允许ACL跨级别申请权限 - 要签名证书

权限分类

日历、相机、麦克风、位置:权限级别 normal 所有应用都能用,但授权方式为 user_grant 需弹窗授权。

照片、通讯录:属于跨级权限,需要通过应用市场(AGC)申请签名证书,开发阶段用自动签名即可。

通知:其他权限。

5. 动态申请权限的具体步骤:

5.1. 配置声明权限

  • 在 module.json5 中添加权限说明
ts 复制代码
    {
      "module": {
        "requestPermissions": [
          {
            // 允许应用获取数据网络信息
            "name": "ohos.permission.GET_NETWORK_INFO"
          },
          // 日历(读写-权限组)
          {
            "name": "ohos.permission.READ_CALENDAR",
            "reason": '$string:permission_reason_calendar',
            "usedScene": {}
          },
          {
            "name": "ohos.permission.WRITE_CALENDAR",
            "reason": '$string:permission_reason_calendar',
            "usedScene": {}
          },
        ],
    }

注意:权限为 user_grant 时,还需添加授权原因。

5.2. 添加 reason 权限使用理由。

  • 当申请的权限为 user_grant 权限时必填,并且需要进行多语种适配。

参考句式:用于某事,如:(麦克风)用于录制加密视频和音频。

5.3. 检查当前是否已经授权

在进行权限申请之前,通常先检查当前应用程序是否已经被授予权限。

可以通过调用checkAccessToken()方法来校验当前是否已经授权。如果已经授权,则可以直接访问目标操作,否则需要进行下一步操作,即向用户申请授权。

核心API: atManager.checkAccessTokenSync(tokenID, 权限名称) 注意: tokenID 为应用唯一标识,通过 bundleManager 获取

ts 复制代码
    // 检查授权结果
    checkPermissions(permissions: Permissions[]) {
      // 1. 创建应用权限管理器
      const atManager = abilityAccessCtrl.createAtManager();
      // 2. 获取 bundle 包信息
      const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)
      // 3. 提取 tokenID 应用唯一标识
      const tokenID = bundleInfo.appInfo.accessTokenId;
      // 4. 校验应用是否被授予某个权限
      const authResults = permissions.map((permission) => atManager.checkAccessTokenSync(tokenID, permission))
      // 处理授权结果
      return authResults.every(v => v === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
    }

5.4. 动态向用户申请授权

动态向用户申请权限是指在应用程序运行时向用户请求授权的过程。

可以通过调用requestPermissionsFromUser()方法来实现。该方法接收一个权限列表参数,例如位置、日历、相机、麦克风等。用户可以选择授予权限或者拒绝授权。

核心API: atManager.requestPermissionsFromUser() 注意: 应用首次申请时才会弹窗。

ts 复制代码
    // 拉起弹框请求用户授权
    async requestPermissions(permissions: Permissions[]) {
      // 1. 创建应用权限管理器
      const atManager = abilityAccessCtrl.createAtManager();
      // 2. 拉起弹框请求用户授权
      const grantStatus = await atManager.requestPermissionsFromUser(getContext(), permissions)
      // 处理请求权限结果
      return grantStatus.authResults.every(v => v === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
    }

5.5. 处理授权结果

调用requestPermissionsFromUser()方法后,应用程序将等待用户授权的结果。

如果用户授权,则可以继续访问目标操作。如果用户拒绝授权,则需要提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限。

注意:如果用户在弹窗中拒绝授权,再次调用 将没有任何反应。 需要引导用户在系统设置页中开启应用权限。

ts 复制代码
    // 打开系统设置的权限管理页
    openPermissionSettingsPage() {
      // 获取上下文
      const context = getContext() as common.UIAbilityContext
      // 获取包信息
      const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)
      // 打开系统设置页
      context.startAbility({
        bundleName: 'com.huawei.hmos.settings', // 固定写法CV:设置页的包名
        abilityName: 'com.huawei.hmos.settings.MainAbility', // 固定写法CV:设置页的 ability 名
        uri: 'application_info_entry', // 固定写法CV:打开 设置->应用和元服务
        parameters: {
          // 按照包名打开对应设置页
          pushParams: bundleInfo.name
        }
      })
    }

6. 封装参考

ts 复制代码
import { abilityAccessCtrl, bundleManager, common, Permissions } from '@kit.AbilityKit';

    class PermissionManager {

      // 检查是否授权
      checkPermissions(permissions: Permissions[]) {
        // 程序访问控制管理
        const atManager = abilityAccessCtrl.createAtManager();
        // 获取 bundle 信息
        const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)
        // 提取 tokenID 标识
        const tokenID = bundleInfo.appInfo.accessTokenId
        // 校验应用是否被授予权限
        const authResults = permissions.map((item) => atManager.checkAccessTokenSync(tokenID, item))
        // 返回是否已授权结果
        return authResults.every(v => v === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
      }

      // 动态申请授权(首次弹窗申请)
      async requestPermissions(permissions: Permissions[]) {
        // 程序访问控制管理
        const atManager = abilityAccessCtrl.createAtManager();
        // 拉起弹框请求用户授权
        const grantStatus = await atManager.requestPermissionsFromUser(getContext(), permissions)
        // 获取请求权限的结果
        const isAuth = grantStatus.authResults.every(v => v === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
        // 返回 Promise 授权结果
        return isAuth ? Promise.resolve(true) : Promise.reject(false)
      }

      // 打开系统设置的权限管理页(处理授权结果)
      openPermissionSettingsPage() {
        // 获取上下文
        const context = getContext() as common.UIAbilityContext
        // 获取包信息
        const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)
        // 打开系统设置页
        context.startAbility({
          bundleName: 'com.huawei.hmos.settings',
          abilityName: 'com.huawei.hmos.settings.MainAbility',
          uri: 'application_info_entry',
          parameters: {
            // 按照包名打开对应设置页
            pushParams: bundleInfo.name
          }
        })
      }
    }

    // 导出类的实例
    export const permissionManager = new PermissionManager()

跨级别申请的权限(受限开放权限)

跨级别权限常见问题

在 module.json5 文件中,如果添加的权限为 ACL使能:true,在编译时会报错,如:通讯录、照片。

● ohos.permission.READ_CONTACTS

● ohos.permission.WRITE_CONTACTS

● ohos.permission.READ_IMAGEVIDEO

● ohos.permission.WRITE_IMAGEVIDEO

ACL权限

● 访问控制列表ACL(Access Control List)提供了解决低等级应用访问高等级权限问题的特殊渠道。

● 从 DevEco Studio 4.0 Release 版本起,支持在调测阶段自动签名快速申请ACL权限。

API版本(compileSdkVersion) 支持的ACL权限
API Version > 10 ●ohos.permission.READ_CONTACTS ●ohos.permission.WRITE_CONTACTS ●ohos.permission.READ_AUDIO ●ohos.permission.WRITE_AUDIO ●ohos.permission.READ_IMAGEVIDEO ●ohos.permission.WRITE_IMAGEVIDEO ●ohos.permission.SYSTEM_FLOAT_WINDOW ●ohos.permission.READ_PASTEBOARD ●ohos.permission.ACCESS_DDK_USB ●ohos.permission.ACCESS_DDK_HID

自动签名

项目要上线时,调用 ACL 权限需要手动签名,生成密钥和证书请求文件。 由于流程和步骤较多,在后续项目上线时再详细讲解到。 当下先使用自动签名方式调用 ACL 权限。

相关推荐
沙振宇33 分钟前
【HarmonyOS】ArkTS开发应用的横竖屏切换
android·华为·harmonyos
bestadc2 小时前
鸿蒙 从打开一个新窗口到Stage模型的UIAbility组件
harmonyos
雪芽蓝域zzs7 小时前
鸿蒙Next开发 获取APP缓存大小和清除缓存
缓存·华为·harmonyos
鸿蒙布道师11 小时前
鸿蒙NEXT开发动画案例5
android·ios·华为·harmonyos·鸿蒙系统·arkui·huawei
康康这名还挺多21 小时前
鸿蒙HarmonyOS list优化一: list 结合 lazyforeach用法
数据结构·list·harmonyos·lazyforeach
晚秋大魔王1 天前
OpenHarmony 开源鸿蒙南向开发——linux下使用make交叉编译第三方库——nettle库
linux·开源·harmonyos
python算法(魔法师版)1 天前
.NET 在鸿蒙系统上的适配现状
华为od·华为·华为云·.net·wpf·harmonyos
bestadc1 天前
鸿蒙 UIAbility组件与UI的数据同步和窗口关闭
harmonyos
枫叶丹41 天前
【HarmonyOS Next之旅】DevEco Studio使用指南(二十二)
华为·harmonyos·deveco studio·harmonyos next
乱世刀疤1 天前
深度 |国产操作系统“破茧而出”:鸿蒙电脑填补自主生态空白
华为·harmonyos