
摘要
在做鸿蒙(HarmonyOS)应用开发时,涉及到相机、定位、存储等功能,系统都会要求应用先获得用户的授权。开发者既要在配置文件里声明权限,还要在代码里动态申请。否则就会遇到"调用接口没反应"或者"权限不足"的报错。本文会从配置、代码、场景三个角度,讲清楚鸿蒙应用如何处理权限请求,并给出一个完整的拍照 Demo。
引言
现在几乎所有应用都会用到敏感权限。比如:
- 短视频应用要用相机和麦克风;
- 外卖应用要用定位;
- 云盘应用要用存储;
鸿蒙在权限管理上也延续了"先声明、再动态申请、用户确认后使用"的模式。这样既能保证用户数据的安全,又能给开发者一个可控的授权流程。接下来我们就从头走一遍,看看鸿蒙应用是如何处理权限请求的。
权限处理的三步流程
在配置文件中声明权限
在 module.json5
文件中声明你需要的权限。如果不写,即使代码里申请了,系统也不会弹框。
json
{
"module": {
"abilities": [
{
"name": "MainAbility",
"requestPermissions": [
{
"name": "ohos.permission.CAMERA"
},
{
"name": "ohos.permission.LOCATION"
}
]
}
]
}
}
这里我们声明了相机和定位权限。
在代码中检查和申请权限
声明了权限后,还要在代码里检查有没有授权。如果没有,就向系统申请。
ts
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import bundleManager from '@ohos.bundle.bundleManager';
async function requestCameraPermission(context) {
const atManager = abilityAccessCtrl.createAtManager();
const bundleInfo = await bundleManager.getBundleInfoForSelf(
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_PERMISSION
);
const tokenId = bundleInfo.appInfo.accessTokenId;
const result = await atManager.verifyAccessToken(tokenId, 'ohos.permission.CAMERA');
if (result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
console.info("已经有相机权限");
} else {
console.info("没有权限,开始申请");
const requestRes = await atManager.requestPermissionsFromUser(context, ['ohos.permission.CAMERA']);
console.info("用户选择结果: " + JSON.stringify(requestRes));
}
}
根据用户操作处理结果
- 如果用户同意,就可以调用相关 API。
- 如果拒绝,就要给出提示,比如"需要相机权限才能继续使用"。
- 如果多次拒绝,可能还要跳转到设置页让用户手动打开权限。
一个完整的相机调用 Demo
下面我们写一个小 Demo:点击按钮 → 检查权限 → 调用相机拍照 → 展示照片。
ts
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import bundleManager from '@ohos.bundle.bundleManager';
import common from '@ohos.app.ability.common';
import camera from '@ohos.multimedia.camera';
@Entry
@Component
struct CameraDemo {
private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
private photoUri: string = '';
build() {
Column() {
Button("拍照").onClick(() => {
this.checkAndOpenCamera();
})
if (this.photoUri !== '') {
Image(this.photoUri)
.width(200).height(200)
}
}
}
async checkAndOpenCamera() {
const hasPermission = await this.checkPermission('ohos.permission.CAMERA');
if (hasPermission) {
this.openCamera();
}
}
async checkPermission(permission: string): Promise<boolean> {
const atManager = abilityAccessCtrl.createAtManager();
const bundleInfo = await bundleManager.getBundleInfoForSelf(
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_PERMISSION
);
const tokenId = bundleInfo.appInfo.accessTokenId;
const result = await atManager.verifyAccessToken(tokenId, permission);
if (result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
return true;
} else {
const req = await atManager.requestPermissionsFromUser(this.context, [permission]);
return req.authResults[0] === 0;
}
}
openCamera() {
// 这里只演示调用相机逻辑,具体 API 可根据相机子系统文档实现
console.info("相机已打开,可以在这里实现拍照逻辑");
this.photoUri = 'your-photo-path'; // 这里替换成真实的拍照结果
}
}
这个 Demo 把"权限检查 + 调用相机"串起来了,基本上能直接放到实际项目里使用。
应用场景举例
场景 1:定位权限
地图类应用需要定位权限。
ts
await atManager.requestPermissionsFromUser(this.context, ['ohos.permission.LOCATION']);
如果没有权限,就提示用户"无法获取位置,请开启定位权限"。
场景 2:存储权限
比如做一个文件上传功能,就要用 ohos.permission.WRITE_USER_STORAGE
。
ts
await atManager.requestPermissionsFromUser(this.context, ['ohos.permission.WRITE_USER_STORAGE']);
拒绝的话就提醒用户"需要存储权限才能上传文件"。
场景 3:麦克风权限
语音聊天应用需要用到麦克风。
ts
await atManager.requestPermissionsFromUser(this.context, ['ohos.permission.MICROPHONE']);
如果没有权限,就提示用户"请开启麦克风权限才能发语音"。
QA 常见问题
Q1:为什么我声明了权限,代码也写了,但是还是提示没有权限? A1:要确认你在 module.json5
里是否写对了权限名,同时还要检查是否在真机上运行(模拟器可能不支持某些权限)。
Q2:用户拒绝权限后还能再申请吗? A2:可以再次调用 requestPermissionsFromUser
,但如果用户多次拒绝,建议提示去设置里手动开启。
Q3:权限申请是不是所有场景都需要动态请求? A3:是的,敏感权限必须动态请求,否则即使写了配置也不会生效。
总结
在鸿蒙应用中,处理权限的步骤其实很固定:
在 module.json5
声明权限。 在代码里检查和动态申请。 根据用户的操作结果执行不同逻辑。
无论是相机、定位还是存储权限,套路都差不多。开发时建议把"检查权限"的逻辑单独封装成工具方法,方便在多个地方复用。