鸿蒙Next应用权限管理

2025-06-27 22:46:50
120次阅读
0个评论

简介: 系统提供了一种允许应用访问系统资源(如:通讯录等)和系统能力(如:访问摄像头、麦克风等)的通用权限访问方式,来保护系统数据(包括用户个人数据)或功能,避免它们被不当或恶意使用。 授权方式system_grant(系统授权) 指的是系统授权类型,如果在应用中申请了system_grant权限,那么系统会在用户安装应用时,自动把相应权限授予给应用。 user_grant(用户授权) 指的是用户授权类型,该类型权限不仅需要在安装包中申请权限,还需要在应用动态运行时,通过发送弹窗的方式请求用户授权。在用户手动允许授权后,应用才会真正获取相应权限,从而成功访问操作目标对象。

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

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
@ComponentV2
struct 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
  });
}

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

收藏00

登录 后评论。没有帐号? 注册 一个。