HarmonyOS NEXT鸿蒙开发:申请user_grant权限封装成模块

介绍

将申请 user_grant 权限的代码,进行封装

代码

创建目录

在 ets 创建目录 utils

创建文件

在 utils 目录下创建 RequestPermissions.ets 文件,内容如下:

import { abilityAccessCtrl, common, Permissions,bundleManager } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';

const TAG = "授权(RequestPermissions.ets)-----"
/**
 * 所有要申请的权限
 */
const allPermissions: Array<Permissions> = [
  // 'ohos.permission.LOCATION',
  'ohos.permission.DISTRIBUTED_DATASYNC' // 申请麦克风权限
];
/**
 * 所有要申请的权限,用户拒绝授权时的提示信息
 */
const allRejectedMessage: Array<string> = [
  '需要使用分布式数据库权限'
]
let atManager: abilityAccessCtrl.AtManager;
/**
 * 创建 AtManager 对象
 */
function createAtManager(){
  if(!atManager){
    console.debug(TAG,"amManager 为null,创建")
    atManager = abilityAccessCtrl.createAtManager()
  }else{
    console.debug(TAG,"amManager 不为null,不用创建")
  }
}
/**
 * 校验权限
 * @param permission
 * @returns 返回 boolean 类型,true表示授权,false表示未授权
 */
export async function checkPermissionGrant(permission: Permissions): Promise<boolean> {
  createAtManager();
  let ret: boolean = false;
  // 获取应用程序的accessTokenID
  let tokenId: number = 0;
  try {
    const bundleInfo: bundleManager.BundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
    const appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
    tokenId = appInfo.accessTokenId;
  } catch (error) {
    const err: BusinessError = error as BusinessError;
    console.error(TAG,`获取 bundle info 失败! Code is ${err.code}, message is ${err.message}`);
  }
  // 校验应用是否被授予权限
  try {
    const grantStatus = atManager.checkAccessTokenSync(tokenId, permission);
    ret = ( grantStatus == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED )
  } catch (err) {
    ret = false
    console.error(TAG,`校验权限失败!Code is ${err.code}, message is ${err.message}`);
  }
  return ret;
}
/**
 * 一次申请所有的权限
 * @param context
 */
export function requestAllPermissionsFromUserAndShow( uiContext: UIContext): void {
  requestPermissionsFromUserAndShow(allPermissions,allRejectedMessage,uiContext);
}
/**
 * 请求一个权限
 * 使用UIExtensionAbility:将common.UIAbilityContext 替换为common.UIExtensionContext
 * @param permission 申请的权限,Permissions类型
 * @param rejectedMessage 用户拒绝授权的提示信息
 * @param context
 */
export function requestPermissionFromUserAndShow(permission:Permissions,rejectedMessage:string, uiContext: UIContext): void {
  requestPermissionsFromUserAndShow([permission],[rejectedMessage],uiContext);
}
/**
 * 向用户申请多个权限
 * 使用UIExtensionAbility:将common.UIAbilityContext 替换为common.UIExtensionContext
 * @param permissions: Array<Permissions>,申请的权限
 * @param rejectedMessage: Array<string>,对应权限,拒绝时的提示消息
 * @param context
 */
export function requestPermissionsFromUserAndShow(permissions: Array<Permissions>,rejectedMessage: Array<string>, uiContext: UIContext): void {
  if(!uiContext){
    console.error(TAG, 'context不能为空');
    return
  }
  createAtManager();
  // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
  atManager.requestPermissionsFromUser(uiContext.getHostContext(), 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) {
        // 用户授权,可以继续访问目标操作
        console.log(TAG,`申请授权 ${permissions} 成功`);
      } else {
        // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
        // 显示Toast提示
        try {
          uiContext.getPromptAction().showToast({
            message: rejectedMessage[i], // 提示文本
            duration: 2000, // 显示时长(毫秒),默认1500ms,范围[1500, 3000]
            bottom: 100 // 距离屏幕底部的距离(像素)
          });
        } catch (error) {
          console.error(TAG,"promptAction.showToast() 报错!")
        }
        return;
      }
    }
    // 授权成功
  }).catch((err: BusinessError) => {
    console.error(TAG,`申请权限失败, Code is ${err.code}, message is ${err.message}`);
  })
}
/**
 * 二次向用户申请授权
 * 当应用通过requestPermissionsFromUser()拉起弹框请求用户授权时,用户拒绝授权。应用将无法再次通过requestPermissionsFromUser拉起弹框,需要用户在系统应用“设置”的界面中,手动授予权限。
 * @param context 上下文
 * @param permission 权限
 * @returns 返回true,表示申请成功;false表示失败
 */
