# m-permission-manager uni-app Vue3 跨端权限管理 UTS 插件,支持 **Android / iOS / Harmony** 三端,提供统一的权限检查与申请 API。 ## 功能 - 统一权限标识,三端通用 - 同步 / 异步检查权限状态 - 单个 / 批量申请权限 - 跳转系统应用设置页 - 获取当前平台支持的权限列表 ## 安装 插件位于 `src/uni_modules/m-permission-manager/`,随项目直接使用,无需额外安装。 ## 文档 > 插件市场仅展示本 readme,下方链接为文内锚点,可直接跳转。 | 文档 | 说明 | | --- | --- | | [使用规范](#使用规范) | 集成约束、推荐流程、审核注意事项 | | [权限配置说明](#权限配置说明) | Android / iOS / Harmony 三端权限文件配置详解 | | [发布指南](#发布指南) | DCloud 插件市场发布填写参考(插件作者) | | [更新日志](#更新日志) | 版本更新记录 | ## 快速开始 ### 方式一:Promise 封装(推荐) ```js import { checkPermission, requestPermission, requestPermissions, openAppSettings, getSupportedPermissions, } from '@/utils/permission-manager' // 检查相机权限 const result = await checkPermission('camera') console.log(result.granted, result.status) // 申请相机权限 const granted = await requestPermission('camera') if (!granted) { await openAppSettings() } // 批量申请 const batch = await requestPermissions(['camera', 'microphone', 'location']) console.log(batch.allGranted, batch.results) ``` ### 方式二:直接调用 UTS API(callback 风格) ```js import { requestPermission } from '@/uni_modules/m-permission-manager' requestPermission({ permission: 'camera', success(res) { console.log(res.granted) }, fail(err) { console.error(err.errCode, err.errMsg) }, }) ``` ## 统一权限标识 | 权限 Key | 说明 | Android | iOS | Harmony | | --- | --- | --- | --- | --- | | `camera` | 相机 | ✅ | ✅ | ✅ | | `photoLibrary` | 相册 | ✅ | ✅ | ✅ | | `storage` | 存储(写) | ✅ | ✅* | ✅ | | `readStorage` | 存储(读) | ✅ | ✅* | ✅ | | `location` | 精确定位 | ✅ | ✅ | ✅ | | `coarseLocation` | 大致定位 | ✅ | ✅* | ✅ | | `microphone` | 麦克风 | ✅ | ✅ | ✅ | | `contacts` | 通讯录(读) | ✅ | ✅ | ✅ | | `writeContacts` | 通讯录(写) | ✅ | ✅* | ✅ | | `bluetooth` | 蓝牙 | ✅ | ✅ | ✅ | | `phone` | 拨打电话 | ✅ | ❌ | ❌ | | `phoneState` | 电话状态 | ✅ | ❌ | ❌ | | `sms` | 发送短信 | ✅ | ❌ | ❌ | | `readSms` | 读取短信 | ✅ | ❌ | ❌ | | `receiveSms` | 接收短信 | ✅ | ❌ | ❌ | | `overlay` | 悬浮窗 | ✅ | ❌ | ❌ | | `writeSettings` | 系统设置 | ✅ | ❌ | ❌ | > *iOS 部分权限映射到相近的系统权限(如 storage → 相册) ## 权限状态 | status | 说明 | | --- | --- | | `granted` | 已授权 | | `denied` | 已拒绝 | | `notDetermined` | 尚未请求 | | `restricted` | 受限制(如家长控制) | | `unsupported` | 当前平台不支持 | ## API | 方法 | 说明 | | --- | --- | | `checkPermissionSync(key)` | 同步检查单个权限 | | `checkPermissionsSync(keys[])` | 同步检查多个权限 | | `checkPermission(options)` | 异步检查单个权限 | | `checkPermissions(options)` | 异步检查多个权限 | | `requestPermission(options)` | 申请单个权限 | | `requestPermissions(options)` | 申请多个权限 | | `openAppSettings(options?)` | 打开系统应用设置 | | `openPermissionSettings(key)` | 按权限类型打开对应设置页(封装层) | | `getSupportedPermissionsSync()` | 获取当前平台支持的权限列表 | ## 宿主配置 > 完整配置说明见 [权限配置说明](#权限配置说明)。 ### Android 在 `manifest.json` → `app-plus.distribute.android.permissions` 中声明所需权限,例如: ```json "permissions": [ "", "", "" ] ``` Android 13+ 读写媒体文件需使用 `READ_MEDIA_IMAGES` / `READ_MEDIA_VIDEO`;插件会同时校验**设备 API** 与宿主 **targetSdkVersion**,仅当 `targetSdkVersion >= 33` 时才申请新媒体权限,否则回退 `READ_EXTERNAL_STORAGE`(兼容未升级 targetSdk 的自定义基座)。 ### iOS 在 `manifest.json` → `app-plus.distribute.ios.privacyDescription` 中配置权限说明,例如: ```json "privacyDescription": { "NSCameraUsageDescription": "需要使用相机进行拍照", "NSMicrophoneUsageDescription": "需要使用麦克风进行录音", "NSPhotoLibraryUsageDescription": "需要访问相册以选择图片", "NSLocationWhenInUseUsageDescription": "需要获取位置信息", "NSBluetoothAlwaysUsageDescription": "需要使用蓝牙连接周边设备" } ``` > **iOS 蓝牙说明**:蓝牙授权开关出现在「设置 → 本 App → 蓝牙」(需声明 `NSBluetoothAlwaysUsageDescription` 且 App 曾触发过蓝牙权限弹窗)。若 App 设置页无该项,请前往「设置 → 隐私与安全性 → 蓝牙」。系统蓝牙开关在「设置 → 蓝牙」,与应用授权无关。Apple 不提供跳转到「隐私 → 蓝牙」的公开深链,插件会打开 App 设置页并配合引导文案。 ### Harmony 插件 `utssdk/app-harmony/module.json5` 已声明鸿蒙端**全部可映射**的 9 项权限: | 权限 Key | ohos.permission | APL 等级 | 说明 | | --- | --- | --- | --- | | `camera` | CAMERA | normal | 可直接安装使用 | | `microphone` | MICROPHONE | normal | 可直接安装使用 | | `location` | LOCATION | normal | 可直接安装使用 | | `coarseLocation` | APPROXIMATELY_LOCATION | normal | 可直接安装使用 | | `bluetooth` | ACCESS_BLUETOOTH | normal | 可直接安装使用 | | `photoLibrary` / `readStorage` | READ_IMAGEVIDEO | system_basic | 需 ACL 签名 | | `storage` | WRITE_IMAGEVIDEO | system_basic | 需 ACL 签名 | | `contacts` | READ_CONTACTS | system_basic | 需 ACL 签名 | | `writeContacts` | WRITE_CONTACTS | system_basic | 需 ACL 签名 | 鸿蒙**不支持**(无系统 API):`phone`、`phoneState`、`sms`、`readSms`、`receiveSms`、`overlay`、`writeSettings`。 #### 配置文件说明 | 文件 | 权限数量 | 用途 | | --- | --- | --- | | `module.json5` | 5 项(normal) | **默认**,调试证书可直接安装 | | `module.normal.json5` | 5 项 | 与 `module.json5` 相同 | | `module.full.json5` | 9 项 | 含相册/通讯录等 system_basic 权限,需 ACL 后启用 | 启用完整权限:将 `module.full.json5` 的内容覆盖 `module.json5`,并在 AppGallery Connect 配置 ACL 签名。 #### 安装报 9568289 时 说明当前 `module.json5` 中仍包含未签名的 system_basic 权限(如 `READ_CONTACTS`)。请确认使用的是默认的 5 项 normal 版本;若已手动合并 `module.full.json5`,需先完成 ACL 白名单与 Profile 签名配置。 相册选图场景仍推荐使用系统 **PhotoViewPicker**(`uni.chooseImage`),无需申请媒体读写权限。 #### 系统设置里找不到相册权限? 默认 `module.json5` 为可安装调试包,**未声明** `READ_IMAGEVIDEO` / `WRITE_IMAGEVIDEO`,因此: - 系统「设置 → 应用 → 本应用 → 权限」中**不会出现**相册/媒体开关 - 插件会将相册相关权限标记为 **未声明(restricted)** - 演示页可直接点 **「选图」** 试用,走系统相册选择器,不依赖该权限 若业务必须申请媒体读写权限:用 `module.full.json5` 覆盖 `module.json5`,在 AppGallery Connect 配置 ACL 并重新签名安装后,系统设置中才会出现对应权限项。 ## 错误码 | errCode | 说明 | | --- | --- | | 9020001 | 当前环境不支持 | | 9020002 | 用户拒绝授权 | | 9020003 | 权限不支持当前平台 | | 9020004 | 打开系统设置失败 | | 9020005 | 权限检查失败 | | 9020006 | 权限申请失败 | ## 注意事项 1. **H5 不支持**:本插件仅适用于 App(Android / iOS)与 Harmony 端。 2. **需自定义基座**:UTS 插件修改后需在 HBuilderX 中重新制作自定义基座或云打包。 3. **永久拒绝**:用户选择「不再询问」后,需引导用户通过 `openAppSettings()` 手动开启。 4. **特殊权限**:Android 悬浮窗(`overlay`)和系统设置(`writeSettings`)需跳转系统设置页授权,申请结果可能为 `notDetermined`。 --- ## 使用规范 本文档面向集成本插件的 App 开发者,说明 **必须遵守的约束**、**推荐做法** 和 **上架审核注意事项**。 --- ### 1. 基本约束(必须遵守) #### 1.1 用户主动触发 `requestPermission` / `requestPermissions` **必须由真实用户手势触发**,例如按钮 `click` / `tap`。 ```vue ``` 原因:Android / iOS / Harmony 运行时权限弹窗均面向用户明确操作;冷启动批量申请易触发拒绝,且不符合各应用商店审核惯例。 #### 1.2 先声明、后申请 **仅安装插件不够**,必须在各端配置文件中声明所需权限,否则: | 平台 | 未声明后果 | | --- | --- | | Android | `SecurityException`、申请无弹窗或直接失败 | | iOS | 崩溃或无授权弹窗 | | Harmony | 系统设置无对应开关,插件返回 `restricted` 或 9020003 | 详细配置见 [权限配置说明](#权限配置说明)。 #### 1.3 按需申请 只申请业务实际使用的权限。在功能入口处按需 `requestPermission`,不要一次性申请全部权限。 ```js // ✅ 审核页 async function handleRequestCamera() { const granted = await requestPermission('camera') if (!granted) { uni.showModal({ title: '需要相机权限', content: getPermissionSettingsGuide('camera', '相机'), confirmText: '去设置', success: (res) => { if (res.confirm) openPermissionSettings('camera') }, }) return } // 继续业务逻辑 } ``` #### 1.4 平台差异处理 调用前可通过 `getSupportedPermissions()` 过滤当前平台不支持的 Key,避免向用户展示无效入口。 ```js const supported = getSupportedPermissions() const canUseOverlay = supported.includes('overlay') // 仅 Android 为 true ``` --- ### 2. 推荐集成流程 ``` 进入功能页 ↓ checkPermission(key) ──→ granted → 执行业务 ↓ notDetermined / denied 用户点击「申请权限」 ↓ requestPermission(key) ↓ 系统弹窗 ──→ 拒绝 → getPermissionSettingsGuide + openPermissionSettings ↓ 同意 granted → 执行业务 ``` #### 2.1 Promise 封装(推荐) 项目可复用 `@/utils/permission-manager.js`: ```js import { checkPermission, requestPermission, requestPermissions, openPermissionSettings, getPermissionSettingsGuide, ensurePermission, getSupportedPermissions, } from '@/utils/permission-manager' ``` | 方法 | 用途 | | --- | --- | | `checkPermission(key)` | 检查状态,返回 `{ granted, status }` | | `requestPermission(key)` | 申请权限,返回 `boolean` | | `requestPermissions(keys[])` | 批量申请,返回 `{ allGranted, results }` | | `openPermissionSettings(key)` | 按权限类型跳转系统设置 | | `getPermissionSettingsGuide(key, label)` | 获取跳转前的引导文案 | | `ensurePermission(key, { openSettings })` | 检查 → 申请 → 可选跳转设置 | #### 2.2 直接调用 UTS API(callback 风格) ```js import { requestPermission } from '@/uni_modules/m-permission-manager' requestPermission({ permission: 'camera', success(res) { if (res.granted) { /* ... */ } }, fail(err) { console.error(err.errCode, err.errMsg) }, }) ``` #### 2.3 永久拒绝后的引导 用户选择「不再询问」或多次拒绝后,应引导至系统设置: ```js const granted = await requestPermission('bluetooth') if (!granted) { uni.showModal({ title: '蓝牙权限未授予', content: getPermissionSettingsGuide('bluetooth', '蓝牙'), confirmText: '去设置', success: (res) => { if (res.confirm) openPermissionSettings('bluetooth') }, }) } ``` 各端跳转行为: | 平台 | `openPermissionSettings` 行为 | | --- | --- | | Android 普通权限 | 应用详情 → 权限列表 | | Android `overlay` | 悬浮窗权限设置页 | | Android `writeSettings` | 修改系统设置权限页 | | iOS | 本 App 设置页(需 manifest 声明对应 UsageDescription) | | Harmony | 系统设置 → 应用详情 | --- ### 3. 各端特别注意 #### 3.1 Android - **Android 13+**:相册 / 存储自动映射 `READ_MEDIA_IMAGES` / `READ_MEDIA_VIDEO` - **Android 12+**:蓝牙自动映射 `BLUETOOTH_CONNECT` / `BLUETOOTH_SCAN` - **特殊权限**:`overlay`、`writeSettings` 需跳转系统设置页,申请结果可能为 `notDetermined`,返回后需再次 `checkPermission` #### 3.2 iOS - 必须在 `privacyDescription` 中配置对应 `NS*UsageDescription`,否则无弹窗 - `storage` / `readStorage` 映射到相册权限(`PHPhotoLibrary`) - `coarseLocation` / `location` 均映射到定位授权 - **蓝牙**:需 `NSBluetoothAlwaysUsageDescription`;系统蓝牙开关在「设置 → 蓝牙」,App 授权在 App 设置页或「隐私与安全性 → 蓝牙」 #### 3.3 Harmony - 默认 `module.json5` 含 5 项 normal 权限,调试包可直接安装 - 相册 / 通讯录为 `system_basic`,需 ACL 签名 + `module.full.json5` - 相册选图推荐 `uni.chooseImage`(系统 PhotoViewPicker),无需媒体读写权限 - 未声明的 ACL 权限:检查返回 `restricted`,申请返回 9020003 --- ### 4. 错误码与用户提示 | errCode | 含义 | 建议提示 | | --- | --- | --- | | 9020001 | 当前环境不支持 | 请在 App 端使用 | | 9020002 | 用户拒绝授权 | 您拒绝了授权,可在设置中重新开启 | | 9020003 | 权限不支持当前平台 | 当前平台不支持该权限 | | 9020004 | 打开系统设置失败 | 无法打开系统设置,请手动前往 | | 9020005 | 权限检查失败 | 权限检查失败,请重试 | | 9020006 | 权限申请失败 | 权限申请失败,请重试 | --- ### 5. 上架审核注意事项 | 市场 | 注意点 | | --- | --- | | App Store | 每个 `NS*UsageDescription` 文案需与真实功能一致;不要申请未使用的权限 | | Google Play | 需在 Data safety 中声明权限用途;Android 13+ 媒体权限需按类型声明 | | 华为 / 鸿蒙 | 说明 `ohos.permission.*` 用途;system_basic 权限需 ACL 白名单 | | 国内 Android 市场 | 隐私合规检测会扫描 manifest 权限列表,确保与隐私政策一致 | --- ### 6. 自定义基座与发版 1. 导入或更新插件后,**必须重新制作自定义基座**或云打包 2. 修改 `manifest.json` 权限或鸿蒙 `module.json5` 后,需重新打包 3. iOS 修改 `privacyDescription` 后需重新打包,必要时删除旧 App 重装以重新触发授权弹窗 --- ### 7. 参考文档 - [readme](#m-permission-manager) — API 与快速开始 - [权限配置说明](#权限配置说明) — 三端权限文件配置详解 - [发布指南](#发布指南) — 插件市场发布填写参考 ## 权限配置说明 本文档说明集成本插件时,**各端需要修改哪些文件**、**如何配置权限**,以及插件内置配置文件的作用。 --- ### 1. 配置总览 | 平台 | 配置文件 | 配置方 | 说明 | | --- | --- | --- | --- | | **Android** | 宿主 `manifest.json` | 集成者 | 声明 `android.permission.*` | | **iOS** | 宿主 `manifest.json` | 集成者 | 声明 `NS*UsageDescription` | | **Harmony** | 插件 `utssdk/app-harmony/module.json5`(可选:`harmony-configs/entry/src/main/module.json5`) | 插件内置为主,集成者可切换 full 版或宿主覆盖 | > 插件负责**运行时检查与申请**;Android / iOS 的**静态声明**必须由宿主项目在 manifest 中完成。Harmony 权限由插件 module 合并进宿主包,集成者按需切换 normal / full 版本。 --- ### 2. Android 配置 #### 2.1 配置文件 **路径**:项目根目录 `manifest.json` **节点**:`app-plus.distribute.android.permissions` ```json { "app-plus": { "distribute": { "android": { "permissions": [ "", "", "", "", "", "", "", "", "" ] } } } } ``` #### 2.2 统一 Key 与 Android 权限映射 | 插件 Key | Android 权限 | 备注 | | --- | --- | --- | | `camera` | `CAMERA` | | | `photoLibrary` | `READ_MEDIA_IMAGES`(API 33+)或 `READ_EXTERNAL_STORAGE` | 插件按 SDK 自动选择 | | `storage` | `READ_MEDIA_IMAGES` + `READ_MEDIA_VIDEO`(API 33+)或 `WRITE/READ_EXTERNAL_STORAGE` | | | `readStorage` | 同 `photoLibrary` / 媒体读权限 | | | `location` | `ACCESS_FINE_LOCATION` | | | `coarseLocation` | `ACCESS_COARSE_LOCATION` | | | `microphone` | `RECORD_AUDIO` | | | `contacts` | `READ_CONTACTS` | | | `writeContacts` | `WRITE_CONTACTS` | | | `bluetooth` | `BLUETOOTH_CONNECT` + `BLUETOOTH_SCAN`(API 31+)或 `BLUETOOTH` + `BLUETOOTH_ADMIN` | | | `phone` | `CALL_PHONE` | | | `phoneState` | `READ_PHONE_STATE` | | | `sms` | `SEND_SMS` | | | `readSms` | `READ_SMS` | | | `receiveSms` | `RECEIVE_SMS` | | | `overlay` | 无 manifest 条目 | 通过 `Settings.canDrawOverlays` 检查 | | `writeSettings` | 无 manifest 条目 | 通过 `Settings.System.canWrite` 检查 | #### 2.3 注意 - 只声明业务使用的权限,避免过度申请 - Android 13+ 媒体权限使用 `READ_MEDIA_*`;插件仅在 **targetSdkVersion >= 33** 时动态申请新媒体权限,否则回退 `READ_EXTERNAL_STORAGE`(兼容 targetSdk 偏低的自定义基座) - `overlay`、`writeSettings` 需在 manifest 声明对应 capability 后,通过插件跳转系统设置页授权 --- ### 3. iOS 配置 #### 3.1 配置文件 **路径**:项目根目录 `manifest.json` **节点**:`app-plus.distribute.ios.privacyDescription` ```json { "app-plus": { "distribute": { "ios": { "privacyDescription": { "NSCameraUsageDescription": "需要使用相机进行拍照", "NSMicrophoneUsageDescription": "需要使用麦克风进行录音", "NSPhotoLibraryUsageDescription": "需要访问相册以选择图片", "NSPhotoLibraryAddUsageDescription": "需要保存图片到相册", "NSLocationWhenInUseUsageDescription": "需要获取位置信息", "NSContactsUsageDescription": "需要访问通讯录", "NSBluetoothAlwaysUsageDescription": "需要使用蓝牙连接周边设备" } } } } } ``` #### 3.2 统一 Key 与 Info.plist 键映射 | 插件 Key | Info.plist 键 | 备注 | | --- | --- | --- | | `camera` | `NSCameraUsageDescription` | | | `photoLibrary` | `NSPhotoLibraryUsageDescription` | | | `storage` | `NSPhotoLibraryUsageDescription` 或 `NSPhotoLibraryAddUsageDescription` | 映射到相册 | | `readStorage` | `NSPhotoLibraryUsageDescription` | 映射到相册 | | `location` | `NSLocationWhenInUseUsageDescription` | | | `coarseLocation` | `NSLocationWhenInUseUsageDescription` | 与精确定位共用 | | `microphone` | `NSMicrophoneUsageDescription` | | | `contacts` | `NSContactsUsageDescription` | | | `writeContacts` | `NSContactsUsageDescription` | 读写共用 | | `bluetooth` | `NSBluetoothAlwaysUsageDescription` | **必须配置**,否则 App 设置页无蓝牙开关 | #### 3.3 iOS 蓝牙特别说明 iOS 蓝牙涉及两个独立概念: | 概念 | 设置路径 | 配置要求 | | --- | --- | --- | | 系统蓝牙开关 | 设置 → 蓝牙 | 无需 manifest,用户手动打开 | | App 蓝牙授权 | 设置 → 本 App → 蓝牙,或 设置 → 隐私与安全性 → 蓝牙 | 需 `NSBluetoothAlwaysUsageDescription` + 重新打包 + App 曾触发弹窗 | Apple 不提供跳转到「隐私 → 蓝牙」的公开深链;插件 `openPermissionSettings('bluetooth')` 会打开 App 设置页并配合引导文案。 --- ### 4. Harmony 配置 #### 4.1 harmony-configs 要不要配? **使用 m-permission-manager 时,一般不需要在 `harmony-configs/` 里重复声明权限。** 鸿蒙端权限有两种配置路径: | 方式 | 配置文件 | 适用场景 | | --- | --- | --- | | **UTS 插件声明(推荐)** | `uni_modules/m-permission-manager/utssdk/app-harmony/module.json5` | 插件打包为鸿蒙子模块(HAR),权限对整个 App 生效 | | **宿主工程覆盖** | `harmony-configs/entry/src/main/module.json5` | 插件未覆盖的权限、或希望在宿主侧集中管理 | 鸿蒙官方规则:**已在子模块中声明的权限,主工程无需重复添加**,权限在整个应用中生效。 m-permission-manager 作为 UTS 插件,其 `module.json5` 会在编译时拷贝为插件子模块的 `src/main/module.json5`,因此**默认情况下宿主不必再配**。 当前项目的 `harmony-configs/` 主要用于: | 文件 | 用途 | | --- | --- | | `AppScope/app.json5` | 包名、版本、图标(HX 4.31+ 也可在 `manifest.json` → `app-harmony` 图形界面配置) | | `build-profile.json5` | 签名证书(`.cer` / `.p12` / `.p7b`) | | `entry/build-profile.json5` | release 混淆等构建选项 | | `entry/obfuscation-rules.txt` | 混淆规则 | **若要在 harmony-configs 中配置权限**(可选,非必须): 1. 先运行一次鸿蒙编译,从 `unpackage/dist/dev/app-harmony/entry/src/main/module.json5` 复制完整文件到 `harmony-configs/entry/src/main/module.json5` 2. **仅修改** `module.requestPermissions` 节点,其他节点不要删(uni-app 是**文件级覆盖**,不是 JSON 节点合并) 3. 不要与插件已声明的权限重复 > 集成 m-permission-manager 时,优先改插件内的 `module.json5` / `module.full.json5`,而不是 harmony-configs。 #### 4.2 插件内置文件 **目录**:`uni_modules/m-permission-manager/utssdk/app-harmony/` | 文件 | 权限数量 | APL 等级 | 用途 | | --- | --- | --- | --- | | `module.json5` | 5 项 | normal | **默认生效**,调试证书可直接安装 | | `module.normal.json5` | 5 项 | normal | 与 `module.json5` 相同,备份参考 | | `module.full.json5` | 9 项 | normal + system_basic | 含相册 / 通讯录,需 ACL 签名 | **权限说明文案**:`resources/base/element/string.json` #### 4.3 默认 module.json5(5 项 normal) | 插件 Key | ohos.permission | 说明 | | --- | --- | --- | | `camera` | `CAMERA` | | | `microphone` | `MICROPHONE` | | | `location` | `LOCATION` | | | `coarseLocation` | `APPROXIMATELY_LOCATION` | | | `bluetooth` | `ACCESS_BLUETOOTH` | | #### 4.4 module.full.json5 额外 4 项(system_basic,需 ACL) | 插件 Key | ohos.permission | APL | 说明 | | --- | --- | --- | --- | | `photoLibrary` / `readStorage` | `READ_IMAGEVIDEO` | system_basic | 需 ACL | | `storage` | `WRITE_IMAGEVIDEO` | system_basic | 需 ACL | | `contacts` | `READ_CONTACTS` | system_basic | 需 ACL | | `writeContacts` | `WRITE_CONTACTS` | system_basic | 需 ACL | #### 4.5 如何切换 full 版本 1. 将 `module.full.json5` 的内容**覆盖** `module.json5` 2. 在 AppGallery Connect 配置 ACL 白名单 3. 使用正式 Profile 重新签名打包 4. 重新制作自定义基座或云打包 #### 4.6 未声明 ACL 权限时的插件行为 | 场景 | 检查 status | 申请结果 | | --- | --- | --- | | 相册 / 通讯录等未在 module.json5 声明 | `restricted` | 9020003,附未声明说明 | | 系统设置 | 无对应开关 | 引导使用 `uni.chooseImage` 或切换 full 版本 | #### 4.7 安装报 9568289 说明 `module.json5` 中含有未签名的 system_basic 权限。请确认使用默认 5 项 normal 版本;若已合并 full 版本,需先完成 ACL 与 Profile 签名。 #### 4.8 鸿蒙不支持的功能 以下插件 Key 在鸿蒙返回 `unsupported`:`phone`、`phoneState`、`sms`、`readSms`、`receiveSms`、`overlay`、`writeSettings`。 --- ### 5. 配置示例(按业务场景) #### 5.1 仅需相机 + 麦克风 **Android** manifest: ```json "permissions": [ "", "" ] ``` **iOS** privacyDescription: ```json "privacyDescription": { "NSCameraUsageDescription": "需要使用相机", "NSMicrophoneUsageDescription": "需要使用麦克风" } ``` **Harmony**:默认 `module.json5` 已包含,无需修改。 #### 5.2 需要蓝牙 **Android** manifest 增加: ```json "", "" ``` **iOS** privacyDescription 增加: ```json "NSBluetoothAlwaysUsageDescription": "需要使用蓝牙连接周边设备" ``` **Harmony**:默认 `module.json5` 已包含 `ACCESS_BLUETOOTH`。 #### 5.3 需要相册读写(Harmony 完整权限) 1. 用 `module.full.json5` 覆盖 `module.json5` 2. 配置 ACL 签名 3. Android 增加 `READ_MEDIA_IMAGES` / `READ_MEDIA_VIDEO` 4. iOS 增加 `NSPhotoLibraryUsageDescription` > 若仅需选图不上传,推荐使用 `uni.chooseImage`,三端均无需媒体读写权限。 --- ### 6. 配置后必做 1. **重新制作自定义基座**或云打包(UTS 插件 + manifest 变更均须重新打包) 2. iOS 修改 `privacyDescription` 后建议删除旧 App 重装,以重新触发授权弹窗 3. Harmony 切换 `module.json5` 后需重新签名安装 --- ### 7. 相关文档 - [readme](#m-permission-manager) — API 与权限 Key 对照表 - [使用规范](#使用规范) — 集成流程与审核注意事项 - [发布指南](#发布指南) — 插件市场发布填写参考 ## 发布指南 面向插件作者,说明如何将本插件提交到 DCloud 插件市场,以及后台各字段的填写参考。 --- ### 发布前检查清单 #### 代码与文档 - [ ] `package.json` 中 `id`、`version`、`description`、`keywords` 已填写 - [ ] `dcloudext.type` 为 `uts` - [ ] `dcloudext.declaration` 中 ads / data / permissions 已如实填写 - [ ] `uni_modules.platforms` 中各端支持情况准确(vue3=y,H5/小程序=x) - [ ] `readme.md` 完整(安装、API、权限、FAQ) - [ ] `使用规范.md`、`权限配置说明.md`、`changelog.md` 已更新 - [ ] `index.d.ts` 与 `index.js` 导出一致 #### 功能验证 - [ ] Android 真机:相机 / 麦克风 / 定位 / 蓝牙申请与检查 - [ ] Android 12+ 真机:蓝牙 `BLUETOOTH_CONNECT` / `BLUETOOTH_SCAN` - [ ] Android 13+ 真机:相册 `READ_MEDIA_IMAGES` 自动映射 - [ ] Android 真机:悬浮窗(`overlay`)、修改系统设置(`writeSettings`)跳转设置页 - [ ] iOS 14+ 真机:相机 / 麦克风 / 定位 / 蓝牙 / 相册 - [ ] iOS 真机:拒绝后 `openPermissionSettings('bluetooth')` 引导文案正确 - [ ] Harmony API 12+ 真机:5 项 normal 权限申请(默认 `module.json5`) - [ ] Harmony 真机:相册 ACL 未声明时返回 `restricted` / 9020003 - [ ] 拒绝授权时引导跳转系统设置 - [ ] H5 环境明确不可用(9020001) #### 打包验证 - [ ] 自定义基座可正常运行 - [ ] 云打包 / 本地打包正式包可正常运行 - [ ] 修改 UTS 代码后已重新制作基座 --- ### 提交到插件市场 1. 登录 [DCloud 插件市场](https://ext.dcloud.net.cn/) 2. 进入 **我的插件** → **发布插件** 3. 插件类型选择 **UTS 插件** 4. 上传 `uni_modules/m-permission-manager` 目录(或打包 zip) 5. 按下方表格填写市场展示信息 --- ### 市场后台填写参考 #### 基本信息 | 字段 | 填写内容 | | --- | --- | | **插件名称** | m-permission-manager 跨端权限管理 | | **插件 ID** | m-permission-manager | | **插件类型** | UTS 插件 | | **价格** | 免费(或按实际定价) | | **版本号** | 与 `package.json` → `version` 一致,如 `1.0.0` | #### 标题(建议) ``` m-permission-manager - uni-app 跨端权限管理(Android/iOS/鸿蒙) ``` #### 一句话描述 ``` UTS 权限插件,Android / iOS / Harmony 三端统一 API,检查与申请运行时权限,支持跳转系统设置。 ``` #### 详细描述(可直接粘贴) ``` m-permission-manager 是 uni-app Vue3 跨端权限管理 UTS 插件,支持 Android、iOS、Harmony 三端。 【核心能力】 · 17 种统一权限 Key,三端通用命名 · 同步 / 异步检查权限状态 · 单个 / 批量申请权限 · 按权限类型跳转系统设置页 · 获取当前平台支持的权限列表 【平台支持】 · Android:17 项权限(含悬浮窗、短信、电话等 Android 专属) · iOS:10 项通用权限(相机、相册、定位、麦克风、蓝牙、通讯录等) · Harmony:10 项通用权限(默认 5 项 normal 可直接安装,相册/通讯录需 ACL) 【集成方式】 1. 导入 uni_modules 插件 2. 在宿主 manifest.json(Android/iOS)及鸿蒙 module.json5 中声明所需权限 3. 使用 @/utils/permission-manager Promise 封装或直接调用 UTS API 详细权限配置见插件内[权限配置说明](#权限配置说明),集成规范见[使用规范](#使用规范)。 ``` #### 标签 / 关键词 ``` 权限, permission, 运行时权限, 蓝牙, 相机, 定位, Android, iOS, Harmony, 鸿蒙, UTS ``` #### 使用说明(市场「使用说明」字段) 可直接粘贴以下内容,或填写插件 readme 链接: ``` 【快速开始】 1. 从插件市场导入 m-permission-manager 到项目 uni_modules 目录 2. 在 manifest.json 中声明宿主所需权限(Android permissions / iOS privacyDescription) 鸿蒙端见插件 utssdk/app-harmony/module.json5,详见[权限配置说明](#权限配置说明) 3. 重新制作自定义基座或云打包(UTS 插件不支持标准基座) 4. 在代码中调用: import { checkPermission, requestPermission, openPermissionSettings, } from '@/utils/permission-manager' const result = await checkPermission('camera') const granted = await requestPermission('camera') if (!granted) { await openPermissionSettings('camera') } 【重要说明】 · 仅支持 App 端(Android / iOS / Harmony),不支持 H5 与小程序 · 插件负责运行时检查与申请,宿主仍需在 manifest 中声明静态权限 · iOS 蓝牙需在 privacyDescription 中配置 NSBluetoothAlwaysUsageDescription · 鸿蒙相册/通讯录为 system_basic 权限,默认调试包未声明,需 ACL 签名后启用 完整文档: · [readme](#m-permission-manager) — API 与快速开始 · [使用规范](#使用规范) — 集成约束与推荐流程 · [权限配置说明](#权限配置说明) — 三端权限文件配置详解 ``` #### 权限与隐私声明(`dcloudext.declaration` 对应项) | 字段 | 填写内容 | | --- | --- | | **是否含广告** | 无 | | **是否采集数据** | 不上传任何用户数据,仅在本地检查与申请系统权限 | | **权限说明** | Android:宿主 manifest 声明对应 android.permission.*;iOS:宿主 manifest 声明 NSCameraUsageDescription 等 Info.plist 键;Harmony:插件 module.json5 声明 ohos.permission.*,运行时申请 | #### 平台支持(与 package.json 一致) | 平台 | 支持情况 | | --- | --- | | uni-app Vue3 | ✅ | | uni-app Vue2 | ❌ | | H5 | ❌ | | 小程序 | ❌ | | Android App | ✅(minSdk 23) | | iOS App | ✅(min iOS 14) | | Harmony App | ✅(API 12+) | #### 截图建议(4–6 张) 1. 权限演示页截图(三端权限列表与状态) 2. Promise 封装调用代码示例 3. Android 系统权限弹窗(相机 / 蓝牙) 4. iOS 隐私授权弹窗 5. manifest.json 权限配置示例 6. 三端权限支持对照表 --- ### 市场 FAQ 预填 **Q:为什么必须自定义基座?** A:本插件为 UTS 原生插件,标准基座不包含。需制作含本插件的自定义基座或云打包。 **Q:H5 能用吗?** A:不支持。仅 App 端(Android / iOS / Harmony)。 **Q:安装插件后还需要配置权限吗?** A:需要。Android / iOS 必须在宿主 `manifest.json` 中声明静态权限与隐私说明;鸿蒙由插件 `module.json5` 合并,但 ACL 权限需额外签名。详见[权限配置说明](#权限配置说明)。 **Q:三端权限 Key 一样吗?** A:统一使用 `camera`、`microphone`、`location`、`bluetooth` 等 Key,插件内部映射到各平台原生权限。部分 Key 仅 Android 支持(如 `overlay`、`sms`),调用时会返回 `unsupported`。 **Q:iOS 蓝牙在 App 设置里找不到?** A:需在 manifest 配置 `NSBluetoothAlwaysUsageDescription` 并重新打包,且 App 需曾触发蓝牙权限弹窗。若 App 设置页无该项,请前往「设置 → 隐私与安全性 → 蓝牙」。系统蓝牙开关在「设置 → 蓝牙」,与应用授权无关。 **Q:鸿蒙相册权限申请失败?** A:默认 `module.json5` 仅含 5 项 normal 权限,未声明相册读写。相册选图推荐 `uni.chooseImage`;若必须申请媒体权限,需用 `module.full.json5` 覆盖并配置 ACL 签名。 **Q:用户永久拒绝后怎么办?** A:调用 `openPermissionSettings(permissionKey)` 跳转对应系统设置页,配合 `getPermissionSettingsGuide()` 展示引导文案。 --- ### 版本号规范 遵循 [语义化版本](https://semver.org/lang/zh-CN/): | 变更类型 | 版本 bump | 示例 | | --- | --- | --- | | 不兼容 API 变更 | major | 2.0.0 | | 新增功能(兼容) | minor | 1.1.0 | | Bug 修复 | patch | 1.0.1 | 每次发版同步更新 `package.json` → `version` 和 `changelog.md`。 --- ### 联系方式 发布前请在 `package.json` → `dcloudext.contact.qq` 填写维护者 QQ,或在插件市场后台配置联系方式。 --- ### 参考链接 - [UTS 插件开发文档](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html) - [插件市场发布流程](https://uniapp.dcloud.net.cn/plugin/publish.html) - 插件内 [readme](#m-permission-manager) - 插件内 [使用规范](#使用规范) - 插件内 [权限配置说明](#权限配置说明) ## 更新日志 ### 1.0.2(2026-06-17) - 修复 Android:相册/存储/蓝牙申请失败(`targetSdkVersion` 与 `READ_MEDIA_*` / `BLUETOOTH_*` 不匹配) - 权限映射同时校验设备 API 与宿主 `targetSdkVersion`,自定义基座 targetSdk < 33 时回退旧版权限 ### 1.0.1(2026-06-17) - 新增 `openPermissionSettings(permission)` 按权限类型跳转系统设置 - 新增 `getPermissionSettingsGuide(permission, label)` 引导文案 - Android:`overlay` / `writeSettings` 跳转对应系统设置页 - 新增 [发布指南](#发布指南)、[使用规范](#使用规范)、[权限配置说明](#权限配置说明) 文档 - readme 补充 iOS 蓝牙说明与 `NSBluetoothAlwaysUsageDescription` ### 1.0.0(2026-05-29) - 初始版本 - 支持 Android / iOS / Harmony 三端统一权限检查与申请 - 提供同步 / 异步 API 及 `@/utils/permission-manager` Promise 封装