鸿蒙开发:权限授权封装

简介: 关于权限,算上本章内容已经阐述了四个章节了,从相关的概念到,权限管理的授权方式,再到申请权限,直至最后的权限工具类封装,基本上涵盖了七七八八,希望可以帮助到大家。

前言


本文基于Api13。


关于权限相关的知识点,陆陆续续分享了三篇了,也在前边的文章中关于权限的状态获取,以及权限的申请也做了原生代码的案例分享,本篇文章,我们把权限授权封装一下,便于在实际的开发中灵活的使用。


对于权限授权的封装,主要的功能点有,获取当前权限的状态,也就是是否已经授权;以及主动的申请权限授权,也就是弹出系统的权限申请弹窗;除了以上的两个功能之外,当用户拒绝了权限,是否提示系统设置页面开启权限,也需要封装一下。


权限列表


权限列表是我们向用户申请的权限组,比如你要拍照,就需要申请相机权限,在前边的案例中,有过概述,但是每个权限都是一个很长的字符串,虽然代码中有联想功能,但是管理起来不太方便,所以,这里,针对权限列表,单独做了一个常量管理类,便于后续的使用。


权限

概述

ohos.permission.ACCESS_BLUETOOTH

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

ohos.permission.MEDIA_LOCATION

允许应用访问用户媒体文件中的地理位置信息

ohos.permission.APP_TRACKING_CONSENT

允许应用读取开放匿名设备标识符

ohos.permission.ACTIVITY_MOTION

允许应用读取用户的运动状态

ohos.permission.CAMERA

允许应用使用相机

ohos.permission.DISTRIBUTED_DATASYNC

允许不同设备间的数据交换

ohos.permission.LOCATION_IN_BACKGROUND

允许应用在后台运行时获取设备位置信息

ohos.permission.LOCATION

允许应用获取设备位置信息

ohos.permission.APPROXIMATELY_LOCATION

允许应用获取设备模糊位置信息

ohos.permission.MICROPHONE

允许应用使用麦克风

ohos.permission.READ_CALENDAR

允许应用读取日历信息

ohos.permission.WRITE_CALENDAR

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

ohos.permission.READ_HEALTH_DATA

允许应用读取用户的健康数据

ohos.permission.ACCESS_NEARLINK

允许应用接入星闪并使用星闪能力,例如配对、连接外围设备等


权限常量类


主要把常用的权限,生成对应的常量,在调用的时候,直接使用这个常量即可。


import { Permissions } from '@kit.AbilityKit';
/**
 *AUTHOR:AbnerMing
 *DATE:2025/3/15
 *INTRODUCE:权限列表
 */
export class PermissionsConstant {
  static CAMERA: Permissions = "ohos.permission.CAMERA"
  static ACCESS_BLUETOOTH: Permissions = "ohos.permission.ACCESS_BLUETOOTH"
  static MEDIA_LOCATION: Permissions = "ohos.permission.MEDIA_LOCATION"
  static APP_TRACKING_CONSENT: Permissions = "ohos.permission.APP_TRACKING_CONSENT"
  static ACTIVITY_MOTION: Permissions = "ohos.permission.ACTIVITY_MOTION"
  static DISTRIBUTED_DATASYNC: Permissions = "ohos.permission.DISTRIBUTED_DATASYNC"
  static LOCATION_IN_BACKGROUND: Permissions = "ohos.permission.LOCATION_IN_BACKGROUND"
  static LOCATION: Permissions = "ohos.permission.LOCATION"
  static APPROXIMATELY_LOCATION: Permissions = "ohos.permission.APPROXIMATELY_LOCATION"
  static MICROPHONE: Permissions = "ohos.permission.MICROPHONE"
  static READ_CALENDAR: Permissions = "ohos.permission.READ_CALENDAR"
  static READ_HEALTH_DATA: Permissions = "ohos.permission.READ_HEALTH_DATA"
  static ACCESS_NEARLINK: Permissions = "ohos.permission.ACCESS_NEARLINK"
}


