鸿蒙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. 异步处理:等待用户点选后再执行业务逻辑。

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

相关推荐
人间打气筒(Ada)20 小时前
「码动四季·开源同行」HarmonyOS应用开发:常见组件
华为·开源·harmonyos·组件·布局·鸿蒙开发
三声三视21 小时前
ArkTS 自定义组件完全指南:@Builder、@Extend、@Styles 实战解析
华为·harmonyos
Utopia^1 天前
Flutter 框架跨平台鸿蒙开发 - 旅行预算管家
flutter·华为·harmonyos
freshman_y1 天前
Qtcreator怎么新建安卓项目?编写一个五子棋游戏APP?
android·qt
李李李勃谦1 天前
Flutter 框架跨平台鸿蒙开发 - 星空识别助手
flutter·华为·harmonyos
李李李勃谦1 天前
Flutter 框架跨平台鸿蒙开发 - 本地生活服务预约
flutter·华为·生活·harmonyos
我的世界洛天依1 天前
胡桃讲编程:早期华为手机(比如畅享等)可以升级鸿蒙吗?
华为·harmonyos
2301_822703201 天前
开源鸿蒙跨平台Flutter开发:幼儿疫苗全生命周期追踪系统:基于 Flutter 的免疫接种档案与状态机设计
算法·flutter·华为·开源·harmonyos·鸿蒙
2301_822703201 天前
鸿蒙flutter三方库实战——教育与学习平台:Flutter Markdown
学习·算法·flutter·华为·harmonyos·鸿蒙
humors2211 天前
各厂商工具包网址
java·数据库·python·华为·sdk·苹果·工具包