鸿蒙Qt权限避坑:动态申请与Crash修复

1. 闪退的相机应用

我们编写了一个简单的Qt应用,点击按钮打开摄像头扫描二维码。

在模拟器上运行正常,但在真机上一点击按钮,应用瞬间闪退,没有任何Qt日志输出。

查看系统日志(HiLog),发现了一行关键错误:
SecurityException: Permission denied. req: ohos.permission.CAMERA

2. 鸿蒙的权限模型:ACL与动态申请

OpenHarmony采用了类似于Android 6.0+的动态权限模型。

权限分为:

  1. system_grant (安装时授权):如网络权限。
  2. user_grant (运行时授权):如相机、麦克风、定位。

对于 user_grant 类型的权限,仅仅在 module.json5 中声明是不够的!必须在代码中动态请求用户授权。

权限状态机

API returns 0 API returns -1 Call requestPermissionsFromUser System Popup User Clicks Allow User Clicks Deny Open Camera UI Tip CheckStatus Granted NotGranted RequestPermission UserDialog Denied UseFeature ShowExplanation

3. 解决方案:Qt与ArkTS的配合

Qt本身(截至目前)并没有封装鸿蒙的权限申请API。我们需要通过NAPI调用鸿蒙的 abilityAccessCtrl

第一步:ArkTS侧的桥接

我们在 EntryAbility.ets 或独立的TS模块中暴露一个申请权限的方法。

typescript 复制代码
// 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侧调用封装:

cpp 复制代码
// 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:异步陷阱

错误代码:

cpp 复制代码
void onBtnClick() {
    PermissionManager::requestCamera(); 
    // ❌ 错误!请求是异步的,这里直接打开相机依然会崩溃
    camera->start(); 
}

正确代码:

cpp 复制代码
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 中声明。

json 复制代码
"requestPermissions": [
  {
    "name": "ohos.permission.CAMERA",
    "reason": "$string:camera_reason",
    "usedScene": {
      "abilities": ["EntryAbility"],
      "when": "inuse"
    }
  }
]

注意:reason 字段必须指向一个字符串资源,不能直接写硬编码字符串,否则编译或安装会报错。

6. 总结

鸿蒙的权限管理非常严格。

  1. 查文档 :确定权限是 system_grant 还是 user_grant
  2. 写配置module.json5 必不可少。
  3. 动态申请 :对于敏感权限,必须在运行时调用 requestPermissionsFromUser
  4. 异步处理:等待用户点选后再执行业务逻辑。

处理好权限问题,是应用上架华为应用市场的基本要求。

相关推荐
anyup1 小时前
2026第一站:分享我在高德大赛现场学到的技术、产品与心得
前端·架构·harmonyos
anyup2 小时前
从赛场到产品:分享我在高德大赛现场学到的技术、产品与心得
前端·harmonyos·产品
小温冲冲2 小时前
QtObject 详解:QML 中的轻量级数据容器
qt
huwei8533 小时前
Q打印表格内容类
开发语言·qt
Van_Moonlight3 小时前
RN for OpenHarmony 实战 TodoList 项目:顶部导航栏
javascript·开源·harmonyos
Swift社区3 小时前
H5 与 ArkTS 通信的完整设计模型
uni-app·harmonyos
程序猿追5 小时前
【鸿蒙PC桌面端实战】从零构建 ArkTS 高性能图像展示器:DevEco Studio 调试与 HDC 命令行验证全流程
华为·harmonyos
前端世界6 小时前
设备找不到、Ability 启不动?一次讲清 DevEco Studio 调试鸿蒙分布式应用
华为·harmonyos
行者967 小时前
OpenHarmony上Flutter粒子效果组件的深度适配与实践
flutter·交互·harmonyos·鸿蒙
小溪彼岸7 小时前
uni-app小白从0开发一款鸿蒙Next应用到上线
uni-app·harmonyos