简介

在HarmonyOS应用开发中,权限管理是保障用户隐私和系统安全的重要机制。应用需要通过在module.json5文件中声明所需权限,并在运行时申请用户授权才能访问受保护的系统功能和用户数据。本教程将详细介绍如何在HarmonyOS应用中配置和管理权限。

项目源码地址

项目源码已发布到GitCode平台, 方便开发者进行下载和使用。
harmonyOSAvatar

项目效果演示

主页面效果如下:

侧边栏效果如下

module.json5中的权限配置

在HarmonyOS的Stage模型中,权限配置位于module.json5文件的requestPermissions字段中。每个权限项包含权限名称、申请理由以及使用场景等信息。

权限配置结构

"requestPermissions": [
    {
        "name": "权限名称",
        "reason": "申请理由",
        "usedScene": {
            "abilities": [
                "使用该权限的Ability名称"
            ],
            "when": "使用时机"
        }
    }
]

权限配置参数说明

  • name: 权限的唯一标识符,以ohos.permission.开头
  • reason: 申请权限的理由,通常使用字符串资源引用格式$string:reason_name
  • usedScene: 权限的使用场景

    • abilities: 使用该权限的Ability列表
    • when: 权限使用时机,可选值:

      • inuse: 仅当应用在前台使用时需要该权限
      • always: 应用在前台和后台都可能需要该权限

项目中的权限配置示例

以下是当前项目中module.json5文件中配置的权限示例:

      "requestPermissions": [
          {
              "name": 'ohos.permission.INTERNET',
              "reason": "$string:Internet"
          }, {
              "name": "ohos.permission.READ_MEDIA",
              "reason": "$string:module_desc",
              "usedScene": {
                  "abilities": [
                      "EntryAbility"
                  ],
                  "when": "inuse"
              }
          },
          {
              "name": "ohos.permission.WRITE_IMAGEVIDEO",
              "reason": "$string:module_desc",
              "usedScene": {
                  "abilities": [
                      "EntryAbility"
                  ],
                  "when": "always"
              }
          },
          {
              "name": "ohos.permission.READ_IMAGEVIDEO",
              "reason": "$string:module_desc",
              "usedScene": {
                  "abilities": [
                      "EntryAbility"
                  ],
                  "when": "always"
              }
          }

      ]

常用权限说明

1. 网络权限

{
    "name": "ohos.permission.INTERNET",
    "reason": "$string:Internet"
}

用途:允许应用程序访问网络,进行网络通信。

注意:网络权限是基本权限,不需要配置usedScene字段。

2. 媒体读取权限

{
    "name": "ohos.permission.READ_MEDIA",
    "reason": "$string:module_desc",
    "usedScene": {
        "abilities": [
            "EntryAbility"
        ],
        "when": "inuse"
    }
}

用途:允许应用程序读取用户的媒体文件,如图片、音频和视频。

使用时机inuse表示仅当应用在前台使用时需要该权限。

3. 图片视频写入权限

{
    "name": "ohos.permission.WRITE_IMAGEVIDEO",
    "reason": "$string:module_desc",
    "usedScene": {
        "abilities": [
            "EntryAbility"
        ],
        "when": "always"
    }
}

用途:允许应用程序写入图片和视频文件。

使用时机always表示应用在前台和后台都可能需要该权限。

4. 图片视频读取权限

{
    "name": "ohos.permission.READ_IMAGEVIDEO",
    "reason": "$string:module_desc",
    "usedScene": {
        "abilities": [
            "EntryAbility"
        ],
        "when": "always"
    }
}

用途:允许应用程序读取图片和视频文件。

使用时机always表示应用在前台和后台都可能需要该权限。

权限申请最佳实践

1. 权限申请理由

为每个权限提供清晰、具体的申请理由,帮助用户理解为什么应用需要这些权限。理由应该:

  • 简洁明了地说明权限用途
  • 解释不授予权限可能带来的功能限制
  • 使用字符串资源引用,支持多语言

2. 最小权限原则

  • 只申请应用功能必需的权限
  • 优先使用inuse而非always,除非功能确实需要后台访问
  • 考虑使用替代方案,减少敏感权限的使用

3. 运行时权限申请

对于需要用户确认的权限,需要在代码中进行运行时申请。以下是一个基本示例:

import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import { BusinessError } from '@ohos.base';

export default class EntryAbility extends UIAbility {
  onCreate() {
    // 创建权限管理对象
    let atManager = abilityAccessCtrl.createAtManager();
    // 定义需要申请的权限列表
    let permissions: Array<string> = [
      'ohos.permission.READ_MEDIA',
      'ohos.permission.MEDIA_LOCATION'
    ];
    
    // 向用户申请权限
    atManager.requestPermissionsFromUser(this.context, permissions)
      .then((data) => {
        // 权限申请成功的处理逻辑
        console.info('权限申请成功');
      })
      .catch((err: BusinessError) => {
        // 权限申请失败的处理逻辑
        console.error(`权限申请失败,错误码:${err.code},错误信息:${err.message}`);
      });
  }
}

4. 实际项目中的权限申请实现

