Skip to content

系统权限使用说明 ​

权限分两层:fcuni/permission 只负责 Android 申请时的全局用途说明;业务文案在 modules/permission;真正向系统申请权限由各端 API 完成。

H5安卓苹果鸿蒙微信小程序其它小程序
-√--√-

库的运行范围与生态兼容:库本身只在 Android 上做顶部权限说明弹窗 + 系统权限监听(uni.createRequestPermissionListener 仅 Android 4.0+ 可用),在微信小程序上做拒绝授权引导(MPShowAuthorize)。iOS / 鸿蒙 / H5 不需要这个库——iOS 走系统弹窗 + app-ios.distribute.privacyDescription;鸿蒙走系统弹窗 + module.json5 的 reason 字段;H5 无系统权限概念。但四端都各自需要在 manifest / module.json5 中声明权限和用途文案,具体见「1.1 平台权限声明」。

已集成的功能有

  • 业务侧统一管理文案(modules/permission/index.ts)
  • Android 顶部权限说明同步弹窗
  • 系统定位 / 蓝牙开关关闭时拦截调用
  • 小程序拒绝授权引导用户打开设置页

安装 ​

终端在项目根目录下执行命令安装模块(如若创建项目时已选择了该模块,可略过这一步)

bash
fc-uniapp-x i permission

1. 配置客户端 ​

1.1 平台权限声明 ​

配置或修改权限后需云端打包(或自定义调试基座)才能生效。标准基座没有 uni.createRequestPermissionListener,会出现模块未注册错误。

Android ​

HBuilderX 4.71+ 在 manifest.json 源码视图的 app-android.distribute.permissions 中额外添加权限。内置模块会自动带上部分权限,不够的再补:

json
{
  "app-android": {
    "distribute": {
      "modules": {
        "uni-createRequestPermissionListener": {},
        "uni-requestSystemPermission": {},
        "uni-media": {},
        "uni-recorder": {},
        "uni-phoneContact": {},
        "uni-calendar": {},
        "uni-makePhoneCall": {},
        "uni-location": {
          "system": {}
        }
      },
      "permissions": [
        "<uses-permission android:name=\"android.permission.CAMERA\"/>",
        "<uses-permission android:name=\"android.permission.READ_MEDIA_IMAGES\"/>",
        "<uses-permission android:name=\"android.permission.READ_MEDIA_VIDEO\"/>",
        "<uses-permission android:name=\"android.permission.READ_MEDIA_VISUAL_USER_SELECTED\"/>",
        "<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
        "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
        "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
        "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
        "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
        "<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
        "<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
        "<uses-permission android:name=\"android.permission.READ_CALENDAR\"/>",
        "<uses-permission android:name=\"android.permission.WRITE_CALENDAR\"/>",
        "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
        "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
        "<uses-permission android:name=\"android.permission.BLUETOOTH_SCAN\"/>",
        "<uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\"/>"
      ]
    }
  }
}

可视化界面:安卓 App 配置 → 权限配置 → 额外添加的权限。android:name 的双引号前必须加转义斜线 \。

Android 权限中文名称用途说明
android.permission.CAMERA相机拍摄照片或扫描二维码
android.permission.READ_MEDIA_IMAGES相册选择相册中的图片
android.permission.READ_MEDIA_VIDEO相册选择相册中的视频
android.permission.READ_MEDIA_VISUAL_USER_SELECTED相册访问用户选择的照片
android.permission.READ_EXTERNAL_STORAGE存储读取读取设备中的图片和文件
android.permission.WRITE_EXTERNAL_STORAGE存储写入保存文件到设备存储
android.permission.ACCESS_COARSE_LOCATION粗略定位获取大致位置信息
android.permission.ACCESS_FINE_LOCATION精确定位获取精确位置信息
android.permission.RECORD_AUDIO麦克风录制语音或视频
android.permission.READ_CONTACTS读通讯录读取联系人信息
android.permission.WRITE_CONTACTS写通讯录新增或修改联系人
android.permission.READ_CALENDAR读取日历读取日程安排
android.permission.WRITE_CALENDAR写入日历添加或修改日程
android.permission.READ_PHONE_STATE电话状态读取设备电话状态
android.permission.CALL_PHONE拨打电话发起电话呼叫
android.permission.BLUETOOTH_SCAN蓝牙扫描附近蓝牙设备
android.permission.BLUETOOTH_CONNECT蓝牙连接蓝牙设备

