写点什么

鸿蒙 Next 应用权限管理

作者:auhgnixgnahz
  • 2025-06-23
    北京
  • 本文字数:4095 字

    阅读完需:约 13 分钟

简介


系统提供了一种允许应用访问系统资源(如:通讯录等)和系统能力(如:访问摄像头、麦克风等)的通用权限访问方式,来保护系统数据(包括用户个人数据)或功能,避免它们被不当或恶意使用。


授权方式


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


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


以下通过定位权限介绍一下需要用户授权的权限请求步骤:



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


"requestPermissions": [      {'name': 'ohos.permission.INTERNET'},      {        "name" : "ohos.permission.APPROXIMATELY_LOCATION",        "reason": "$string:location_reason",        "usedScene": {          "abilities": [            "EntryAbility"          ],          "when":"inuse"        }      },      {        "name" : "ohos.permission.LOCATION",        "reason": "$string:location_reason",        "usedScene": {          "abilities": [            "EntryAbility"          ],          "when":"inuse"        }      }    ]
复制代码


2.在需要用到定位权限的时候,查询是否有该权限,使用 atManager.checkAccessToken 方法,返回-1 无权限,0 有权限


3.如果没有权限,使用 atManager.requestPermissionsFromUser 方法动态向用户申请权限,通过回调判断是否同意


4.如果用户拒绝了该权限,还可以调用 atManager.requestPermissionOnSetting 直接拉起权限设置弹框,引导用户授予权限


在 page 中调用:


import { location_permissions, requestLocation, requestPermissionOnSetting } from '../utils/RequestPermission'import { common } from '@kit.AbilityKit'import { showToast } from '../utils/ToastUtil'
@Entry@ComponentV2struct permission{
build() { Column(){ Button('获取定位权限').onClick(()=>{ requestLocation(getContext(this) as common.UIAbilityContext).then((result)=>{ if (result) { showToast('获取成功') }else { showToast('获取失败') requestPermissionOnSetting(location_permissions,getContext(this) as common.UIAbilityContext).then((result)=>{ if (result) { showToast('获取成功') }else { showToast('获取失败') } }) } }) }) } }}
复制代码


权限请求控制方法:


import { abilityAccessCtrl, bundleManager, common, Permissions } from '@kit.AbilityKit';import { BusinessError } from '@kit.BasicServicesKit';//位置const LOCATION:Permissions = 'ohos.permission.LOCATION'const LOCATION_IN_BACKGROUND:Permissions = 'ohos.permission.LOCATION_IN_BACKGROUND'const APPROXIMATELY_LOCATION:Permissions = 'ohos.permission.APPROXIMATELY_LOCATION'export const location_permissions: Array<permissions> = [LOCATION,APPROXIMATELY_LOCATION]//相机const CAMERA:Permissions = 'ohos.permission.CAMERA'//麦克风const MICROPHONE:Permissions = 'ohos.permission.MICROPHONE'//通讯录const READ_CONTACTS:Permissions = 'ohos.permission.READ_CONTACTS'const WRITE_CONTACTS:Permissions = 'ohos.permission.WRITE_CONTACTS'//日历const READ_CALENDAR:Permissions = 'ohos.permission.READ_CALENDAR'const WRITE_CALENDAR:Permissions = 'ohos.permission.WRITE_CALENDAR'//运动数据const ACTIVITY_MOTION:Permissions = 'ohos.permission.ACTIVITY_MOTION'//身体传感器const READ_HEALTH_DATA:Permissions = 'ohos.permission.READ_HEALTH_DATA'//图片和视频const WRITE_IMAGEVIDEO:Permissions = 'ohos.permission.WRITE_IMAGEVIDEO'const READ_IMAGEVIDEO:Permissions = 'ohos.permission.READ_IMAGEVIDEO'const MEDIA_LOCATION:Permissions = 'ohos.permission.MEDIA_LOCATION'
//音乐和音频const WRITE_AUDIO:Permissions = 'ohos.permission.WRITE_AUDIO'const READ_AUDIO:Permissions = 'ohos.permission.READ_AUDIO'
//跨应用关联const APP_TRACKING_CONSENT:Permissions = 'ohos.permission.APP_TRACKING_CONSENT'//多设备协同const DISTRIBUTED_DATASYNC:Permissions = 'ohos.permission.DISTRIBUTED_DATASYNC'//蓝牙const ACCESS_BLUETOOTH:Permissions = 'ohos.permission.ACCESS_BLUETOOTH'//剪切板const READ_PASTEBOARD:Permissions = 'ohos.permission.READ_PASTEBOARD'//文件夹const READ_WRITE_DOWNLOAD_DIRECTORY:Permissions = 'ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY'const READ_WRITE_DOCUMENTS_DIRECTORY:Permissions = 'ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY'//星闪const ACCESS_NEARLINK:string = 'ohos.permission.ACCESS_NEARLINK'//文件//读写媒体库图片或视频 推荐方案(无需申请权限):使用Picker读取媒体库的图片与视频//读取媒体库音频文件 需申请音视频权限//读取文件管理器中的文件 无需申请权限,通过文件Picker读写文件管理器中的文件
//PERMISSION_DENIED -1 表示未授权//PERMISSION_GRANTED 0 表示已授权let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();

