鸿蒙的请求用户权限相对比较好用,下面的代码,基本是来源华为官方的文档,只需要封装一下,挺好用。
鸿蒙的权限分类
鸿蒙的权限分为两种
- 系统权限(直接配置文件配置申请,不需要询问用户)
- 需要用户手动确认的权限(必须提示用户主动授权)
参考:
《应用权限管控概述》
在配置文件中设置需要申请的权限
在配置文件module.json5
中配置requestPermissions
。同时一定要配置usedScene
和reason
。注意reason
字段,不可以直接写字符串原因。因为要求这个是可以翻译的字段。
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}, {
"name": "ohos.permission.LOCATION",
"reason": "$string:location_reason",
"usedScene": {
"when": "inuse"
}
}, {
"name": "ohos.permission.APPROXIMATELY_LOCATION",
"reason": "$string:location_reason",
"usedScene": {
"when": "inuse"
}
}
]
参考:
- 《申请应用权限》
弹出界面向用户申请权限
检查有没有之前是不是已经拥有权限
async function checkPermissionGrant(permission: Permissions): Promise<boolean> {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
let grantStatus: abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
// 获取应用程序的accessTokenID
let tokenId: number = 0;
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 == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}
//
checkPermissionGrant("ohos.permission.LOCATION") //true or false
第一次请求用户权限
如上图,就是弹出给用户授权的界面。requestPermissionsFromUser
方法就是弹出上面的界面的。注意,如果用户拒绝了,再此调用requestPermissionsFromUser
是不会再此弹出来的。
async function firstReqPermissionFormUser(permissions: Array<Permissions>, context: common.UIAbilityContext) {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
const data = await atManager.requestPermissionsFromUser(context, permissions)
let grantStatus: Array<number> = data.authResults;
return grantStatus.every(s => s == 0)
}
//
const p = "ohos.permission.LOCATION"
let isAuth = await checkPermissionGrant(p)
if(!isAuth) {
isAuth = await firstReqPermissionFormUser([p], context); // true or false
}
当用户第一次申请权限的时候,用户拒绝了,下次再次调用此代码。将不会弹出界面让用户选择了。
如果还需要选项,就需要引导用户去设置里面授权。
二次向用户申请授权
requestPermissionOnSetting
打开应用设置权限界面,可以参考打开应用设置权限界面。此节不详细说明。
第一次被拒绝后,那么需要引导用户去设置中,授权。
const secondAuthResults = await atManager.requestPermissionOnSetting(context, permissions)
const isSecondAuth = secondAuthResults.every(s => s == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
注意在这里设置会有三种情况。
设置中授权界面一般会有三个选项:
- 仅使用期间允许
- 每次使用询问
- 禁止
只有第一个选项,结果会返回授权了。第三个选项,好理解,就是不授权。但是要注意了,第二个选项也是返回不授权。但是我们明显是知道用户是授权了的。所以上面的代码返回false
之后,还需要再次调用第一次授权的代码,再次询问用户是否授权了。
下面是完整二次授权代码
const secondAuthResults = await atManager.requestPermissionOnSetting(context, permissions)
const isSecondAuth = secondAuthResults.every(s => s == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
if (!isSecondAuth) {
const isAuth = await firstReqPermissionFormUser(permissions, context)
resolve(isAuth)
} else {
resolve(true)
}
完整请求权限工具类代码
import { abilityAccessCtrl, bundleManager, common, Permissions } from '@kit.AbilityKit';
import { UIContext } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
async function checkPermissionGrant(permission: Permissions): Promise<boolean> {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
let grantStatus: abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
// 获取应用程序的accessTokenID
let tokenId: number = 0;
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 == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}
async function firstReqPermissionFormUser(permissions: Array<Permissions>, context: common.UIAbilityContext) {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
const data = await atManager.requestPermissionsFromUser(context, permissions)
let grantStatus: Array<number> = data.authResults;
return grantStatus.every(s => s == 0)
}
async function reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext,
uiContext: UIContext) {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
try {
// requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
const isAuth = await firstReqPermissionFormUser(permissions, context)
if (isAuth) {
return true
}
return await new Promise((resolve, reject) => {
uiContext.showAlertDialog({
title: "系统提示",
message: "必须要授权才能使用,是否前往应用进行授权",
autoCancel: false,
primaryButton: {
value: "取消",
action: () => {
resolve(false)
}
},
secondaryButton: {
value: "前往授权",
action: async () => {
const secondAuthResults = await atManager.requestPermissionOnSetting(context, permissions)
const isSecondAuth =
secondAuthResults.every(s => s == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
if (!isSecondAuth) {
const isAuth = await firstReqPermissionFormUser(permissions, context)
resolve(isAuth)
} else {
resolve(true)
}
}
}
})
})
} catch (err) {
const error = err as BusinessError
console.error(`Failed to request permissions from user. Code is ${error.code}, message is ${error.message}`);
}
return true
}
export async function requestPermissions(uiAbilityContext: common.UIAbilityContext, uiContext: UIContext,
permissions: Permissions[]) {
const ps = permissions.map((s) => {
return checkPermissionGrant(s).then(isSuccess => {
if (isSuccess) {
return true
}
return Promise.reject(s)
})
})
const s = await Promise.allSettled(ps)
const rejectedPs =
s.filter(item => item.status == "rejected").map((item: PromiseRejectedResult) => item.reason as Permissions)
if (rejectedPs.length == 0) {
return true
}
return await reqPermissionsFromUser(rejectedPs, uiAbilityContext, uiContext)
}
import { requestPermissions } from './permission';
const isAuth =
await this.requestPermissions(['ohos.permission.LOCATION', 'ohos.permission.APPROXIMATELY_LOCATION'])
if (isAuth) {
//
} else {
//
}
参考:
打开应用设置权限界面
很多的时候,判断 APP 没有权限的时候,会提示让用户去设置界面设置权限,但是这样用户不方便。那么这个时候最好的做法是提示后,直接 APP 打开当前应用的设置界面,让用户直接设置,然后后退回来 APP 就能用了。
打开应用设置页
使用FunctionalButton
组件
import {FunctionalButton, functionalButtonComponentManager} from '@kit.ScenarioFusionKit';
// 声明FunctionalButton
FunctionalButton({
params: {
// OpenType.OPEN_SETTING表示Button为打开授权设置页类型
openType: functionalButtonComponentManager.OpenType.OPEN_SETTING,
label: '打开授权设置页',
// 调整Button样式
styleOption: {
styleConfig: new functionalButtonComponentManager.ButtonConfig()
.fontSize(20)
.fontColor(Color.Black)
}
},
// OpenType为“OPEN_SETTING”时,回调必须选择“onOpenSetting”
controller: new functionalButtonComponentManager.FunctionalButtonController().onOpenSetting((err,
data) => {
if (err) {
// 错误日志处理
hilog.error(0x0000, "testTag", "error: %{public}d %{public}s", err.code, err.message);
return;
}
// 成功日志处理,终止设置应用程序时触发
hilog.info(0x0000, "testTag", "succeeded in opening setting");
data.permissions!.forEach((value, key) => {
hilog.info(0x0000, "testTag", "key: %{public}s value: %{public}s", String(key), value);
})
})
})
效果如下:
但是注意,这个界面中,没有什么定位、相册权限。
定位、相册在鸿蒙中的设置是在【隐私和安全】当中设置的。那如何打开定位权限设置呢。
打开当前应用用户授权的权限设置界面
<font style="color:rgba(0, 0, 0, 0.9);">requestPermissionOnSetting</font>
方法。参考《requestPermissionOnSetting API》。
const permissions = ['ohos.permission.LOCATION', 'ohos.permission.APPROXIMATELY_LOCATION']
const secondAuthResults = await atManager.requestPermissionOnSetting(context, permissions)
const isSecondAuth =
secondAuthResults.every(s => s == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
打开的界面如下:
参考
标签:abilityAccessCtrl,const,err,鸿蒙,await,Harmony,error,日志,权限 From: https://www.cnblogs.com/xakoy/p/18413817在开发过程中遇到其它使用的,会更新此章节