iOS ​

uni.requestSystemPermission 不支持 iOS。在 app-ios.distribute.privacyDescription 配置许可描述,系统首次弹窗会展示这段文字。未配置或描述与实际用途不符会被 App Store 拒审。

json
{
  "app-ios": {
    "distribute": {
      "privacyDescription": {
        "NSCameraUsageDescription": "拍摄照片或扫描二维码",
        "NSPhotoLibraryUsageDescription": "选择相册中的图片",
        "NSPhotoLibraryAddUsageDescription": "保存图片到相册",
        "NSMicrophoneUsageDescription": "录制语音或视频",
        "NSLocationWhenInUseUsageDescription": "获取当前位置",
        "NSLocationAlwaysAndWhenInUseUsageDescription": "持续获取位置信息",
        "NSContactsUsageDescription": "读取或写入联系人",
        "NSCalendarsUsageDescription": "读取或写入日程",
        "NSBluetoothAlwaysUsageDescription": "扫描并连接蓝牙设备",
        "NSBluetoothPeripheralUsageDescription": "使用蓝牙外设"
      }
    }
  }
}

可视化界面:iOS App 配置 → 隐私信息访问的许可描述。也可在项目根目录 Info.plist 中补充,冲突时 Info.plist 会覆盖 manifest。内置模块会写入通用描述,上架前请改成真实业务文案。

鸿蒙 ​

在 harmony-configs/entry/src/main/module.json5 的 requestPermissions 声明权限,reason 就是系统弹窗用途说明。精确定位和模糊定位必须成对出现,否则审核会被驳回。reason 文案写在 harmony-configs/AppScope/resources/base/element/string.json(覆盖模板时需保留 app_name)。

鸿蒙权限中文名称用途说明
ohos.permission.CAMERA相机拍摄照片或扫描二维码
ohos.permission.APPROXIMATELY_LOCATION粗略定位获取当前位置信息
ohos.permission.LOCATION精确定位获取当前位置信息
ohos.permission.MICROPHONE麦克风录制语音或视频
ohos.permission.READ_CONTACTS读通讯录读取联系人信息
ohos.permission.READ_CALENDAR读取日历读取日程安排
ohos.permission.WRITE_CALENDAR写入日历添加或修改日程
ohos.permission.GET_NETWORK_INFO网络信息读取设备网络状态
ohos.permission.PLACE_CALL拨打电话发起电话呼叫
ohos.permission.ACCESS_BLUETOOTH蓝牙扫描并连接蓝牙设备

以下为受限权限(ACL),默认已在 module.json5 中注释。未在 AGC 申请并通过带授权的证书签名时,声明它们会导致无法安装(报「运行所需的权限没有签名授权」):

鸿蒙受限权限中文名称说明
ohos.permission.READ_IMAGEVIDEO相册读取普通选图用 uni.chooseImage(系统 Picker,无需该权限)
ohos.permission.WRITE_IMAGEVIDEO相册写入保存图片用 uni.saveImageToPhotosAlbum
ohos.permission.WRITE_CONTACTS写通讯录uni.makePhoneCall 文档要求此权限,需单独申请
json5
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.CAMERA",
        "reason": "$string:permission_camera_tips",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.APPROXIMATELY_LOCATION",
        "reason": "$string:permission_location_tips",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.LOCATION",
        "reason": "$string:permission_location_tips",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      }
    ]
  }
}

1.2 业务文案配置 ​

在 modules/permission/index.ts 维护 Android 短名到中文文案(name + explain)的映射。key 必须等于 android.permission. 后面那段(如 CAMERA、ACCESS_FINE_LOCATION),与 Android 权限声明一一对应。

ts
export const permissionConfig = {
  CAMERA: { name: '相机', explain: '拍摄照片或扫描二维码' },
  ACCESS_FINE_LOCATION: { name: '精确定位', explain: '获取精确位置信息' }
}

