鸿蒙应用权限处理全攻略:从配置到相机拍照,一篇文章讲透

摘要

在做鸿蒙(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 声明权限。 在代码里检查和动态申请。 根据用户的操作结果执行不同逻辑。

无论是相机、定位还是存储权限,套路都差不多。开发时建议把"检查权限"的逻辑单独封装成工具方法,方便在多个地方复用。

相关推荐
HarderCoder1 天前
使用仓颉语言理解 SOLID 原则:概念、实战与踩坑总结
harmonyos
爱笑的眼睛111 天前
HarmonyOS 应用开发深度解析:ArkTS 声明式 UI 与状态管理最佳实践
华为·harmonyos
安卓开发者1 天前
鸿蒙Next ArkWeb进程解析:多进程架构如何提升Web体验
前端·架构·harmonyos
damo王1 天前
鸿蒙(HarmonyOS) 历史
华为·harmonyos
爱笑的眼睛111 天前
HarmonyOS声明式UI开发:深入ArkUI与状态管理实践
华为·harmonyos
爱笑的眼睛111 天前
HarmonyOS 应用开发进阶:深入 Stage 模型与 ArkUI 声明式开发实践
华为·harmonyos
2501_919749031 天前
鸿蒙:更改状态栏、导航栏颜色
华为·harmonyos
2501_919749031 天前
鸿蒙:@Builder 和 @BuilderParam正确使用方法
华为·harmonyos
爱笑的眼睛111 天前
HarmonyOS应用开发:深入解析Stage模型与UIAbility
华为·harmonyos
HMSCore1 天前
Cloud Foundation Kit启动预加载,赋能喜马拉雅秒启秒开流畅体验
harmonyos