鸿蒙笔记-鸿蒙中的权限申请

TokenID

系统采用TokenID(Token identity)作为应用的唯一标识。权限管理服务通过应用的TokenID来管理应用的AT(Access Token)信息,包括应用身份标识APP ID、子用户ID、应用分身索引信息、应用APL、应用权限授权状态等。在资源使用时,系统将通过TokenID作为唯一身份标识映射获取对应应用的权限授权状态信息,并依此进行鉴权,从而管控应用的资源访问行为。

值得注意的是,系统支持多用户特性和应用分身特性,同一个应用在不同的子用户下和不同的应用分身下会有各自的AT,这些AT的TokenID也是不同的。

授权方式

根据授权方式的不同,权限类型可分为system_grant(系统授权)和user_grant(用户授权)。

  1. 如果在应用中申请了system_grant权限,那么系统会在用户安装应用时,自动把相应权限授予给应用。
  2. user_grant权限不仅需要在安装包中申请权限,还需要在应用动态运行时,通过发送弹窗的方式请求用户授权。在用户手动允许授权后,应用才会真正获取相应权限,从而成功访问操作目标对象。

system_grant权限

ohos.permission.INTERNET
允许使用Internet网络。

ohos.permission.USE_BLUETOOTH
允许应用查看蓝牙的配置。

ohos.permission.GET_BUNDLE_INFO
允许查询应用的基本信息。

ohos.permission.PREPARE_APP_TERMINATE
允许应用关闭前执行自定义的预关闭动作。

ohos.permission.PRINT 
允许应用获取打印框架的能力。

ohos.permission.DISCOVER_BLUETOOTH
允许应用配置本地蓝牙,查找远端设备且与之配对连接。

ohos.permission.ACCELEROMETER
允许应用读取加速度传感器的数据。

ohos.permission.ACCESS_BIOMETRIC
允许应用使用生物特征识别能力进行身份认证。

ohos.permission.ACCESS_NOTIFICATION_POLICY
在本设备上允许应用访问通知策略。

ohos.permission.GET_NETWORK_INFO
允许应用获取数据网络信息。

ohos.permission.GET_WIFI_INFO
允许应用获取Wi-Fi信息。

ohos.permission.GYROSCOPE
允许应用读取陀螺仪传感器的数据。

ohos.permission.KEEP_BACKGROUND_RUNNING
允许Service Ability在后台持续运行。

ohos.permission.NFC_CARD_EMULATION
允许应用实现卡模拟功能。

ohos.permission.NFC_TAG
允许应用读写Tag卡片。

ohos.permission.PRIVACY_WINDOW
允许应用将窗口设置为隐私窗口,禁止截屏录屏

ohos.permission.PUBLISH_AGENT_REMINDER
允许该应用使用后台代理提醒。

ohos.permission.SET_NETWORK_INFO
允许应用配置数据网络。

ohos.permission.SET_WIFI_INFO
允许应用配置Wi-Fi设备。

ohos.permission.VIBRATE
允许应用控制马达振动。

ohos.permission.CLEAN_BACKGROUND_PROCESSES
允许应用根据包名清理相关后台进程。

ohos.permission.COMMONEVENT_STICKY
允许应用发布粘性公共事件。

ohos.permission.MODIFY_AUDIO_SETTINGS
允许应用修改音频设置。

ohos.permission.RUNNING_LOCK
允许应用获取运行锁,保证应用在后台的持续运行。

ohos.permission.SET_WALLPAPER**
允许应用设置壁纸。

ohos.permission.ACCESS_CERT_MANAGER
允许应用进行查询证书及私有凭据等操作。

ohos.permission.hsdr.HSDR_ACCESS
允许应用访问安全检测与响应框架。

user_grant权限

ohos.permission.CAMERA
允许应用使用相机。

ohos.permission.READ_MEDIA
允许应用读取用户外部存储中的媒体文件信息。

ohos.permission.WRITE_MEDIA
允许应用读写用户外部存储中的媒体文件信息。

ohos.permission.APPROXIMATELY_LOCATION
允许应用获取设备模糊位置信息。
ohos.permission.LOCATION
允许应用获取设备位置信息。

ohos.permission.MICROPHONE
允许应用使用麦克风。

ohos.permission.READ_CALENDAR
允许应用读取日历信息。

ohos.permission.READ_HEALTH_DATA
允许应用读取用户的健康数据。

ohos.permission.WRITE_CALENDAR
允许应用添加、移除或更改日历活动。

ohos.permission.ACCESS_BLUETOOTH
允许应用接入蓝牙并使用蓝牙能力,例如配对、连接外围设备等。

ohos.permission.MEDIA_LOCATION
允许应用访问用户媒体文件中的地理位置信息。

ohos.permission.APP_TRACKING_CONSENT
允许应用读取开放匿名设备标识符。

ohos.permission.ACTIVITY_MOTION
允许应用读取用户的运动状态。

ohos.permission.DISTRIBUTED_DATASYNC
允许不同设备间的数据交换。

声明权限