权限管理


权限管理,包含了三个功能,分别是,权限状态检查,权限申请,和二次权限验证提示,目前简单封装了常见的调用方式,也提供了异步和可同步的调用方式。


import { abilityAccessCtrl, bundleManager, Permissions } from "@kit.AbilityKit"
/**
 *AUTHOR:AbnerMing
 *DATE:2025/3/15
 *INTRODUCE:权限管理工具
 */
export class PermissionsUtil {
  private constructor() {
  }
  private static mPermissionsUtil: PermissionsUtil
  public static get(): PermissionsUtil {
    if (PermissionsUtil.mPermissionsUtil == undefined) {
      PermissionsUtil.mPermissionsUtil = new PermissionsUtil()
    }
    return PermissionsUtil.mPermissionsUtil
  }
  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:检查并请求权限
   */
  checkRequestPermission(permissions: Permissions[], success: () => void, error?: () => void) {
    if (!this.checkPermissions(permissions)) {
      this.requestPermission(permissions, () => {
        success()
      }, () => {
        this.requestPermissionOnSetting(permissions, () => {
          success()
        }, error)
      })
    } else {
      success()
    }
  }
  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:检查并请求权限
   */
  async checkRequestPermissionPromise(permissions: Permissions[]): Promise<boolean> {
    if (!this.checkPermissions(permissions)) {
      let isBool = await this.requestPermissionPromise(permissions)
      if (isBool) {
        return true
      }
      let isSetting = await this.requestPermissionOnSettingPromise(permissions)
      if (isSetting) {
        return true
      }
      return false
    } else {
      return true
    }
  }
  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:检查用户权限,单个权限
   */
  checkPermission(permission: Permissions): boolean {
    let grantStatus = this.getGrantStatus(permission)
    if (grantStatus == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
      //已有权限
      return true
    } else {
      //没有权限
      return false
    }
  }
  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:检查用户权限,多个权限,一个没权限,都没权限
   */
  checkPermissions(permissions: Permissions[]): boolean {
    let isPermissions = true
    permissions.forEach((item) => {
      let grantStatus = this.getGrantStatus(item)
      if (grantStatus != abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
        isPermissions = false
      }
    })
    return isPermissions
  }
  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:检查用户权限,多个权限,返回没有权限的数组
   */
  checkPermissionList(permissions: Permissions[]): Permissions[] {
    let permissionArray: Permissions[] = []
    permissions.forEach((item) => {
      let grantStatus = this.getGrantStatus(item)
      if (grantStatus != abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
        permissionArray.push(item)
      }
    })
    return permissionArray
  }
  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:权限申请
   */
  requestPermission(permissions: Permissions[],
    success: () => void, error?: (permissionArray: string[]) => void) {
    this.getAtManager().requestPermissionsFromUser(getContext(), permissions)
      .then((data) => {
        let grantStatus: Array<number> = data.authResults
        let tempPermissionList: Permissions[] = []
        for (let i = 0; i < grantStatus.length; i++) {
          if (grantStatus[i] != 0) {
            tempPermissionList.push(permissions[i])
          }
        }
        if (tempPermissionList.length == 0) {
          success()
        } else {
          if (error != undefined) {
            error(tempPermissionList)
          }
        }
      })
  }
  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:权限申请
   */
  async requestPermissionPromise(permissions: Permissions[]): Promise<boolean> {
    let result = await this.getAtManager().requestPermissionsFromUser(getContext(), permissions)
    let grantStatus: Array<number> = result.authResults
    let tempPermissionList: Permissions[] = []
    for (let i = 0; i < grantStatus.length; i++) {
      if (grantStatus[i] != 0) {
        tempPermissionList.push(permissions[i])
      }
    }
    if (tempPermissionList.length == 0) {
      return true
    } else {
      return false
    }
  }
  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:二次向用户申请授权
   */
  requestPermissionOnSetting(permissions: Array<Permissions>,
    success: () => void, error?: () => void) {
    abilityAccessCtrl.createAtManager().requestPermissionOnSetting(getContext(), permissions)
      .then((data: Array<abilityAccessCtrl.GrantStatus>) => {
        let isPermissions = true
        data.forEach((status) => {
          if (status != abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
            //没有权限
            isPermissions = false
          }
        })
        if (isPermissions) {
          success()
        } else {
          if (error != undefined) {
            error()
          }
        }
      })
  }
  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:二次向用户申请授权
   */
  async requestPermissionOnSettingPromise(permissions: Array<Permissions>): Promise<boolean> {
    let result = await abilityAccessCtrl.createAtManager().requestPermissionOnSetting(getContext(), permissions)
    let isPermissions = true
    result.forEach((status) => {
      if (status != abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
        //没有权限
        isPermissions = false
      }
    })
    if (isPermissions) {
      return true
    } else {
      return false
    }
  }
  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:校验应用是否被授予权限
   */
  getGrantStatus(permissionName: Permissions): abilityAccessCtrl.GrantStatus {
    let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager()
    // 获取应用程序的accessTokenID
    let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)
    let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo
    let tokenId: number = appInfo.accessTokenId
    //检查权限状态
    let grantStatus = atManager.checkAccessTokenSync(tokenId, permissionName)
    return grantStatus
  }
  private getAtManager(): abilityAccessCtrl.AtManager {
    return abilityAccessCtrl.createAtManager()
  }
}


