权限管理,鸿蒙Next版

  一、应用权限概述

注意事项

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

部分 API 权限调用的时候还会弹窗,如:麦克风、位置、摄像头、相册、传感器(sensor)、日历等。

申请应用权限时,需要注意两个关键信息:

  1. 权限级别
  2. 授权方式

权限文档截图 

 

 

应用权限级别

系统根据应用的APL等级设置进程域和数据域标签,并通过访问控制机制限制应用可访问的数据范围,从而实现在机制上消减应用数据泄露的风险。

不同APL等级的应用能够申请的权限等级不同,且不同的系统资源(如:通讯录等)或系统能力(如:访问摄像头、麦克风等)受不同的应用权限保护。通过严格的分层权限保护,有效抵御恶意攻击,确保系统安全可靠。

应用权限管控的详细介绍,请参考应用权限管控概述

应用APL等级

应用的等级可以分为以下三个等级,等级依次提高。

APL级别

说明

大白话

normal

默认情况下,应用的APL等级都为normal等级。

都能用

system_basic

该等级的应用服务提供系统基础服务。

要签名证书

system_core

该等级的应用服务提供操作系统核心能力。

仅对系统应用开放

不开放

 授权方式概述

根据授权方式的不同,权限类型可分为 system_grant 和 user_grant。

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

system_grant(系统授权)

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

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

user_grant(用户授权)

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

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

申请 user_grant 用户授权

权限管理封装

由于 检查授权,动态申请授权,处理授权结果 逻辑都是相同的,我们通过 class 类把功能封装,方便复用。

基本结构
import { Permissions } from '@kit.AbilityKit';

class PermissionManager {

  // 检查是否授权
  checkPermissions(permissions: Permissions[]) {

  }

  // 动态申请授权(首次弹窗申请)
  async requestPermissions(permissions: Permissions[]) {

  }

  // 打开系统设置的权限管理页(处理授权结果)
  openPermissionSettingsPage() {

  }
}

