uni-app 全量权限:统一别名、归一状态与多端分流

发布时间:2026/8/5 8:36:20
uni-app 全量权限:统一别名、归一状态与多端分流 uni-app 全量权限统一别名、归一状态与多端分流插件lf-permission1.0.0地址https://ext.dcloud.net.cn/plugin?id29096业务场景相机、定位、相册、通知、悬浮窗等权限在 Android、iOS、鸿蒙、小程序、H5 上检测与申请方式不同。本文说明别名表、状态机、各端实现、用法与真机问题。需求三类能力检测只读check不弹系统授权框申请request/requestMany特殊权限跳转设置页组合ensure 检测 → 申请 → 按需打开设置 → 再检测主 APIcheck(permission)request(permission)requestMany(permissions,{stopOnDenied})ensure(permission,{request,openSettingOnDenied})openSetting({type,permission})返回统一结构{permission:camera,status:granted,// granted | denied | permanentlyDenied | limited | serviceOff | unsupported | unknownplatform:android,native:android.permission.CAMERA,kind:runtime,special:false,canRequest:true,supported:true,message:granted}状态含义status含义granted已授权denied未授权permanentlyDenied永久拒绝 /「不再询问」limited有限授权iOS 部分相册serviceOff系统开关关闭unsupported当前端无此项unknown无法判断平台差异环境行为Androidplus.android.requestPermissionsAPI 33 使用READ_MEDIA_*/POST_NOTIFICATIONS悬浮窗等特殊权限走 IntentiOSuni.getAppAuthorizeSetting 原生 authorization / request永久拒绝后打开 App 设置鸿蒙uni 授权查询与openAppAuthorizeSetting小程序getSetting/authorize/openSetting别名映射scope.*H5Permissions API /getUserMedia/ NotificationopenSetting返回falsenvue不依赖document监听plusready轮询plus就绪uni-app xUTS 代码在utssdk.pendingVue / App 使用index.js处理流程别名 / 原生权限串 │ ├─ android ── runtime 申请 / special 跳设置 ├─ ios ────── AppAuthorize 原生 request ├─ harmony ── uni 授权 API ├─ mp-* ───── scope authorize └─ web ────── Permissions / getUserMedia权限种类kind含义行为runtime运行时权限request弹系统框special特殊权限只checkopenSettingservice系统开关如定位服务关闭为serviceOffprivacy隐私权限iOS 首次触发系统弹框引入import{check,request,requestMany,ensure,openSetting,isSupported,listPermissions,getPlatform,PermissionStatus,SettingType}from/uni_modules/lf-permission/index.js使用index.js入口。插件不写入工程权限声明。用到哪项在 manifest / iOS Privacy / 小程序后台声明哪项。用法只读检测constretawaitcheck(camera)if(ret.statusPermissionStatus.GRANTED){// 已授权}elseif(ret.statusPermissionStatus.UNSUPPORTED){// 当前端无此项}else{// 未授权}申请与永久拒绝constretawaitrequest(location)if(ret.statusPermissionStatus.GRANTED){// 继续}elseif(ret.statusPermissionStatus.PERMANENTLY_DENIED){awaitopenSetting({permission:location})}ensureconstretawaitensure(microphone,{request:true,openSettingOnDenied:true})if(ret.status!PermissionStatus.GRANTED){uni.showToast({title:需要麦克风权限,icon:none})return}定位先系统开关再 App 权限系统定位开关与 App 定位权限是两层状态分开检测asyncfunctiongetMyLocation(){letserviceawaitcheck(locationService)if(service.statusPermissionStatus.SERVICE_OFF){awaitopenSetting({type:SettingType.LOCATION_SERVICE})serviceawaitcheck(locationService)if(service.status!PermissionStatus.GRANTED){uni.showToast({title:请开启系统定位,icon:none})return}}constappLocawaitensure(location,{request:true,openSettingOnDenied:true})if(appLoc.status!PermissionStatus.GRANTED){uni.showToast({title:需要定位权限,icon:none})return}uni.getLocation({type:gcj02,success:(res){console.log(res.latitude,res.longitude)}})}从设置页返回后复查特殊权限打开设置后授权结果在用户返回时才变化。在onShow再checkexportdefault{data(){return{waiting:}},asynconShow(){if(!this.waiting)returnconstretawaitcheck(this.waiting)this.waiting// 按 ret.status 继续业务},methods:{asyncaskOverlay(){this.waitingoverlayawaitopenSetting({permission:overlay})}}}打开设置类型awaitopenSetting({type:SettingType.APP})awaitopenSetting({type:SettingType.LOCATION_SERVICE})awaitopenSetting({type:SettingType.NOTIFICATION})awaitopenSetting({type:SettingType.OVERLAY})awaitopenSetting({type:SettingType.BATTERY})awaitopenSetting({type:SettingType.INSTALL})awaitopenSetting({type:SettingType.MANAGE_STORAGE})权限别名部分完整表见readme.md/permissions.js。业务使用别名也支持直接传android.permission.XXX、scope.xxx、ohos.permission.XXX。别名说明kindAndroidiOS / 小程序location精确定位runtimeACCESS_FINE_LOCATIONWhenInUse /scope.userLocationlocationService系统定位开关service系统 Location系统开关 /locationEnabledcamera相机runtimeCAMERAcamera /scope.cameramicrophone麦克风runtimeRECORD_AUDIOrecord /scope.recordphotoRead读相册/媒体runtimeAPI 33READ_MEDIA_*photoLibrarynotification通知runtimeAPI 33POST_NOTIFICATIONS通知授权overlay悬浮窗specialSYSTEM_ALERT_WINDOW仅 Androidbluetooth蓝牙runtimeAPI 31BLUETOOTH_*bluetooth /scope.bluetoothmanageExternalStorage所有文件访问specialMANAGE_EXTERNAL_STORAGE审核风险高电话、短信、通话记录等敏感权限在别名表中。无业务需求时不要在 manifest 声明。实现要点Android 运行时权限plus.android.requestPermissions(natives,(resultObj){// granted / deniedPresent / deniedAlways// deniedAlways → permanentlyDenied},(error){/* unknown */})检测使用ContextCompat.checkSelfPermission不可用时回退 support 包或checkSelfPermission。媒体与存储按SDK_INT择权API 33READ_MEDIA_IMAGES/READ_MEDIA_VIDEO/POST_NOTIFICATIONS更低READ_EXTERNAL_STORAGEAndroid 特殊权限Settings.canDrawOverlays(main)// 未授权 → ACTION_MANAGE_OVERLAY_PERMISSION同类writeSettings、batteryOptimization、installPackages、manageExternalStorage、scheduleExactAlarm、notificationListener。request对这些别名打开设置页不调用requestPermissions。iOS读取uni.getAppAuthorizeSetting()字段cameraAuthorized、locationAuthorized等。字段不足时使用原生authorizationStatus。request触发对应request*Authorization状态为permanentlyDenied时打开app-settings:。系统定位开关与 App 定位权限分离locationService与location。小程序uni.getSetting → authSetting[scope]uni.authorize({scope})uni.openSetting()// 永久拒绝后别名location→scope.userLocationcamera→scope.camera。nvue / plus 就绪// 有 document监听 plusready// 无 DOM轮询 typeof plus ! undefined各端声明部分Android用到再加uses-permissionandroid:nameandroid.permission.CAMERA/uses-permissionandroid:nameandroid.permission.ACCESS_FINE_LOCATION/uses-permissionandroid:nameandroid.permission.RECORD_AUDIO/uses-permissionandroid:nameandroid.permission.POST_NOTIFICATIONS/iOS Privacy Key未填用途文案时系统拒绝授权用途Key相机NSCameraUsageDescription麦克风NSMicrophoneUsageDescription相册NSPhotoLibraryUsageDescription定位NSLocationWhenInUseUsageDescription真机问题永久拒绝后继续弹授权框无效状态为permanentlyDenied。调用openSetting打开设置页。App 定位已授权仍拿不到坐标系统定位总开关为serviceOff。先check(locationService)。iOS 跳转定位设置无反应私有App-Prefs在高版本受限。回退app-settings:/uni.openAppAuthorizeSetting。Android 13 读相册失败使用别名photoRead插件按 API 选择READ_MEDIA_*。通知权限在 Android 12 申请无效果POST_NOTIFICATIONS从 API 33 起才是运行时权限。更低版本检测通知开关打开通知设置页。悬浮窗request后立刻check仍是 denied用户还在设置页。在onShow复查。导入报 UTS 编译失败使用/uni_modules/lf-permission/index.js。UTS 代码位于utssdk.pending。nvue 中plus为 undefined未等待 plus 就绪。插件内部轮询业务侧对权限 API 使用await。小程序authorize失败且无法再弹状态为permanentlyDenied调用openSetting。H5openSetting为 false浏览器无法打开站点权限页。用文案引导用户到地址栏站点设置。声明了电话权限但业务未用应用市场上架被拒。无需求不要写入phone/sms等权限。manageExternalStorage上架失败所有文件访问属敏感特殊权限。无强需求不要使用。后台定位申请失败Android 10 须先具备前台定位再申请locationBackground。业务用数字码判断权限使用PermissionStatus字符串比较例如ret.status PermissionStatus.GRANTED。排查console.log(getPlatform())console.log(awaitcheck(camera))console.log(listPermissions({onlyCurrent:true}))检查项当前端platform与预期是否一致ret.native是否为当前 API 应申请的权限串manifest / plist / 小程序是否已声明status是denied还是permanentlyDenied/serviceOff特殊权限是否在onShow复查引入路径是否为index.jsDemo/uni_modules/lf-permission/pages/demo/demo逐项「检查 / 申请 / ensure / 设置」。源码目录uni_modules/lf-permission/ ├── index.js # 对外 API ├── constants.js # 状态 / SettingType ├── permissions.js # 别名全表 ├── core.js # 结果构造、平台探测 ├── platforms/ │ ├── android.js │ ├── ios.js │ ├── harmony.js │ ├── mp.js │ └── web.js ├── pages/demo/demo.vue ├── utssdk.pending/ # uni-app x启用时改名为 utssdk ├── readme.md ├── changelog.md └── article.md接入要求插件目录为uni_modules/lf-permission从/uni_modules/lf-permission/index.js引入按业务声明各端权限与 iOS 用途文案定位场景区分locationService与location特殊权限在设置返回后复查敏感权限无需求不声明调用示例awaitensure(camera,{request:true,openSettingOnDenied:true})问题反馈插件https://ext.dcloud.net.cn/plugin?id29096邮箱lingfugroupgmail.com