鸿蒙掌上驾考宝典应用开发31:权限管理——PermissionUtil 二次授权策略
·
第31篇:权限管理——PermissionUtil 二次授权策略

一、引言
鸿蒙系统对权限管理有严格的要求,用户首次拒绝后应用需要提供二次授权引导。DriverLicenseExam 项目的 PermissionUtil 工具类封装了完整的权限申请流程,包括首次申请、二次授权、状态检查等。本文将深入解析其实现。
二、权限管理架构
2.1 权限状态枚举
enum PermissionStatus {
GRANTED = 0, // 已授权
DENIED = -1, // 已拒绝
UNKNOWN = 2, // 未知
}
2.2 权限管理器
export class PermissionUtil {
private static _atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
private static _context: Context;
}
三、权限申请流程
3.1 首次申请
public static async requestPermissions(permissions: Permissions[]) {
const needAuthorized: Permissions[] = [];
let permissive = true;
// 检查每个权限的状态
for (let permission of permissions) {
const isGranted: boolean = await PermissionUtil._checkPermissions(permission);
if (!isGranted) {
needAuthorized.push(permission);
}
}
// 全部已授权,直接返回
if (!needAuthorized.length) {
return permissive;
}
// 向用户请求授权
try {
const data = await PermissionUtil._atManager
.requestPermissionsFromUser(PermissionUtil._context, needAuthorized);
let grantStatus: number[] = data.authResults;
const needAuthorizedAgain: Permissions[] = [];
for (let i = 0; i < grantStatus.length; i++) {
if (grantStatus[i] === PermissionStatus.GRANTED) {
Logger.info(TAG, 'request permission success: ' + needAuthorized[i]);
} else if (grantStatus[i] === PermissionStatus.DENIED) {
permissive = false;
needAuthorizedAgain.push(needAuthorized[i]);
}
}
// 对拒绝的权限进行二次申请
PermissionUtil._requestPermissionsOnSetting(needAuthorizedAgain);
return permissive;
} catch (error) {
return false;
}
}
3.2 二次授权
// 用户首次拒绝后,引导用户到设置页面授权
private static async _requestPermissionsOnSetting(permissions: Permissions[]) {
PermissionUtil._atManager.requestPermissionOnSetting(PermissionUtil._context, permissions)
.then((data: abilityAccessCtrl.GrantStatus[]) => {
Logger.info(TAG, 'request permission on setting success: ' + JSON.stringify(data));
})
.catch((err: BusinessError) => {
Logger.error(TAG, 'Failed to request permissions on setting: ' + err.message);
});
}
3.3 权限状态检查
private static async _checkPermissions(permission: Permissions): Promise<boolean> {
let grantStatus = await PermissionUtil._checkAccessToken(permission);
return grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}
private static async _checkAccessToken(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {
let grantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
let tokenId: number = 0;
try {
let bundleInfo = bundleManager.getBundleInfoForSelfSync(
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
let appInfo = bundleInfo.appInfo;
if (appInfo) {
tokenId = appInfo.accessTokenId;
}
} catch (error) {
Logger.error(TAG, 'Failed to get bundle info: ' + error.message);
}
try {
grantStatus = await PermissionUtil._atManager.checkAccessToken(tokenId, permission);
} catch (error) {
Logger.error(TAG, 'Failed to check access token: ' + error.message);
}
return grantStatus;
}
四、权限声明
在 module.json5 中声明应用所需权限:
{
"requestPermissions": [
{
"name": "ohos.permission.INTERNET",
"reason": "用于网络请求"
},
{
"name": "ohos.permission.APPROXIMATELY_LOCATION",
"reason": "用于获取当前位置"
},
{
"name": "ohos.permission.LOCATION",
"reason": "用于获取精确位置"
},
{
"name": "ohos.permission.GET_NETWORK_INFO",
"reason": "用于获取网络状态"
},
{
"name": "ohos.permission.VIBRATE",
"reason": "用于答题振动反馈"
}
]
}
五、权限使用场景
// 定位权限申请
Utils.applyLocationPermission().then((city) => {
if (city) {
this.guideService.updateCity(city);
}
});
// 通知权限申请
notificationManager.requestEnableNotification(this.context).then(() => {
hilog.info(0x0000, 'testTag', '[ANS] requestEnableNotification success');
});
六、总结
PermissionUtil 实现了完整的权限管理流程,包括状态检查、首次申请、二次授权引导,确保应用在最小权限原则下正常运行。
关键源码文件:
commons/commonLib/src/main/ets/utils/PermissionUtil.ets
更多推荐




所有评论(0)