文章目录
- 前言
- 第一步:在 module.json5 声明
- 代码实现
- 第二步:判断当前是否已授权
- 核心代码
- 第三步:动态申请(弹窗)
- 完整示例
- 完整流程串起来
- 常见权限对照
- 常见误区(小白必踩)
- 完整可运行示例:动态权限申请
- 代码解析
- 写在最后
前言
HarmonyOS 对用户隐私管得很严,这其实是好事。但对你开发来说意味着:要用摄像头、定位、通讯录,光在代码里调 API 不够,得走一套"声明 + 动态申请"的流程。
我见过太多新手卡在"为啥调相机没反应"——答案几乎都是没申请权限。这篇文章把权限全流程讲透,从配置文件到运行时弹窗,一步不漏。
第一步:在 module.json5 声明
任何权限,先在配置里"报备"你要用。以定位为例:
代码实现
"requestPermissions": [ { "name": "ohos.permission.LOCATION", "reason": "$string:location_reason", "usedScene": { "abilities": ["EntryAbility"], "when": "inuse" } } ]name:权限常量,必须拼对。reason:给用户看的理由,写在string.json里,说清楚"为什么需要"。when: "inuse":仅使用时申请,比always对用户更友好,上架也更容易过。
不声明就调用,系统直接拒绝,连弹窗都没有。声明是前提。
第二步:判断当前是否已授权
运行时先查一下,已授权就直接干,没授权再弹窗。用abilityAccessCtrl:
核心代码
import{abilityAccessCtrl}from'@kit.AbilityKit'asyncfunctioncheckPermission(perm:string):Promise<boolean>{constcontext=getContext()constatManager=abilityAccessCtrl.createAtManager()conststatus=awaitatManager.checkAccessToken(context.applicationInfo.accessTokenId,perm)returnstatus===abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED}checkAccessToken返回"已授权"或"未授权"。先查再申请,避免每次都弹窗烦用户。
第三步:动态申请(弹窗)
没授权就调requestPermissionsFromUser弹系统授权框:
完整示例
asyncfunctionrequestPermission(perm:string):Promise<boolean>{constatManager=abilityAccessCtrl.createAtManager()constresult=awaitatManager.requestPermissionsFromUser(getContext(),[perm]// 可以一次申请多个)// result.authResults[0] === 0 表示用户同意returnresult.authResults[0]===0}- 传入权限数组,可批量申请。
authResults[0] === 0代表用户点了"允许"。非 0 就是拒绝了。
完整流程串起来
asyncfunctiondoWithLocation(){constperm='ohos.permission.LOCATION'if(awaitcheckPermission(perm)){startLocate()// 已授权,直接干活return}if(awaitrequestPermission(perm)){startLocate()// 刚授权,干活}else{promptAction.showToast({message:'定位权限被拒绝,功能不可用'})}}先查、后申请、再判断结果——这就是标准的"声明→检查→申请→使用"四步。少一步都会出问题。
常见权限对照
| 权限 | 常量 | 典型用途 |
|---|---|---|
| 定位 | ohos.permission.LOCATION | 地图、附近的人 |
| 相机 | ohos.permission.CAMERA | 拍照、扫码 |
| 麦克风 | ohos.permission.MICROPHONE | 录音、语音 |
| 相册读取 | ohos.permission.READ_MEDIA | 选图 |
| 网络 | ohos.permission.INTERNET | 所有联网 |
常见误区(小白必踩)
| 误区 | 说明 |
|---|---|
| 不声明就调用 API | 没在配置里报备权限,系统直接拒绝,连弹窗都没有。声明是前提。 |
| 一上来就弹窗 | 应该先checkAccessToken再看是否申请,别每次都弹,烦用户。 |
| 拒绝不提示 | 用户拒了权限要友好说明功能不可用,而不是默默失灵让用户猜。 |
下面这段代码可以直接复制到 DevEco Studio 里运行。建议你边读边敲,改一改文末「动手改一改」里的参数,亲眼看看效果。
完整可运行示例:动态权限申请
声明 + 运行时弹窗授权,拿「相机」权限做例子。
代码解析
// 运行时动态申请权限import{abilityAccessCtrl}from'@kit.AbilityKit'@Entry@Componentstruct PermDemo{@Stategranted:boolean=falsebuild(){Column({space:16}){Text(this.granted?'已授权':'未授权').fontSize(20)Button('申请相机权限').onClick(async()=>{constatManager=abilityAccessCtrl.createAtManager()constresult=awaitatManager.requestPermissionsFromUser(getContext(),['ohos.permission.CAMERA'])this.granted=result.authResults[0]===0// 0=允许})}.padding(20)}}你会看到什么:点按钮弹出系统授权框,点「允许」后文字变「已授权」;点「拒绝」则保持未授权。记住:权限必须先在module.json5的requestPermissions声明,否则这里直接失败。
动手改一改:
- 把
['ohos.permission.CAMERA']改成多个权限数组,一次申请多个。 - 在
module.json5删掉 CAMERA 声明再跑,观察报错,理解「声明是前提」。 - 用
verifyAccessToken先做「已授权就不弹窗」的短路判断,优化体验。
写在最后
权限流程记住四步:配文件声明 → 运行时检查 → 弹窗申请 → 按结果处理。永远先check再request,别一上来就弹窗;拒绝后要给用户友好提示,而不是默默失灵。
把这套封装成一个PermissionUtil.doWith(perm, action)工具,全项目复用——你以后写任何需要权限的功能,一行调用就完事。