HarmonyOS 权限申请避坑:声明、弹窗、审核说明一次讲清 HarmonyOS 权限申请避坑声明、弹窗、审核说明一次讲清应用上架审核里权限问题很常见功能里确实需要定位但module.json5没声明清楚用户点击“附近门店”才需要定位应用却一启动就弹权限相册权限只是上传头像却在审核说明里写成“提升体验”。这些问题不一定是代码跑不通而是权限申请链路不完整。这篇文章只讲一件事HarmonyOS 应用申请权限时如何把业务场景、配置声明、运行时弹窗、拒绝处理和 AGC 审核说明串起来。一、资料定位权限不是只写一行配置类型资料/能力本文使用点官方权限文档访问控制开发概述权限类型、授权边界官方申请权限向用户申请授权运行时申请、授权结果处理官方配置module.json5 配置文件权限声明位置官方上架AppGallery Connect 提交审核审核资料、版本提交本文以 HarmonyOS 5.0.0、Stage 模型、ArkTS 为边界。示例围绕“附近路线推荐”功能只有用户点击附近路线时才申请定位权限。二、合规流程先有场景再申请权限权限申请按六步走确认业务场景。在配置里声明权限。给用户说明使用目的。在用户触发功能时运行时申请。处理拒绝和永久拒绝。上架前复查权限与功能是否一致。不要把权限申请写成“进入首页就弹”。这会让用户反感也容易被审核认为申请时机不合理。三、权限合规架构推荐目录entry/src/main/ets/ ├── pages/nearby/ │ └── NearbyRoutePage.ets ├── permission/ │ ├── PermissionReason.ets │ ├── PermissionGuard.ets │ └── DeniedHandler.ets └── service/location/ └── NearbyLocationService.ets文件职责module.json5声明应用会使用哪些权限PermissionReason管理给用户看的权限说明PermissionGuard执行检查和运行时申请DeniedHandler处理拒绝后的降级路径NearbyLocationService真正使用定位能力权限逻辑不要散落在每个按钮里。统一封装后上架前检查也更容易。四、先做权限清单能不用就不用能按需就按需功能权限申请时机拒绝后策略附近路线推荐位置权限点击“查看附近”手动选择城市扫码导入路线相机权限点击“扫码”输入路线码上传头像相册/媒体权限点击“更换头像”使用默认头像语音备注麦克风权限点击“录音”文本输入网络请求网络访问应用使用期间提示网络不可用这张表最好在开发前就写。它能避免两个问题申请了不用的权限或者用了权限却没说明业务场景。五、module.json5声明要准确不要贪多下面示例只声明“附近路线”需要的定位权限。具体权限名要以项目目标 API 和官方权限列表为准。{ module: { name: entry, type: entry, requestPermissions: [ { name: ohos.permission.LOCATION, reason: $string:permission_location_reason, usedScene: { abilities: [ EntryAbility ], when: inuse } } ] } }代码解释name必须和实际能力匹配不要把暂时不用的权限提前声明。reason要写给用户能理解的业务原因不要写“应用需要权限”。usedScene要和实际使用 Ability 对应。when表示使用场景具体取值以官方文档和权限类型要求为准。权限声明不是越全越保险。声明越多审核越会关注你是否真的需要。六、权限说明用户要知道为什么此刻申请exportinterfacePermissionReason{permission:string;title:string;message:string;fallback:string;}exportconstLOCATION_REASON:PermissionReason{permission:ohos.permission.LOCATION,title:需要定位权限,message:用于根据当前位置推荐附近路线不会在后台持续获取位置。,fallback:如果拒绝授权可以手动选择城市继续使用路线搜索。};代码解释message要讲业务场景不讲空话。fallback告诉用户拒绝后还能怎么用。不要承诺做不到的事比如“绝不收集任何信息”。权限说明和隐私政策里的描述要一致。如果用户点击“附近路线”此时弹出定位说明是合理的如果刚打开应用就弹用户很难理解。七、运行时申请用户触发功能后再弹importabilityAccessCtrl,{Permissions}fromohos.abilityAccessCtrl;importcommonfromohos.app.ability.common;exportclassPermissionGuard{privateatManagerabilityAccessCtrl.createAtManager();asyncensurePermission(context:common.UIAbilityContext,permission:Permissions):Promiseboolean{constgrantStatusawaitthis.atManager.checkAccessToken(context.applicationInfo.accessTokenId,permission);if(grantStatusabilityAccessCtrl.GrantStatus.PERMISSION_GRANTED){returntrue;}constresultawaitthis.atManager.requestPermissionsFromUser(context,[permission]);returnresult.authResults[0]abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;}}代码解释先检查授权状态已经授权就不重复弹窗。requestPermissionsFromUser()要在用户触发相关功能后调用。返回值只表达是否可继续执行不在这里写业务降级。权限类型使用Permissions减少字符串写错风险。真实项目里要根据 API 版本确认导入路径和返回结构。权限代码最怕复制旧版本示例后不复测。八、页面调用拒绝后也要有路可走EntryComponentstruct NearbyRoutePage{privatepermissionGuard:PermissionGuardnewPermissionGuard();Stateprivatemessage:string点击按钮查看附近路线;build(){Column({space:16}){Text(this.message).fontSize(18)Button(查看附近路线).onClick((){this.openNearbyRoutes();})Button(手动选择城市).onClick((){this.message已切换为手动城市选择模式;})}.padding(24)}privateasyncopenNearbyRoutes():Promisevoid{constcontextgetContext(this)ascommon.UIAbilityContext;constgrantedawaitthis.permissionGuard.ensurePermission(context,ohos.permission.LOCATION);if(!granted){this.message未授权定位可手动选择城市继续使用;return;}this.message正在获取附近路线...;}}代码解释权限申请发生在用户点击“查看附近路线”之后。拒绝后不阻断整个页面而是提供“手动选择城市”。页面只关心业务结果不关心权限底层细节。审核时能看出权限和功能存在明确对应关系。权限合规的一个核心点是“克制”。不是所有功能都必须拿权限也不是拒绝后就让用户寸步难行。九、拒绝处理不要循环弹窗exportclassDeniedHandler{staticbuildLocationDeniedTips():string{return定位权限未开启附近路线将无法自动推荐。你可以手动选择城市继续使用。;}staticshouldShowGuide(rejectCount:number):boolean{returnrejectCount1;}}代码解释拒绝后给出功能影响和替代方案。不要循环弹权限弹窗会严重影响体验。rejectCount可以存在本地用于控制引导频率。永久拒绝场景可以引导用户去系统设置但不要强迫。很多审核问题不是权限本身而是申请方式太激进。用户拒绝一次后应该尊重这个结果。十、AGC 审核说明怎么写权限审核说明建议写成“功能 时机 用途 拒绝后影响”。权限推荐说明定位用户点击“查看附近路线”时申请用于推荐当前位置附近路线拒绝后可手动选择城市相机用户点击“扫码导入路线”时申请用于扫描路线二维码拒绝后可手动输入路线码相册用户点击“更换头像/上传图片”时申请用于选择本地图片拒绝后使用默认图片麦克风用户点击“语音备注”时申请用于录制路线备注拒绝后可使用文字输入不要写这种说明为了提升用户体验需要申请定位权限。这句话太空审核人员看不出权限和功能的对应关系。十一、验证流程1. 首次安装应用进入首页确认不会立即弹定位权限。 2. 点击“查看附近路线”确认先出现合理说明或系统授权弹窗。 3. 点击拒绝确认页面提供手动选择城市方案。 4. 再次点击功能确认不会无限骚扰式弹窗。 5. 授权后进入功能确认定位能力只在对应功能里使用。 6. 检查隐私政策和 AGC 审核说明是否一致。建议保留测试截图截图用途权限触发入口证明不是启动即申请系统授权弹窗证明权限名和时机拒绝后的降级页面证明不强迫授权AGC 权限说明证明审核材料完整十二、常见问题排查现象可能原因检查方法修复建议审核说权限用途不清说明太泛查看 AGC 权限说明写清功能、时机、用途用户一进应用就被弹窗申请时机过早搜索启动生命周期移到用户触发后拒绝后功能崩溃没有降级路径拒绝权限测试提供手动输入或替代能力配置了权限但申请失败权限名或 usedScene 不匹配检查 module.json5对照官方权限文档隐私政策和弹窗不一致多处文案各写各的对比文案统一 PermissionReason十三、上架前验收清单检查项是否完成每个权限都有明确业务场景没有声明暂时不用的敏感权限权限申请发生在用户触发功能后拒绝权限后有可用降级方案权限说明、隐私政策、AGC 审核说明一致首次安装、拒绝、授权、系统设置关闭都测试过日志和埋点不记录敏感权限数据权限类问题建议在提交审核前单独做一轮“干净安装测试”。不要用已经授权过的开发机直接判断流程是否合规因为系统可能不会再次弹窗很多首次授权问题会被掩盖。测试时至少覆盖首次安装、拒绝一次、拒绝后再次点击、系统设置关闭权限、重新授权这几条路径。审核材料也要和代码同步更新。只要新增、删除或调整了敏感权限AGC 的权限说明、应用内弹窗说明、隐私政策都要一起检查。三处只要有一处说法不一致就可能被认为用途不清或告知不充分。十四、总结HarmonyOS 权限申请能否顺利通过审核不只看代码能不能调通更看整条链路是否合理业务确实需要。配置声明准确。用户触发后再申请。拒绝后有替代方案。审核说明写清楚。权限不是越多越强而是越克制越稳。把“为什么要申请、什么时候申请、拒绝怎么办”讲清楚上架风险会小很多。