export async function requestLocation(context: common.UIAbilityContext): Promise<boolean>{ let grantStatus1: boolean = await checkPermissionGrant(LOCATION) === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;// 获取精确定位权限状态 let grantStatus2: boolean = await checkPermissionGrant(APPROXIMATELY_LOCATION) === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;// 获取模糊定位权限状态 // 精确定位权限只能跟模糊定位权限一起申请,或者已经有模糊定位权限才能申请精确定位权限 if (grantStatus2 && !grantStatus1) { // 申请精确定位权限 return reqPermissionsFromUser([LOCATION],context) } else if (!grantStatus1 && !grantStatus2) { // 申请模糊定位权限与精确定位权限或单独申请模糊定位权限 return reqPermissionsFromUser([LOCATION,APPROXIMATELY_LOCATION],context) } else { // 已经授权,可以继续访问目标操作 return true }}

async function checkPermissionGrant(permission: Permissions): Promise<abilityaccessctrl.grantstatus> { // 获取应用程序的accessTokenID let tokenId: number = 0; let grantStatus: abilityAccessCtrl.GrantStatus = -1; 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 (error) { const err: BusinessError = error as BusinessError; console.error(`Failed to get bundle info for self. Code is ${err.code}, message is ${err.message}`); } // 校验应用是否被授予权限 try { grantStatus = await atManager.checkAccessToken(tokenId, permission); } catch (error) { const err: BusinessError = error as BusinessError; console.error(`Failed to check access token. Code is ${err.code}, message is ${err.message}`); } return grantStatus;}

async function reqPermissionsFromUser(permissions: Array<permissions>, context: common.UIAbilityContext): Promise<boolean> { return atManager.requestPermissionsFromUser(context, permissions).then((data) => { let grantStatus: Array<number> = data.authResults; let grants: number = 0; for (let i = 0; i < grantStatus.length; i++) { if (grantStatus[i] === 0) { // 用户授权,可以继续访问目标操作 grants++ } } if (grants===grantStatus.length) { return true } return false }).catch((err: BusinessError) => { console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`); return false });}//引导用户到系统设置中打开相应的权限export function requestPermissionOnSetting(permissions: Array<permissions>, context: common.UIAbilityContext):Promise<boolean> { return atManager.requestPermissionOnSetting(context, permissions).then((data: Array<abilityaccessctrl.grantstatus>) => { let grants: number = 0; for (let i = 0; i < data.length; i++) { if (data[i] === 0) { // 用户授权,可以继续访问目标操作 grants++ } } if (grants===data.length) { return true } return false }).catch((err: BusinessError) => { return false });}</abilityaccessctrl.grantstatus></boolean></permissions></number></boolean></permissions></abilityaccessctrl.grantstatus></boolean></permissions>
复制代码


以上列出了所有需要用户授权的权限,如果用到相关的用户权限,可以按照定位权限的方式动态获取。后续介绍使用 Picker 读取媒体库的图片与视频。


发布于: 刚刚阅读数: 4
用户头像

auhgnixgnahz

关注

还未添加个人签名 2018-07-10 加入

还未添加个人简介

评论

发布
暂无评论
鸿蒙Next应用权限管理_鸿蒙Next_auhgnixgnahz_InfoQ写作社区