res.authsetting 的值表示权限三态:undefined(未询问)、false(已拒绝)、true(已授权);需据此决定是否调用 uni.authorize 或 uni.opensetting。

uni.getSetting 检查权限状态时,res.authSetting 的值到底代表什么
调用 uni.getSetting 后,success 回调里的 res.authSetting 是个对象,键是权限 scope(如 'scope.writePhotosAlbum'),值只有三种可能:true、false、undefined。这不是布尔判断题,而是三态状态机:undefined 表示“用户还没见过这个弹窗”,false 表示“用户点过‘拒绝’”,true 表示“已授权”。很多人误把 false 当成“未授权”,结果在 false 状态下还反复调 uni.authorize,白跑一遍——它不会弹窗,直接进 fail 回调。
常见错误现象:点击上传图片按钮后毫无反应,控制台也没报错。实际是 uni.authorize({ scope: 'scope.writePhotosAlbum' }) 在 false 状态下静默失败,没走任何回调分支。
- 必须先检查
res.authSetting['scope.writePhotosAlbum'] === undefined,才可安全调用uni.authorize -
false时应跳过authorize,直接准备uni.openSetting引导 - iOS 和 Android 对
scope字符串大小写敏感,务必严格对照文档写,比如相册是scope.writePhotosAlbum,不是scope.photos或scope.photoAlbum
用户点“拒绝”后,uni.authorize 不再弹窗,该怎么补救
这是 uni-app 权限流程里最常被忽略的断点。平台规则决定:只要用户对某个 scope 点过一次“拒绝”,后续所有 uni.authorize 调用都会跳过弹窗,直接触发 fail 回调。此时唯一合法出口是 uni.openSetting —— 它会唤起系统设置页,定位到当前应用的权限开关。
但注意:uni.openSetting 在微信小程序里不支持跳转到具体权限项,只打开通用设置页;而 App 端(iOS/Android)可以精准跳转,前提是 manifest.json 已正确声明该权限。
- 必须在
uni.authorize的fail回调里判断是否因拒绝导致失败,不能只靠err.errMsg字符串匹配,应结合前置的getSetting状态做双重确认 - 调用
uni.openSetting前建议加一层uni.showModal提示,说明“需手动开启相册权限”,否则用户看到空白设置页容易困惑 - Android 端若 manifest.json 中未声明
android.permission.WRITE_EXTERNAL_STORAGE(App 端)或未勾选“存储权限”,uni.openSetting可能无法显示对应开关,导致引导失效
manifest.json 权限配置和运行时申请,哪个漏了都会失败
manifest.json 不是摆设。它相当于向操作系统提交的“能力说明书”。如果这里没声明,App 打包后在 Android/iOS 上根本无法获得对应权限入口,uni.openSetting 打开的设置页里压根不显示该开关,用户无从开启。而小程序端虽不依赖 manifest.json,但需在 project.config.json 或 app.json 中补充声明(uni-app 会自动映射)。
典型场景:iOS 提交审核被拒,提示“相册权限描述缺失”。原因往往是 manifest.json 中 app-plus.distribute.apple.permissions.photos.description 字段为空或未配置。
- App 端必须在 manifest.json 的
app-plus.distribute.apple.permissions(iOS)和app-plus.distribute.android.permissions(Android)下分别配置,且description字段不能为空字符串 - 微信小程序需确保
mp-weixin下的permission配置已同步,uni-app 2.9+ 版本会自动处理,但老项目要手动检查 - 修改 manifest.json 后必须重新打包(非热更新),否则新配置不生效
要不要封装一个权限管理工具函数?别直接封装 uni.authorize
直接封装 uni.authorize 是常见误区。它只是流程一环,单独拎出来意义不大。真正需要封装的是“检测 → 尝试申请 → 拒绝引导 → 状态缓存”的完整链路。比如一个 requestAlbumPermission() 函数,内部应包含:getSetting 查询、authorize 触发、fail 中调 showModal + openSetting、以及成功后本地记录状态避免重复请求。
更关键的是缓存策略:用户授权后,下次进入页面前可先读取本地缓存的状态,跳过一次 getSetting 调用(减少 IO 开销)。但要注意,用户可能在系统设置里手动关闭权限,所以不能完全依赖缓存,首次操作仍建议走完整检测。
- 不要在工具函数里硬编码
scope字符串,应作为参数传入,保持复用性 - 失败回调中避免无限递归调用自身,防止用户连续点两次按钮触发两次
openSetting - 涉及多端时,函数内部需用
uni.getSystemInfoSync().platform区分环境,比如 iOS 的相册权限文案和 Android 的提示语应略有差异
权限引导真正的复杂点不在代码行数,而在状态跃迁的完整性——你得覆盖从“未询问”到“已授权”,再到“已拒绝→手动开启→重新检测”的全路径。少任何一个环节,用户卡在某一步就再也进不去了。尤其是 undefined 和 false 的区分,几乎决定了整个流程能否闭环。











