在 HarmonyOS/OpenHarmony 应用开发中,权限控制是保障用户隐私和数据安全的重要机制。
以下是完整的 ArkTS 权限控制实现方案,包含最佳实践和典型场景示例:
一、权限系统架构设计
1. 权限分级机制
js
enum PermissionType {
// 普通权限(无需用户授权)
NORMAL = 0,
// 敏感权限(需动态申请)
SENSITIVE = 1,
// 特殊权限(需跳转设置页)
SPECIAL = 2
}
2. 权限管理类封装
js
class PermissionManager {
private context: common.UIAbilityContext;
private atManager: abilityAccessCtrl.AtManager;
constructor(context: common.UIAbilityContext) {
this.context = context;
this.atManager = abilityAccessCtrl.createAtManager();
}
}
二、动态权限申请实现
1. 基础权限申请
js
async requestPermission(permission: string): Promise<boolean> {
try {
const grantStatus = await this.atManager.checkAccessToken(
this.context.tokenId,
permission
);
if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
return true;
}
const result = await this.atManager.requestPermissionsFromUser(
this.context,
[permission]
);
return result.authResults[0] === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
} catch (err) {
console.error(`Permission request failed: ${err.code}, ${err.message}`);
return false;
}
}
2. 批量权限申请优化
js
async requestMultiplePermissions(
permissions: Array<string>
): Promise<Record<string, boolean>> {
const results: Record<string, boolean> = {};
// 先检查已授权状态
await Promise.all(permissions.map(async (permission) => {
const granted = await this.checkPermission(permission);
if (granted) {
results[permission] = true;
}
}));
// 筛选未授权权限
const needRequest = permissions.filter(p => !results[p]);
if (needRequest.length === 0) return results;
// 批量申请
const requestResult = await this.atManager.requestPermissionsFromUser(
this.context,
needRequest
);
// 合并结果
needRequest.forEach((permission, index) => {
results[permission] =
requestResult.authResults[index] === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
});
return results;
}
三、权限使用最佳实践
1. 带解释的权限申请
js
async requestWithRationale(
permission: string,
rationale: {
title: string;
message: string;
buttonText?: string;
}
): Promise<boolean> {
// 先检查是否已拒绝过
const shouldShowRationale = await this.atManager.shouldShowRequestPermissionRationale(
this.context,
permission
);
if (shouldShowRationale) {
await showDialog({
title: rationale.title,
message: rationale.message,
buttons: [
{
text: rationale.buttonText || 'OK',
action: async () => {
return this.requestPermission(permission);
}
}
]
});
} else {
return this.requestPermission(permission);
}
}
2. 权限结果监听
js
class PermissionStatusObserver {
private callback: (permission: string, granted: boolean) => void;
constructor(callback: (permission: string, granted: boolean) => void) {
this.callback = callback;
this.registerObserver();
}
private registerObserver() {
abilityAccessCtrl.on('permissionStateChange', (data) => {
this.callback(data.permission, data.granted);
});
}
}
// 使用示例
new PermissionStatusObserver((permission, granted) => {
console.log(`Permission ${permission} changed to ${granted}`);
});
四、特殊场景处理
1. 跳转设置页面
js
async openPermissionSettings(): Promise<void> {
try {
await this.context.startAbility({
bundleName: 'com.android.settings',
abilityName: 'com.android.settings.Settings',
parameters: {
'destination': 'PERMISSION' // 直达权限设置页
}
});
} catch (err) {
console.error('Failed to open settings:', err);
}
}
2. 后台权限管理
js
async checkBackgroundPermission(): Promise<boolean> {
const backgroundPerms = [
'ohos.permission.LOCATION_IN_BACKGROUND',
'ohos.permission.READ_MEDIA_IN_BACKGROUND'
];
const results = await this.requestMultiplePermissions(backgroundPerms);
return Object.values(results).every(Boolean);
}
五、配置声明示例
module.json5
配置:
js
{
"requestPermissions": [
{
"name": "ohos.permission.CAMERA",
"reason": "用于视频通话功能",
"usedScene": {
"abilities": ["MainAbility"],
"when": "always"
}
},
{
"name": "ohos.permission.READ_MEDIA",
"reason": "访问用户相册",
"usedScene": {
"abilities": ["GalleryAbility"],
"when": "inuse"
}
}
]
}
六、关键注意事项:
- 最小权限原则:只申请必要的权限
- 适时申请:在具体使用场景时申请(如点击拍照按钮时申请相机权限)
- 持续监控:定期检查权限状态变化(特别是后台权限)