更新记录
1.0.0(2026-01-02)
首次发布
平台兼容性
xc-sys-permission
一套跨端权限工具,统一封装 Android / iOS / 鸿蒙 的权限检查、申请与跳转设置页,适用于 uni-app 及 uni-app x。
功能特点
- 同一份 API 覆盖 Android、iOS、鸿蒙(OpenHarmony/HarmonyOS)
checkPermissions/requestPermissions/openSystemPermissionPage三个核心方法,返回统一的PermissionResult- 使用原生 API 实现,不依赖第三方库
- 原生权限常量格式(android.permission.XXX, ohos.permission.XXX, iOS Info.plist key)
- 权限结果按传参顺序返回,保持原始顺序
- 支持在用户拒绝权限时,通过
doNotAskAgain标识引导到系统设置
安装与引入
插件市场直接安装或将代码放入 uni_modules/xc-sys-permission
页面中引入:
import { checkPermissions, requestPermissions, openSystemPermissionPage } from '@/uni_modules/xc-sys-permission'
调用时需保证页面已启动(如 onLoad / onShow 后),以便 Android/Harmony 拿到有效 Activity/UIAbilityContext
支持的权限名约定
Android
支持所有 Android 系统权限常量(不限于示例),权限名称必须以 android.permission. 开头,如:
android.permission.CAMERA- 相机权限android.permission.RECORD_AUDIO- 麦克风权限android.permission.ACCESS_FINE_LOCATION- 精确位置权限android.permission.ACCESS_COARSE_LOCATION- 粗略位置权限android.permission.READ_MEDIA_IMAGES- 读取图片(Android 13+,API 33+)android.permission.READ_MEDIA_VIDEO- 读取视频(Android 13+,API 33+)android.permission.READ_MEDIA_AUDIO- 读取音频(Android 13+,API 33+)android.permission.READ_EXTERNAL_STORAGE- 读取外部存储(Android 12 及以下,API < 33)android.permission.WRITE_EXTERNAL_STORAGE- 写入外部存储(Android 9 及以下,API < 29)android.permission.POST_NOTIFICATIONS- 通知权限(Android 13+,API 33+)android.permission.READ_CONTACTS- 读取通讯录权限android.permission.WRITE_CONTACTS- 写入通讯录权限android.permission.READ_CALENDAR- 读取日历权限android.permission.WRITE_CALENDAR- 写入日历权限- 等等... 支持所有 Android 系统权限常量
注意:
- 权限名称可以不带
android.permission.前缀,系统会自动补全 - 对于媒体权限(
READ_MEDIA_IMAGES、READ_MEDIA_VIDEO、READ_MEDIA_AUDIO),在 Android 12 及以下会自动映射为READ_EXTERNAL_STORAGE - 对于通知权限(
POST_NOTIFICATIONS),仅在 Android 13+(API 33+)有效,需要跳转到系统设置
iOS
直接使用 Info.plist 中的权限说明 key(原生常量),支持所有 iOS 系统权限 key,如:
基础权限:
NSPhotoLibraryUsageDescription- 相册权限(读取)NSPhotoLibraryAddUsageDescription- 相册权限(仅添加)NSCameraUsageDescription- 相机权限NSMicrophoneUsageDescription- 麦克风权限NSLocationWhenInUseUsageDescription- 定位权限(使用时)NSLocationAlwaysAndWhenInUseUsageDescription- 定位权限(始终和使用时,iOS 11+)
系统服务权限:
NSContactsUsageDescription- 通讯录权限NSCalendarsUsageDescription- 日历权限(iOS 17+ 需要完整访问)NSCalendarsFullAccessUsageDescription- 日历完整访问权限(iOS 17+)NSCalendarsWriteOnlyUsageDescription- 日历仅写入权限(iOS 17+)NSRemindersUsageDescription- 提醒事项权限NSAppleMusicUsageDescription- Apple Music 权限
生物识别与安全:
NSFaceIDUsageDescription- Face ID 权限
健康与运动:
NSMotionUsageDescription- 运动与健身权限NSHealthShareUsageDescription- 健康数据读取权限NSHealthUpdateUsageDescription- 健康数据写入权限
智能家居与语音:
NSHomeKitUsageDescription- HomeKit 权限NSSiriUsageDescription- Siri 权限NSSpeechRecognitionUsageDescription- 语音识别权限
媒体与订阅:
NSVideoSubscriberAccountUsageDescription- 视频订阅账户权限
网络与蓝牙:
NSBluetoothAlwaysUsageDescription- 蓝牙权限(iOS 13+)NSBluetoothPeripheralUsageDescription- 蓝牙外设权限(iOS 12 及以下,已废弃)NSLocalNetworkUsageDescription- 本地网络权限
隐私与追踪:
NSUserTrackingUsageDescription- 追踪权限(ATT,iOS 14.5+)
注意:
- 所有权限都需要在
Info.plist中声明对应的usage description键值对 - 部分权限(如通知权限)需要异步检查,
cannotCheckByAPI字段会标识 - 某些权限(如健康、HomeKit、Siri 等)无法通过 API 准确检查状态,需要通过实际使用来判断
鸿蒙(HarmonyOS)
传 @ohos.abilityAccessCtrl 的权限名,权限名称必须以 ohos.permission. 开头,如:
基础权限:
ohos.permission.CAMERA- 相机权限ohos.permission.MICROPHONE- 麦克风权限ohos.permission.LOCATION- 定位权限
通讯录与日历:
ohos.permission.READ_CALENDAR- 读取日历权限ohos.permission.WRITE_CALENDAR- 写入日历权限
通知权限:
ohos.permission.ACCESS_NOTIFICATION_POLICY- 通知权限
其他权限:
- 等等... 支持所有鸿蒙系统权限常量
注意:
- 权限名称必须严格以
ohos.permission.开头,否则会被识别为无效权限(状态 3) - 所有权限都需要在
module.json5中声明 - 权限状态检查使用
checkAccessTokenAPI,无法区分"从未申请过"和"已拒绝",统一返回未授权(状态 0) - 一旦用户拒绝权限,系统会记住选择,无法再次弹出对话框,需要引导到系统设置
- 更多权限列表请参考:鸿蒙权限管理文档
API 说明
checkPermissions(permissions)
检查权限状态,同步返回(鸿蒙为 Promise,推荐统一使用 await)
import { checkPermissions } from '@/uni_modules/xc-sys-permission'
// Android 示例
const permissionList = [{
name: 'android.permission.CAMERA',
title: '相机权限申请说明:',
content: 'APP申请相机权限用于扫码,允许或拒绝均不会获取任何隐私信息。'
}]
// iOS 示例(直接使用 Info.plist key)
// const permissionList = [{
// name: 'NSCameraUsageDescription',
// title: '相机权限申请说明:',
// content: 'APP申请相机权限用于扫码,允许或拒绝均不会获取任何隐私信息。'
// }]
const res = await checkPermissions(permissionList)
if (!res.allGranted) {
// TODO: 给出引导
console.log('未授权权限:', res.permissions.filter(p => p.status !== 1))
}
requestPermissions(permissions)
申请权限并返回 Promise
import { requestPermissions, openSystemPermissionPage } from '@/uni_modules/xc-sys-permission'
// Android 示例
const permissionList = [{
name: 'android.permission.CAMERA',
title: '相机权限申请说明:',
content: 'APP申请相机权限用于扫码,允许或拒绝均不会获取任何隐私信息。'
}]
// iOS 示例(直接使用 Info.plist key)
// const permissionList = [{
// name: 'NSCameraUsageDescription',
// title: '相机权限申请说明:',
// content: 'APP申请相机权限用于扫码,允许或拒绝均不会获取任何隐私信息。'
// }]
const res = await requestPermissions(permissionList)
if (!res.allGranted && res.doNotAskAgain) {
// 用户勾选"不再询问"或权限被永久拒绝,引导去系统设置
openSystemPermissionPage(permissionList)
}
openSystemPermissionPage(permissions)
打开系统权限设置页;Android 支持传入需要高亮/引导的权限列表,iOS 无视参数直接跳转 App 设置,鸿蒙返回 Promise 可 await
注意:permissions 参数是必需的,但可以传入空数组 [] 表示不需要特定权限。
import { openSystemPermissionPage } from '@/uni_modules/xc-sys-permission'
// 打开系统设置页(不需要特定权限)
await openSystemPermissionPage([])
// 打开系统设置页(传入需要引导的权限列表)
await openSystemPermissionPage(permissionList)
PermissionResult 结构
{
allGranted: boolean, // 是否全部授权(所有权限的 status 都为 1)
doNotAskAgain: boolean, // 是否存在需要引导到系统设置的权限(存在 status 为 2 的权限)
permissions: Array<{
name: string, // 权限名称(原生常量)
status: number, // 权限状态:0=未授权,1=已授权,2=拒绝授权(需引导系统设置),3=无效权限
title: string, // 权限标题说明
content: string, // 权限详细说明
cannotCheckByAPI: boolean // 是否无法通过 API 直接检查状态(true=需要通过实际使用来判断,false=可以通过 API 检查)
}> // 按传参顺序返回,保持原始顺序
}
权限状态说明
-
0- 未授权:权限尚未授予,可以申请- Android:首次请求或用户拒绝但未选择"不再询问"(支持"每次询问"模式)
- iOS:权限尚未确定(
.notDetermined) - 鸿蒙:权限未授权(
GrantStatus.PERMISSION_DENIED),可以申请
-
1- 已授权:权限已授予,可以使用- Android:权限已授予(
PERMISSION_GRANTED) - iOS:权限已授权(
.authorized或.limited) - 鸿蒙:权限已授权(
GrantStatus.PERMISSION_GRANTED)
- Android:权限已授予(
-
2- 拒绝授权:权限被拒绝且无法再次申请,需要引导用户到系统设置页开启- Android:用户选择"不再询问"(永久拒绝),或通知权限(Android 13+)需要跳转到设置
- iOS:权限被拒绝(
.denied或.restricted) - 鸿蒙:权限被拒绝且无法再次弹出对话框(需要引导到系统设置)
-
3- 无效权限:权限名称无效或无法识别,该权限无法使用- Android:权限常量不存在、未在
AndroidManifest.xml中声明,或版本不支持(如POST_NOTIFICATIONS在 API < 33) - iOS:Info.plist key 无法识别或未在
Info.plist中声明 - 鸿蒙:权限常量格式不正确(不是以
ohos.permission.开头)或未在module.json5中声明
- Android:权限常量不存在、未在
cannotCheckByAPI 字段说明
false- 可以通过 API 直接检查权限状态(Android、鸿蒙的所有权限,iOS 的大部分权限)true- 无法通过 API 直接检查权限状态,需要通过实际使用来判断(仅 iOS 部分权限):NSUserNotificationsUsageDescription- 通知权限(需要异步检查)NSMotionUsageDescription- 运动权限(需要异步查询)NSHealthShareUsageDescription/NSHealthUpdateUsageDescription- 健康数据权限(需要异步检查)NSHomeKitUsageDescription- HomeKit 权限(无法准确判断)NSSiriUsageDescription- Siri 权限(无法准确判断)NSVideoSubscriberAccountUsageDescription- 视频订阅账户权限(无法准确判断)NSTVProviderUsageDescription- TV Provider 权限(无法准确判断)NSLocalNetworkUsageDescription- 本地网络权限(无法准确判断)
注意:当 cannotCheckByAPI 为 true 时,status 可能不准确,实际权限状态需要通过实际使用相关功能来判断。
使用示例
import { checkPermissions, requestPermissions, openSystemPermissionPage } from '@/uni_modules/xc-sys-permission'
// 根据平台动态构建权限列表
let permissionList = []
// #ifdef APP-PLUS
// uni-app 中需要通过系统 API 判断平台
const systemInfo = uni.getSystemInfoSync()
if (systemInfo.platform === 'android') {
permissionList = [{
name: 'android.permission.ACCESS_FINE_LOCATION',
title: '手机位置权限申请说明:',
content: 'APP申请定位信息用于查找附近门店使用,允许或拒绝均不会获取任何隐私信息。'
}, {
name: 'android.permission.CAMERA',
title: '相机权限申请说明:',
content: 'APP申请摄像头权限用于扫码,允许或拒绝均不会获取任何隐私信息。'
}]
} else if (systemInfo.platform === 'ios') {
permissionList = [{
name: 'NSLocationWhenInUseUsageDescription',
title: '手机位置权限申请说明:',
content: 'APP申请定位信息用于查找附近门店使用,允许或拒绝均不会获取任何隐私信息。'
}, {
name: 'NSCameraUsageDescription',
title: '相机权限申请说明:',
content: 'APP申请摄像头权限用于扫码,允许或拒绝均不会获取任何隐私信息。'
}]
}
// #endif
// #ifdef APP-ANDROID
// uni-app x 中可以直接使用 APP-ANDROID
permissionList = [{
name: 'android.permission.ACCESS_FINE_LOCATION',
title: '手机位置权限申请说明:',
content: 'APP申请定位信息用于查找附近门店使用,允许或拒绝均不会获取任何隐私信息。'
}, {
name: 'android.permission.CAMERA',
title: '相机权限申请说明:',
content: 'APP申请摄像头权限用于扫码,允许或拒绝均不会获取任何隐私信息。'
}]
// #endif
// #ifdef APP-IOS
// uni-app x 中可以直接使用 APP-IOS
permissionList = [{
name: 'NSLocationWhenInUseUsageDescription',
title: '手机位置权限申请说明:',
content: 'APP申请定位信息用于查找附近门店使用,允许或拒绝均不会获取任何隐私信息。'
}, {
name: 'NSCameraUsageDescription',
title: '相机权限申请说明:',
content: 'APP申请摄像头权限用于扫码,允许或拒绝均不会获取任何隐私信息。'
}]
// #endif
// #ifdef APP-HARMONY
permissionList = [{
name: 'ohos.permission.LOCATION',
title: '手机位置权限申请说明:',
content: 'APP申请定位信息用于查找附近门店使用,允许或拒绝均不会获取任何隐私信息。'
}, {
name: 'ohos.permission.CAMERA',
title: '相机权限申请说明:',
content: 'APP申请摄像头权限用于扫码,允许或拒绝均不会获取任何隐私信息。'
}]
// #endif
// 检查权限
async function checkAndRequestPermissions() {
const checkResult = await checkPermissions(permissionList)
if (checkResult.allGranted) {
console.log('所有权限已授权')
return
}
const requestResult = await requestPermissions(permissionList)
if (!requestResult.allGranted && requestResult.doNotAskAgain) {
uni.showModal({
title: '权限申请',
content: '部分权限被拒绝,请在系统设置中开启',
success: (res) => {
if (res.confirm) {
openSystemPermissionPage(permissionList)
}
}
})
}
}
注意事项
权限声明
-
Android:请在
manifest.json的app-plus->distribute->android->permissions中声明需要的权限,或在原生AndroidManifest.xml中使用<uses-permission>标签声明- 权限名称必须与系统权限常量完全一致(如
android.permission.CAMERA) - 未声明的权限会被识别为无效权限(状态 3)
- 权限名称必须与系统权限常量完全一致(如
-
iOS:请在
manifest.json的app-plus->distribute->ios->privacyDescription中声明权限说明,或在原生Info.plist中添加对应的usage description键值对- 键名必须与系统权限 key 完全一致(如
NSCameraUsageDescription) - 未声明的权限无法申请,会被识别为无效权限(状态 3)
- 键名必须与系统权限 key 完全一致(如
-
鸿蒙:请在
module.json5的requestPermissions数组中声明需要的权限- 权限名称必须严格以
ohos.permission.开头(如ohos.permission.CAMERA) - 未声明的权限会被识别为无效权限(状态 3)
- 更多信息请参考:鸿蒙权限管理文档
- 权限名称必须严格以
权限状态处理
-
权限结果数组严格按照传参顺序返回,便于前端按顺序展示
-
当
status为 2 时,表示权限被永久拒绝,需要引导用户到系统设置页开启:- Android:用户选择"不再询问",或通知权限(Android 13+)需要跳转到设置
- iOS:用户拒绝权限,需要跳转到 App 设置
- 鸿蒙:权限被拒绝且无法再次弹出对话框,需要引导到系统设置
-
当
status为 3 时,表示权限名称无效或无法识别,请检查:- Android:权限名称格式是否正确(可以不带
android.permission.前缀,系统会自动补全),是否在AndroidManifest.xml中声明,版本是否支持 - iOS:Info.plist key 是否正确,是否在
Info.plist中声明 - 鸿蒙:权限名称是否以
ohos.permission.开头,是否在module.json5中声明
- Android:权限名称格式是否正确(可以不带
平台特性
-
Android 权限特性:
- 支持"每次询问"模式(Android 13+):即使用户之前拒绝过,如果设置了"每次询问",仍然可以弹出对话框
- 通知权限(
POST_NOTIFICATIONS)在 Android 13+ 无法通过运行时对话框申请,必须跳转到系统设置 - 媒体权限在 Android 13+ 使用
READ_MEDIA_IMAGES、READ_MEDIA_VIDEO、READ_MEDIA_AUDIO,在 Android 12 及以下自动映射为READ_EXTERNAL_STORAGE
-
iOS 权限特性:
- 部分权限(如通知、运动、健康等)需要异步检查,
cannotCheckByAPI字段会标识 - 某些权限(如健康、HomeKit、Siri 等)无法通过 API 准确检查状态,需要通过实际使用来判断
- 相册权限在 iOS 14+ 支持
.limited状态(部分授权)
- 部分权限(如通知、运动、健康等)需要异步检查,
-
鸿蒙权限特性:
- 权限状态检查无法区分"从未申请过"和"已拒绝",统一返回未授权(状态 0)
- 一旦用户拒绝权限,系统会记住选择,无法再次弹出对话框,需要引导到系统设置
- 权限申请使用
requestPermissionsFromUser,永久拒绝后使用requestPermissionOnSetting引导到系统设置

收藏人数:
购买源码授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 6
赞赏 0
下载 12826491
赞赏 1835
赞赏
京公网安备:11010802035340号