下面是本项目中EntryAbility.ets文件中实际的权限申请代码实现和详细解析:

import abilityAccessCtrl, { PermissionRequestResult, Permissions } from '@ohos.abilityAccessCtrl';

// 定义日志域,用于日志分类
const DOMAIN = 0x0000;

export default class EntryAbility extends UIAbility {
    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
        // 设置应用颜色模式
        this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
        // 记录Ability创建日志
        hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
        
        // 创建权限管理器实例
        let AtManager = abilityAccessCtrl.createAtManager();
        
        // 向用户申请READ_MEDIA和MEDIA_LOCATION权限
        // 这两个权限在module.json5中已经声明
        AtManager.requestPermissionsFromUser(this.context, ['ohos.permission.READ_MEDIA' ])
            .then((data: PermissionRequestResult) => {
                // 权限申请成功回调,记录成功日志和权限授权结果
                hilog.info(0x0000, 'testTag', '%{public}s', 'request permissions from user success' + JSON.stringify(data));
            })
            .catch((err: Object) => {
                // 权限申请失败回调,记录错误日志
                hilog.error(0x0000, 'testTag', 'Failed to request permissions from user. Cause: %{public}s', JSON.stringify(err) ?? '');
            });
    }
}

权限申请代码详解

  1. 导入权限相关模块

    import abilityAccessCtrl, { PermissionRequestResult, Permissions } from '@ohos.abilityAccessCtrl';
    • abilityAccessCtrl:权限访问控制模块,提供权限管理功能
    • PermissionRequestResult:权限请求结果的类型定义
    • Permissions:权限相关的枚举类型
  2. 创建权限管理器

    let AtManager = abilityAccessCtrl.createAtManager();

    通过createAtManager()方法创建权限管理器实例,用于后续的权限申请操作。

  3. 申请权限

    AtManager.requestPermissionsFromUser(this.context, ['ohos.permission.READ_MEDIA' ])
    • 第一个参数this.context:当前Ability的上下文,权限管理器需要此上下文来显示权限请求对话框
    • 第二个参数:包含需要申请的权限名称的字符串数组
  4. 处理权限申请结果

    .then((data: PermissionRequestResult) => {
        hilog.info(0x0000, 'testTag', '%{public}s', 'request permissions from user success' + JSON.stringify(data));
    })
    • 使用Promise的then方法处理权限申请成功的情况
    • data参数包含权限申请的结果,包括每个权限的授权状态
    • 使用hilog.info记录成功日志,便于调试
  5. 处理权限申请错误

    .catch((err: Object) => {
        hilog.error(0x0000, 'testTag', 'Failed to request permissions from user. Cause: %{public}s', JSON.stringify(err) ?? '');
    });
    • 使用Promise的catch方法处理权限申请失败的情况
    • err参数包含错误信息
    • 使用hilog.error记录错误日志,便于排查问题

权限申请结果解析

权限申请结果PermissionRequestResult是一个对象,包含以下信息:

interface PermissionRequestResult {
    permissions: Array<string>;  // 申请的权限列表
    authResults: Array<number>;  // 对应权限的授权结果
}

其中authResults数组中的每个元素对应permissions数组中同索引位置的权限授权结果,可能的值有:

  • 0:表示权限被授予
  • -1:表示权限被拒绝

最佳实践建议

  1. 权限申请时机:在需要使用权限的功能之前申请权限,通常在onCreate生命周期中进行
  2. 权限结果处理:根据权限申请结果调整应用行为,如果权限被拒绝,应提供替代功能或友好提示
  3. 错误处理:完善的错误处理机制,确保应用在权限申请失败时不会崩溃
  4. 日志记录:使用hilog等工具记录权限申请过程,便于调试和问题排查

5. 权限检查

在使用需要权限的功能前,应先检查是否已获得权限:

import abilityAccessCtrl from '@ohos.abilityAccessCtrl';

// 检查是否有读取媒体的权限
let atManager = abilityAccessCtrl.createAtManager();
let result = await atManager.checkAccessToken(this.context.getApplicationInfo().accessTokenId, 'ohos.permission.READ_MEDIA');

if (result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
  // 有权限,执行相关操作
} else {
  // 无权限,提示用户或申请权限
}

常见问题

1. 权限被拒绝怎么办?

  • 提供清晰的解释,说明为什么应用需要该权限
  • 提供替代功能或优雅降级的用户体验
  • 在适当的时机再次请求权限,但避免频繁打扰用户

2. 权限配置错误的常见问题

  • 权限名称拼写错误
  • 缺少必要的usedScene配置
  • 权限理由未使用字符串资源引用
  • 权限理由不够具体或不符合应用商店审核要求

总结

正确配置和申请权限是HarmonyOS应用开发的重要环节。通过在module.json5文件中声明所需权限,并在代码中实现运行时权限申请和检查,可以确保应用在访问受保护资源时符合系统安全要求和用户隐私期望。

遵循最小权限原则,只申请应用功能必需的权限,并为每个权限提供清晰的申请理由,有助于提高用户对应用的信任度和应用商店的审核通过率。


全栈若城
1 声望2 粉丝