PermissionEnum 接口字段:

字段含义
name权限名称(中文,如"相机")
explain权限说明(中文,如"拍摄照片或扫描二维码")

2. 初始化(仅 Android) ​

pages.json 已注册 components/fc-dialog/permission。在 App.uvue 启动时初始化、退出时销毁:

ts
import { FC } from '@/fcuni'
// #ifdef APP-ANDROID
import { permissionConfig } from '@/modules/permission'
// #endif

onLaunch(() => {
  // #ifdef APP-ANDROID
  FC.Permission.init(permissionConfig)
  // #endif
})

onExit(() => {
  // #ifdef APP-ANDROID
  FC.Permission.destroy()
  // #endif
})

init() 做两件事:

  1. 监听定位 / 蓝牙开关(uni.getLocation、uni.chooseLocation、uni.openBluetoothAdapter)。系统开关关闭时拦截调用并提示去设置。
  2. 创建 uni.createRequestPermissionListener。任意业务代码弹出系统权限框时,顶部同步展示用途说明。

不要在页面里单独 init / destroy,否则会漏掉其它页面触发的权限申请。鸿蒙、iOS 上 init 为空操作,仅打印 console.warn 提示。

公开 API:

API平台说明
FC.Permission.init(config)Android初始化拦截器与系统权限监听器;非 Android 为空操作
FC.Permission.destroy()Android停止监听并移除拦截器;非 Android 为空操作
FC.Permission.MPShowAuthorize(scope, text)小程序用户拒绝授权后引导打开设置页;非小程序平台 Promise.reject

3. 业务侧申请权限 ​

三端统一:直接调用会触发权限的业务 API,不要在业务里显式调用 uni.requestSystemPermission。Android 上 FC.Permission.init 会在系统权限框弹出时同步展示用途说明。

能力业务 API
相机uni.chooseImage({ sourceType: ['camera'] })
相册uni.chooseImage({ sourceType: ['album'], albumMode: 'custom' })
定位uni.getLocation
麦克风uni.getRecorderManager().start
存储写入uni.saveImageToPhotosAlbum
读通讯录uni.chooseContact
写通讯录uni.addPhoneContact
写入日历uni.addPhoneCalendar / uni.addPhoneRepeatCalendar

以下 API 不会申请危险权限,测试页已去掉:uni.chooseFile(系统文件选择器)、uni.makePhoneCall(系统拨号页)、uni.chooseImage({ albumMode: 'system' })。读取日历、读取电话状态、App 端蓝牙目前没有会申请权限的业务 API。查询授权状态用 uni.getAppAuthorizeSetting()。蒸汽模式下不要调用 UTSAndroid.checkSystemPermissionGranted。

通讯录、日历、录音、拨号、选图等 API 依赖原生模块。HBuilderX 会按代码摇树,但改模块或新增这些 API 后必须重新打包自定义基座,标准基座和旧自定义基座会报 UTS module is not registered。

被永久拒绝后无法再次弹系统框,引导用户打开设置:

ts
uni.openAppAuthorizeSetting({})

小程序拒绝授权 ​

ts
try {
  const ok = await FC.Permission.MPShowAuthorize('scope.userLocation', '获取当前位置')
  console.log('授权成功', ok)
} catch (err) {
  console.warn('授权失败', err)
}

MPShowAuthorize 在非小程序平台会 reject,业务侧请用 // #ifdef MP-WEIXIN 包起来。

完整对照见 pages/base/permission.uvue。

4. 推荐流程 ​

  1. 按平台在 manifest / module.json5 / privacyDescription 声明权限和用途文案。
  2. 在 modules/permission/index.ts 补齐 Android 短名对应的 name、explain。
  3. App.uvue 调用 FC.Permission.init(permissionConfig)。
  4. 业务在需要时直接调用对应 API,由系统弹出权限框。
  5. 根据业务 API 的 success / fail 处理结果。
  6. 永久拒绝时调用 uni.openAppAuthorizeSetting。
  7. 应用退出时 FC.Permission.destroy()。

调试页:pages/base/permission.uvue。