应用在申请权限时,需要在项目的配置文件中,逐个声明需要的权限,否则应用将无法获取授权。

应用需要在module.json5配置文件的requestPermissions标签中声明权限。

属性 说明 取值范围
name 必须,填写需要使用的权限名称。 需为系统已定义的权限
reason 可选,当申请的权限为user_grant权限时此字段必填,用于描述申请权限的原因。**说明:**该字段用于应用上架校验,当申请的权限为user_grant权限时必填,并且需要进行多语种适配。 使用string类资源引用。格式为$string: ***
usedScene 可选,当申请的权限为user_grant权限时此字段必填。描述权限使用的场景由abilities和when组成。其中abilities可以配置为多个UIAbility组件,when表示调用时机。**说明:**默认为可选,当申请的权限为user_grant权限时,abilities标签必填,when标签可选。 abilities:UIAbility或者ExtensionAbility组件的名称。when:inuse(使用时)、always(始终)。
{
  "module" : {
    // ...
    "requestPermissions":[
      {
        "name" : "ohos.permission.PERMISSION1",
        "reason": "$string:reason",
        "usedScene": {
          "abilities": [
            "FormAbility"
          ],
          "when":"inuse"
        }
      },
      {
        "name" : "ohos.permission.PERMISSION2",
        "reason": "$string:reason",
        "usedScene": {
          "abilities": [
            "FormAbility"
          ],
          "when":"always"
        }
      }
    ]
  }
}

权限使用理由的文案内容规范

  1. 保持句子简洁、不要加入多余的分割符号。

    建议句式:用于某事。

    示例:用于扫码拍照。

  2. 用途描述的字串建议小于72个字符(即36个中文字符,UI界面显示大约为两行)。不能超过256个字符,以保证多语言适配的体验。

  3. 如果不写,将展示默认的申请理由。

向用户申请授权

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

申请user_grant权限步骤

  1. 在配置文件中,声明应用需要请求的权限。

  2. 将应用中需要申请权限的目标对象与对应目标权限进行关联,让用户明确地知道,哪些操作需要用户向应用授予指定的权限。

  3. 运行应用时,在用户触发访问操作目标对象时应该调用接口,精准触发动态授权弹框。该接口的内部会检查当前用户是否已经授权应用所需的权限,如果当前用户尚未授予应用所需的权限,该接口会拉起动态授权弹框,向用户请求授权。

  4. 检查用户的授权结果,确认用户已授权才可以进行下一步操作。

约束与限制

  • 每次执行需要目标权限的操作时,应用都必须检查自己是否已经具有该权限。

    如需检查用户是否已向您的应用授予特定权限,可以使用checkAccessToken()函数,此方法会返回PERMISSION_GRANTEDPERMISSION_DENIED

  • 每次访问受目标权限保护的接口之前,都需要使用requestPermissionsFromUser()接口请求相应的权限。

    用户可能在动态授予权限后通过系统设置来取消应用的权限,因此不能将之前授予的授权状态持久化。

  • user_grant权限授权要基于用户可知可控的原则,需要应用在运行时主动调用系统动态申请权限的接口,系统弹框由用户授权,用户结合应用运行场景的上下文,识别出应用申请相应敏感权限的合理性,从而做出正确的选择。

  • 系统不鼓励频繁弹窗打扰用户,如果用户拒绝授权,将无法再次拉起弹窗。需要应用引导用户在系统应用“设置”的界面中手动授予权限。

1、检查单个权限是否授权

/**
 * 校验当前权限是否已经授权
 * @param permission
 * @returns
 */
async checkAccessToken(permission: Permissions) {
  let 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 (err) {
    console.error(`getBundleInfoForSelf failed, error: ${err}`);
  }

  // 校验应用是否被授予权限
  try {
    grantStatus = await atManager.checkAccessToken(tokenID, permission);
  } catch (err) {
    console.error(`checkAccessToken failed, error: ${err}`);
  }
  return grantStatus;
}

2、批量检查权限

/**
 * 请求权限
 * @param permissions
 * @param context
 */
requestPermissions(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
  let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
  // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
  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}`);
  })
}

3、批量申请权限

/**
 * 这里传入需要检查的权限,也可以传入权限数组Array<Permissions>
 * @param permission
 * @returns
 */
async checkAndRequestPermissions(permissions: Array<Permissions>, context: common.UIAbilityContext): Promise<void> {
  for (let i = 0; i < permissions.length; i++) {
    let grantStatus: abilityAccessCtrl.GrantStatus = await this.checkAccessToken(permissions[i]);
    if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
      // 已经授权,可以继续访问目标操作

    } else {
      // 申请权限
      this.requestPermissions(this.permissions, context)
    }
  }

}

4、申请权限的使用方法


aboutToAppear(): void {
  const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext
  this.checkAndRequestPermissions(this.permissions, context)
}

原文链接:https://juejin.cn/post/7349791638112305162 作者:儿歌八万首

(0)
上一篇 2024年3月25日 下午5:03
下一篇 2024年3月25日 下午5:13

相关推荐

发表回复

登录后才能评论