// 导出 Manager
export const permissionManager = new PermissionManager()
封装参考
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(item => item === 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

自动签名步骤

  1. 确保已连接真机或模拟器。

 

2.登录华为帐号后,勾选“Automatically generate signature”,即可完成签名。

 

温馨提示

项目要上线时,调用 ACL 权限需要手动签名,生成密钥和证书请求文件。

由于流程和步骤较多,在后续文章中再补充。

当下先使用自动签名方式调用 ACL 权限。

  1. 在 module.json5 中添加权限
{
  "module": {
    "requestPermissions": [
      // ...
      // 通讯录
      {
        "name": "ohos.permission.READ_CONTACTS",
        "reason": '$string:permission_reason_contact',
        "usedScene": {}
      },
      {
        "name": "ohos.permission.WRITE_CONTACTS",
        "reason": '$string:permission_reason_contact',
        "usedScene": {}
      },
      // 照片
      {
        "name": "ohos.permission.READ_IMAGEVIDEO",
        "reason": "$string:permission_reason_imageVideo",
        "usedScene": {}
      },
      {
        "name": "ohos.permission.WRITE_IMAGEVIDEO",
        "reason": "$string:permission_reason_imageVideo",
        "usedScene": {}
      },
    ],
  }
}

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

  1. 当申请的权限为 user_grant 权限时必填,并且需要进行多语种适配。
  2. 参考句式:用于某事,如:(麦克风)用于录制加密视频和音频。

 

<think>嗯,用户想在鸿蒙Next中实现自定义权限弹窗,这需要我回顾一下之前关于鸿蒙弹窗的知识。记得之前有提到过CustomDialog和SubWindow两种方式,但可能存在代码冗余的问题。用户现在需要的是权限弹窗,可能涉及到权限请求的逻辑,所以需要结合鸿蒙的权限系统。 首先,我应该确认鸿蒙的权限弹窗是否有特定的API,或者是否需要自定义界面。常规的做法可能是使用CustomDialog来设计弹窗的UI,然后处理用户的点击事件,比如同意或拒绝权限。同时,权限的请求可能需要调用系统的权限管理模块,比如@ohos.abilityAccessCtrl这个模块。 然后,需要考虑如何将弹窗的显示与权限请求流程结合起来。用户在弹窗点击同意后,应该触发系统的权限申请,而拒绝的话可能需要关闭弹窗或者提示用户。另外,代码结构方面,如何解耦弹窗逻辑和页面代码,可能需要使用单独的自定义组件或者模块化设计,避免在页面中写太多重复的showDialog方法。 之前有提到过使用CustomDialog的解耦实践,比如把弹窗封装成独立的组件,通过回调函数处理结果。这可能适用于权限弹窗的情况。用户可能需要示例代码,展示如何创建自定义弹窗,绑定按钮事件,以及调用权限接口。 还需要注意鸿蒙Next是否有新的变化,比如API的更新或者权限机制的调整。假设用户提到的鸿蒙Next是基于最新的HarmonyOS本,可能需要参考最新的开发文档,确保示例代码的准确性。 最后,生成的相关问题应该围绕权限弹窗的实现细节、权限请求流程、解耦方法以及用户体验优化等方面。确保回答结构清晰,步骤明确,用户能一步步跟着实现。</think>### 鸿蒙Next自定义权限弹窗实现方法 在鸿蒙Next中实现自定义权限弹窗,需要结合`CustomDialog`组件和权限管理模块,以下是分步骤实现方案: #### 1. 创建自定义弹窗布局 在`resources/base/layout`目录下定义弹窗布局文件`permission_dialog.xml`: ```xml <DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:width="300vp" ohos:height="200vp" ohos:orientation="vertical"> <Text ohos:id="$+id:title_text" ohos:width="match_content" ohos:height="40vp" ohos:text="权限申请说明"/> <Text ohos:id="$+id:content_text" ohos:width="match_parent" ohos:height="100vp" ohos:text="需要访问您的位置信息以提供周边服务"/> <DirectionalLayout ohos:width="match_parent" ohos:height="60vp" ohos:orientation="horizontal"> <Button ohos:id="$+id:cancel_btn" ohos:width="100vp" ohos:height="match_parent" ohos:text="拒绝"/> <Button ohos:id="$+id:confirm_btn" ohos:width="100vp" ohos:height="match_parent" ohos:text="同意"/> </DirectionalLayout> </DirectionalLayout> ``` #### 2. 封装权限弹窗组件 创建`PermissionDialog`类继承`CustomDialog`: ```typescript import { CustomDialog, CommonEvent } from '@ohos.arkui.UIContext'; import { PermissionRequestResult } from '@ohos.abilityAccessCtrl'; export class PermissionDialog extends CustomDialog { private permissionType: string; private onResult: (granted: boolean) => void; constructor(context: Context, permissionType: string, callback: (granted: boolean) => void) { super(context); this.permissionType = permissionType; this.onResult = callback; this.setUIContent($r('app.layout.permission_dialog')); this.initView(); } private initView() { this.findComponentById($r('app.id.cancel_btn')).on('click', () => { this.onResult(false); this.destroy(); }); this.findComponentById($r('app.id.confirm_btn')).on('click', () => { this.requestSystemPermission(); this.destroy(); }); } private async requestSystemPermission() { try { const result: PermissionRequestResult = await abilityAccessCtrl.requestPermissionsFromUser( this.context, [this.permissionType] ); this.onResult(result.authResults[0] === 0); } catch (err) { console.error(`Permission request failed: ${err.code}, ${err.message}`); } } } ``` #### 3. 在页面中调用弹窗 ```typescript import { Ability } from '@ohos.application.Ability'; import { permission } from '@ohos.abilityAccessCtrl'; export default class MainAbility extends Ability { onWindowStageCreate(windowStage) { // 触发权限弹窗逻辑 this.showPermissionDialog('ohos.permission.LOCATION'); } private showPermissionDialog(permissionType: string) { const dialog = new PermissionDialog(this.context, permissionType, (granted) => { if (granted) { // 处理权限授予后的逻辑 } else { // 处理权限拒绝后的逻辑 } }); dialog.show(); } } ``` #### 关键实现要点: 1. **权限声明配置**:需在`module.json5`中声明所需权限: ```json "requestPermissions": [ { "name": "ohos.permission.LOCATION", "reason": "提供基于位置的服务" } ] ``` 2. **弹窗生命周期管理**:通过`destroy()`方法确保弹窗资源释放[^2] 3. **系统权限对接**:通过`abilityAccessCtrl`模块与系统权限管理服务交互,保证权限请求合规性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值