export async function requestPermissionOnSetting(permission: Permissions,context: Context): Promise<boolean>{
  createAtManager()
  try {
    const datas = await atManager.requestPermissionOnSetting(context, [permission])
    console.info(TAG, JSON.stringify(datas));
    return datas[0] == 0
  }catch (err){
    console.error(TAG , `二次申请授权失败!code:${err.code},message:${err.message}`);
  }
  return false;
}

使用

申请麦克风权限,步骤如下:

  1. 添加授权配置

  2. 添加代码,有两种方式:

    • 在 UIAbility 中向用户申请授权

    • 在UI中向用户申请授权

添加授权

修改 module.json5 配置文件,添加下面内容:

{
  "name": "ohos.permission.MICROPHONE",
  "reason": "$string:microphone_permission_reason",
  "usedScene": {
    "when": "inuse",
    "abilities": ["EntryAbility"]
  }
}

如图:

添加需要权限原因

在 \resources\base\element\string.json 添加申请权限原因:

{
  "name": "microphone_permission_reason",
  "value": "需要使用麦克风"
}

导包

import {requestAllPermissionsFromUserAndShow,requestPermissionFromUserAndShow,checkPermissionGrant,requestPermissionOnSetting} from '../utils/RequestPermissions'

第一次启动申请权限

第一次启动申请权限,在 EntryAbility.ets 中加上下面代码:

async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {
  // Main window is created, set main page for this ability
  hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

  windowStage.loadContent('pages/Index', async (err) => {
    if (err.code) {
      hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
      return;
    }
    // 第一次启动申请权限
    const pg = 'ohos.permission.MICROPHONE'
    const reason = '需要使用麦克风'
    const cpg = await checkPermissionGrant(pg)
    if(cpg){
      console.log(TAG,` 检测授予 ${pg} 授权`)
    }else{
      // 申请所有权限
      // requestAllPermissionsFromUser(getContext())
      // 只分布式数据同步权限
      try {
        const uiContext = windowStage.getMainWindowSync().getUIContext()
        requestPermissionFromUserAndShow(pg,reason,uiContext)

      }catch (err) {
        console.error(TAG,`getMainWindowSync() 报错!code:${err.code},message:${err.message}`)
      }
    }
    hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
  });
}

二次申请权限

第一次运行申请权限,如果拒绝,在首页中,二次申请权限

在 Index.ets 中,加上下面代码

async aboutToAppear(): Promise<void> {
  const pg = 'ohos.permission.MICROPHONE'
  const reason = '需要使用麦克风'
  await LoginKVStoreUtils.init(this.getUIContext().getHostContext()!)
  const cpg = await checkPermissionGrant(pg)
  if(cpg){
    console.log(TAG,` 检测授予 ${pg} 授权`)
  }else{
    // 二次申请
    try {
      const context = this.getUIContext().getHostContext()
      if (context != null) {
        const rpos = await requestPermissionOnSetting(pg, context)
        if (!rpos) {
          try {
            this.getUIContext().getPromptAction().showToast({
              message: reason, // 提示文本
              duration: 2000, // 显示时长(毫秒),默认1500ms,范围[1500, 3000]
              bottom: 100 // 距离屏幕底部的距离(像素)
            });
          } catch (error) {
            console.error(TAG, "promptAction.showToast() 报错!")
          }
        }
      }

    }catch (err) {
      console.error(TAG,`getMainWindow() 报错!code:${err.code},message:${err.message}`)
    }
  }
}

原文出处:/show_1GW2O6eNJjE3.html