鸿蒙Qt权限避坑:动态申请与Crash修复
摘要:在鸿蒙系统开发Qt应用时,调用相机权限导致闪退,原因是未正确处理动态权限申请。鸿蒙的权限分为安装时授权(system_grant)和运行时授权(user_grant),相机权限属于后者,必须通过代码动态请求用户授权。解决方案包括:1)在ArkTS侧创建权限申请桥接;2)在C++层封装NAPI接口供Qt调用;3)正确处理异步授权回调;4)在module.json5中声明权限。关键点在于理解权限
1. 闪退的相机应用
我们编写了一个简单的Qt应用,点击按钮打开摄像头扫描二维码。
在模拟器上运行正常,但在真机上一点击按钮,应用瞬间闪退,没有任何Qt日志输出。
查看系统日志(HiLog),发现了一行关键错误:SecurityException: Permission denied. req: ohos.permission.CAMERA
2. 鸿蒙的权限模型:ACL与动态申请
OpenHarmony采用了类似于Android 6.0+的动态权限模型。
权限分为:
- system_grant (安装时授权):如网络权限。
- user_grant (运行时授权):如相机、麦克风、定位。
对于 user_grant 类型的权限,仅仅在 module.json5 中声明是不够的!必须在代码中动态请求用户授权。
权限状态机
3. 解决方案:Qt与ArkTS的配合
Qt本身(截至目前)并没有封装鸿蒙的权限申请API。我们需要通过NAPI调用鸿蒙的 abilityAccessCtrl。
第一步:ArkTS侧的桥接
我们在 EntryAbility.ets 或独立的TS模块中暴露一个申请权限的方法。
// PermissionBridge.ts
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import bundleManager from '@ohos.bundle.bundleManager';
export async function requestCameraPermission(context: any): Promise<boolean> {
const atManager = abilityAccessCtrl.createAtManager();
const result = await atManager.requestPermissionsFromUser(context, ['ohos.permission.CAMERA']);
// 检查授权结果
if (result.authResults[0] === 0) {
return true;
}
return false;
}
第二步:C++ NAPI封装
我们需要在C++层暴露一个函数给Qt调用,这个函数内部去调用上面的TS方法。
(这里为了简化,假设我们已经通过某种方式(如信号/槽或Native机制)建立好了通信通道)。
Qt侧调用封装:
// PermissionManager.cpp
void PermissionManager::requestCamera(std::function<void(bool)> callback) {
#ifdef Q_OS_OHOS
// 调用NAPI接口
// 伪代码:NativeInterface::call("requestCameraPermission", ...)
// 等待回调...
bool granted = waitForResult();
callback(granted);
#else
// Desktop always granted or handled by Qt Multimedia
callback(true);
#endif
}
第三步:使用 QtAndroidPrivate 的替代品?
在Android Qt开发中,我们有 QtAndroid::requestPermissions。
在鸿蒙上,目前没有官方等价类。我们推荐维护一个 HarmonyPermission 单例类,专门处理这些逻辑。
4. 实战Bug:异步陷阱
错误代码:
void onBtnClick() {
PermissionManager::requestCamera();
// ❌ 错误!请求是异步的,这里直接打开相机依然会崩溃
camera->start();
}
正确代码:
void onBtnClick() {
PermissionManager::instance()->requestCamera([this](bool granted) {
if (granted) {
// ✅ 在回调中启动,且最好切回主线程
QMetaObject::invokeMethod(this, [this](){
camera->start();
});
} else {
QMessageBox::warning(this, "Error", "Camera permission denied!");
}
});
}
5. 配置文件别忘了
在写代码之前,必须先在 entry/src/main/module.json5 中声明。
"requestPermissions": [
{
"name": "ohos.permission.CAMERA",
"reason": "$string:camera_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
]
注意:reason 字段必须指向一个字符串资源,不能直接写硬编码字符串,否则编译或安装会报错。
6. 总结
鸿蒙的权限管理非常严格。
- 查文档:确定权限是
system_grant还是user_grant。 - 写配置:
module.json5必不可少。 - 动态申请:对于敏感权限,必须在运行时调用
requestPermissionsFromUser。 - 异步处理:等待用户点选后再执行业务逻辑。
处理好权限问题,是应用上架华为应用市场的基本要求。
更多推荐

所有评论(0)