代码调用


异步权限申请


PermissionsUtil.get().checkRequestPermission([PermissionsConstant.CAMERA], () => {
            console.log("======有权限")
          }, () => {
            console.log("======拒绝了权限")
          })


可同步方式权限申请


private async checkPermission() {
  let isPermission = await PermissionsUtil.get().checkRequestPermissionPromise([PermissionsConstant.CAMERA])
  if (isPermission) {
    console.log("======有权限")
  } else {
    console.log("======拒绝了权限")
  }
}


以上的代码,如果没有权限,会直接弹出权限申请的系统弹窗,拒绝之后,会进行二次权限申请。



相关总结


关于权限,算上本章内容已经阐述了四个章节了,从相关的概念到,权限管理的授权方式,再到申请权限,直至最后的权限工具类封装,基本上涵盖了七七八八,希望可以帮助到大家。

相关文章
|
29天前
|
人工智能 物联网 Android开发
【04】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-自定义一个设置输入小部件组件-完成所有设置setting相关的页面-优雅草卓伊凡
【04】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-自定义一个设置输入小部件组件-完成所有设置setting相关的页面-优雅草卓伊凡
160 92
|
2天前
|
安全 索引
鸿蒙开发:如何更新对象数组
关于对象数组中的数据更新,目前例举了三种方式,一种是传统的装饰器方式,另外两种是针对数据源进行操作,数据源直接赋值的方式,适合简单、高频的单元素修改,性能最优且类型安全,而splice方法适合复杂操作或需保持引用稳定的场景,但需注意性能损耗,在实际的开发中可以根据需求,选择自己适合的方式。
60 34
|
29天前
|
人工智能 物联网 Android开发
【03】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-在lib目录新建自定义库UtilsLibrary,ComponentLibrary,CommonConstLibrary完成设置SettingsView.ets初始公共类书写-优雅草卓伊凡
【03】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-在lib目录新建自定义库UtilsLibrary,ComponentLibrary,CommonConstLibrary完成设置SettingsView.ets初始公共类书写-优雅草卓伊凡
72 23
【03】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-在lib目录新建自定义库UtilsLibrary,ComponentLibrary,CommonConstLibrary完成设置SettingsView.ets初始公共类书写-优雅草卓伊凡
|
25天前
|
人工智能 JavaScript 数据安全/隐私保护
鸿蒙开发难题多到崩溃?然而 10 亿终端暗藏财富密码-卓伊凡
鸿蒙开发难题多到崩溃?然而 10 亿终端暗藏财富密码-卓伊凡
50 5
鸿蒙开发难题多到崩溃?然而 10 亿终端暗藏财富密码-卓伊凡
|
14天前
|
人工智能 前端开发 物联网
【05】20250416优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-增加告警中心相关卡片页面WarningCardWidget相关-增加Canvas 绘制折线图-Canvas 绘制柱状图-首页-优雅草卓伊凡
【05】20250416优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-增加告警中心相关卡片页面WarningCardWidget相关-增加Canvas 绘制折线图-Canvas 绘制柱状图-首页-优雅草卓伊凡
34 0
【05】20250416优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-增加告警中心相关卡片页面WarningCardWidget相关-增加Canvas 绘制折线图-Canvas 绘制柱状图-首页-优雅草卓伊凡
|
19天前
|
缓存 开发工具 开发者
鸿蒙NEXT开发App相关工具类(ArkTs)
这段代码展示了一个名为鸿蒙NEXT开发 `AppUtil` 的工具类,主要用于管理鸿蒙应用的上下文、窗口、状态栏、导航栏等配置。它提供了多种功能,例如设置灰阶模式、颜色模式、字体类型、屏幕亮度、窗口属性等,并支持获取应用包信息(如版本号、包名等)。该工具类需在 UIAbility 的 `onWindowStageCreate` 方法中初始化,以便缓存全局变量。代码由鸿蒙布道师编写,适用于鸿蒙系统应用开发,帮助开发者更便捷地管理和配置应用界面及系统属性。
|
7天前
|
安全 前端开发 Android开发
拥抱国产化:转转APP的鸿蒙NEXT端开发尝鲜之旅
本文将要分享的是转转APP在开发全新鸿蒙NEXT端所遇到的一些问题,对比了鸿蒙开发和 Android、iOS 的不同,总结了这次开发过程中的一些经验等等。希望能带给你启发。
21 0
|
30天前
|
前端开发
鸿蒙开发:使用Rect绘制矩形
几何矩形,在实际的开发中,有多种的实现方式,并非一定需要Rect组件,但是,如果有需要用到矩形的场景,建议还是使用Rect组件,因为Rect组件自身携带了很多样式属性,可以满足我们日常的不同的需求。
鸿蒙开发:使用Rect绘制矩形
|
1月前
|
存储 调度 开发者
HarmonyOS Next 实战卡片开发 03
本文详细介绍了基于 HarmonyOS Next 的卡片开发实战,涵盖从项目创建到功能实现的全流程。首先通过新建项目和服务卡片搭建基础框架,并设置沉浸式体验优化界面。接着实现了首页轮播图功能,包括申请网络权限、初始化数据和构建轮播组件。随后深入讲解了卡片 id 的处理,涉及获取、返回、持久化存储及移除操作,确保卡片与应用间的高效通信。此外,封装了下载图片工具类,支持卡片发起通知获取网络图片,增强功能扩展性。最后实现了卡片同步轮播功能,使首页与卡片轮播状态保持一致。整个流程注重细节,结合实际案例,为开发者提供了全面的参考。
83 20
HarmonyOS Next 实战卡片开发 03
|
1月前
|
移动开发 JavaScript API
HarmonyOS Next 简单上手元服务开发
本文介绍了 HarmonyOS Next 中元服务的开发流程与关键特性。元服务是一种轻量级应用程序形态,支持免安装、秒开直达,适用于听音乐、打车等场景,大幅提升服务获取效率。文章详细讲解了元服务的开发旅程,包括在 AGC 平台上新建项目、修改名称与图标、新增卡片等内容,并提供了代码示例,如 AtomicServiceTabs 的 tab 切换和标题设置、AtomicServiceNavigation 的路由管理等。此外,还探讨了 AtomicServiceWeb 的使用方法,涵盖鸿蒙页面与 h5 页面的数据传递及方法调用。
117 20
HarmonyOS Next 简单上手元服务开发