App端权限必须分两层处理:manifest.json静态声明+运行时动态检查与引导;只做其一,90%概率真机失败,因Android/iOS均要求安装包层面提前声明权限,否则系统不认请求。

App端权限必须分两层处理:manifest.json静态声明 + 运行时动态检查与引导。只做其中一层,90%概率在真机上失败。
manifest.json里权限没配对,uni.authorize直接静默失败
Android 和 iOS 都要求权限在安装包层面提前声明,否则系统根本不认这个请求。很多人在代码里调 uni.authorize({scope: 'camera'}) 却没反应,第一反应是 API 写错了,其实八成是 manifest 没配。
- Android 权限名必须写全称字符串,比如
"android.permission.CAMERA",不能漏android.permission.前缀 - iOS 不需要写权限字符串,但必须在
app-plus.distribute.apple.permissions下配置带description的对象,例如:{"camera": {"description": "用于扫码和拍照"}} - HBuilderX 可视化勾选只是快捷方式,最终仍会转成上述 JSON 结构;但如果你手动改源码,记得改完要重新「发行」或「云打包」才生效
- 常见踩坑:把
WRITE_EXTERNAL_STORAGE当成 iOS 权限加进 apple 节点——iOS 会忽略,但 Android 打包时若没同步声明,就真没权限
运行时用 uni.getSetting 判断状态,别依赖 uni.authorize 的 success/fail
uni.authorize 只在用户从未选择过该权限时弹窗;一旦拒绝过,再调它只会进 fail 回调,且不会重弹。所以你不能靠它来“探测”当前是否可用,而要用 uni.getSetting 先看 res.authSetting['scope.xxx'] 的值。
-
undefined:用户还没被问过,可以安全调uni.authorize -
true:已授权,直接用对应 API(如uni.chooseImage) -
false:明确拒绝过,此时必须走uni.openSetting引导,不能再试uni.authorize - 注意:iOS 的
uni.openSetting只能跳到 App 主设置页,无法直达具体开关项;Android 可跳到权限详情页,但部分厂商(如华为、小米)可能拦截或跳转异常,需做好兜底提示
uni.openSetting 必须在拒绝后触发,不能预调用
很多开发者图省事,在页面 onLoad 里直接调 uni.openSetting(),结果 iOS 静默无反应,Android 可能闪退。这是因为系统要求:只有当用户明确拒绝过权限后,uni.openSetting 才被允许激活。
- 正确流程是:调
uni.authorize→ 进fail→ 立即调uni.getSetting确认authSetting['scope.xxx'] === false→ 再调uni.openSetting - 不要在
onShow或定时器里反复尝试跳转,用户没拒绝前调它无效,还可能触发平台风控 - 跳转后必须监听页面
onShow,重新执行权限检查并更新 UI,否则用户开完权限返回,界面仍是“未授权”状态
最易被忽略的点是:iOS 和 Android 对「永久拒绝」的判定逻辑不同。Android 有 deniedAlways 明确标识,而 iOS 没有等价字段,只能靠 getSetting 返回 false + 用户历史行为推断。这意味着,你在 iOS 上无法区分「第一次拒绝」和「永久拒绝」,所有 false 都得按永久拒绝处理——引导设置页,且不再主动申请。


















