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

摘要

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

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

相关推荐
zhanshuo3 小时前
HarmonyOS 实战:学会在鸿蒙中使用第三方 JavaScript 库(附完整 Demo)
harmonyos
AlbertZein5 小时前
HarmonyOS5 凭什么学鸿蒙—— GetContext
架构·harmonyos
森之鸟8 小时前
flutter项目适配鸿蒙
flutter·华为·harmonyos
奶糖不太甜10 小时前
鸿蒙图片资源加载全攻略:从基础到性能优化
harmonyos·图片资源
小小小小小星10 小时前
鸿蒙多端适配开发指南:从入门到实战
harmonyos
鸿蒙小灰10 小时前
鸿蒙开发之仿抖音APP教程:方法论与技术探索
harmonyos
CC__xy10 小时前
04 类型别名type + 检测数据类型(typeof+instanceof) + 空安全+剩余和展开(运算符 ...)简单类型和复杂类型 + 模块化
开发语言·javascript·harmonyos·鸿蒙
鸿蒙先行者10 小时前
鸿蒙开发ArkUI框架布局与适配难题丛生之响应式布局实现艰难
harmonyos·arkui
ajassi200011 小时前
开源 Arkts 鸿蒙应用 开发(十七)通讯--http多文件下载
华为·开源·harmonyos