鸿蒙权限声明体系 — INTERNET / PUBLISH_AGENT_REMINDER 等权限的合理使用
文章简介
HarmonyOS 的应用权限体系是保障用户隐私和应用安全的核心机制。MoneyTrack 作为一款联网记账应用,需要在 module.json5 中声明多项权限,包括网络访问权限(INTERNET)、代理提醒权限(PUBLISH_AGENT_REMINDER)等。本文详细解析鸿蒙权限体系的分类(system_grant / user_grant)、声明方式、运行时权限请求以及权限被拒绝时的降级处理策略。
核心知识点
1. 权限声明到运行时请求的完整流程
从开发者在 module.json5 中声明权限,到系统在运行时请求用户授权,经历了以下完整链路:
2. system_grant 与 user_grant 完整对比表
鸿蒙权限体系将权限分为 system_grant(系统授权)和 user_grant(用户授权)两大类,理解二者的区别至关重要:
| 对比维度 | system_grant | user_grant |
|---|---|---|
| 授予时机 | 应用安装时自动授予 | 运行时动态请求 |
| 用户交互 | 无需用户参与 | 需弹窗征得用户同意 |
| 可撤销性 | 无法单独撤销,卸载即移除 | 用户可随时在设置中关闭 |
| 典型权限 | INTERNET、PUBLISH_AGENT_REMINDER | 位置信息、相机、麦克风 |
| 风险等级 | 低风险,不涉及敏感数据 | 高风险,涉及用户隐私 |
| 声明要求 | 声明即可,无需 reason | 必须提供 reason 说明用途 |
| 代码要求 | 仅声明,无需运行时请求 | 声明 + 运行时请求 + 降级处理 |
3. 运行时权限请求完整代码
对于 user_grant 类权限,除了在module.json5中声明外,还需在运行时主动请求授权:
import { common } from '@kit.AbilityKit'; import { abilityAccessCtrl } from '@kit.AbilityKit'; async function requestPermission(context: common.UIAbilityContext): Promise<void> { const atManager = abilityAccessCtrl.createAtManager(); const permissions: Array<string> = [ 'ohos.permission.LOCATION', // 示例 user_grant 权限 'ohos.permission.CAMERA', ]; try { const grantResults: Array<number> = await atManager.requestPermissionsFromUser( context, permissions ); const allGranted = grantResults.every( result => result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED ); if (allGranted) { hilog.info(0xFF00, 'Permission', '所有权限已授予'); } else { hilog.warn(0xFF00, 'Permission', '部分权限被拒绝'); handlePermissionDenied(); } } catch (err) { hilog.error(0xFF00, 'Permission', `权限请求异常: ${JSON.stringify(err)}`); } }4. 权限被拒绝的降级处理
用户拒绝授权时,应用不能直接崩溃或闪退,必须提供合理的降级体验。鸿蒙推荐以下处理策略:
- 功能不可用提示:不允许使用该功能时,展示功能不可用的友好提示,而非报错。例如,拒绝位置权限时,手动输入地址作为替代方案。
- 二次申请引导:首次被拒后,下次触发同一功能时再次申请。若用户选择「不再询问」,引导用户前往系统设置手动开启。
- 不影响核心功能:敏感权限(如位置)被拒不应影响应用的核心功能(如记账)。核心功能应尽量不依赖 user_grant 权限。
function handlePermissionDenied(): void { AlertDialog.show({ title: '权限被拒绝', message: '部分功能需要相关权限才能使用。您可以在系统设置中重新开启。', primaryButton: { value: '去设置', action: () => { context.startAbility({ bundleName: 'com.huawei.hmos.settings', abilityName: 'com.huawei.hmos.settings.MainAbility', }); }, }, secondaryButton: { value: '知道了', action: () => { /* 不做操作 */ }, }, }); }5. 权限最佳实践
- 最小权限原则:只申请应用功能真正需要的权限,不提前申请、不超范围申请。
- 按需申请:在用户实际触发需要权限的功能时才申请,而非应用启动时一次性申请所有权限。
- 说明用途:声明 user_grant 权限时,必须在
reason字段中详细说明用途,并在弹窗中清晰展示。 - 权限检查前置:每次调用敏感 API 前检查权限状态,避免因权限被撤销导致运行时异常。
- 测试覆盖:在测试环境中覆盖权限被拒、权限关闭等多种场景,确保降级体验完整。
项目代码案例
网络权限 + 代理提醒权限的声明配置
在 MoneyTrack 中,各模块的module.json5均声明了INTERNET权限用于网络通信。PUBLISH_AGENT_REMINDER权限用于发送预算超支等提醒通知。
文件路径示例:
commons/lib_network/src/main/module.json5products/entry/src/main/module.json5features/home/src/main/module.json5
在 HomeVM 中,预算超支时调用notificationManager发送通知,依赖于PUBLISH_AGENT_REMINDER权限:
const request: notificationManager.NotificationRequest = { id: 1001, content: { notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, // ... }, };推荐参考文档
- HarmonyOS 权限开发指南(安全章节)
- module.json5 配置文件规范
- notificationManager 通知 API 文档
- abilityAccessCtrl 权限管理 API 参考