# m-permission-manager 使用规范
本文档面向集成本插件的 App 开发者,说明 **必须遵守的约束**、**推荐做法** 和 **上架审核注意事项**。
---
## 1. 基本约束(必须遵守)
### 1.1 用户主动触发
`requestPermission` / `requestPermissions` **必须由真实用户手势触发**,例如按钮 `click` / `tap`。
```vue
```
原因:Android / iOS / Harmony 运行时权限弹窗均面向用户明确操作;冷启动批量申请易触发拒绝,且不符合各应用商店审核惯例。
### 1.2 先声明、后申请
**仅安装插件不够**,必须在各端配置文件中声明所需权限,否则:
| 平台 | 未声明后果 |
| --- | --- |
| Android | `SecurityException`、申请无弹窗或直接失败 |
| iOS | 崩溃或无授权弹窗 |
| Harmony | 系统设置无对应开关,插件返回 `restricted` 或 9020003 |
详细配置见 [权限配置说明.md](./权限配置说明.md)。
### 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.md](./readme.md) — API 与快速开始
- [权限配置说明.md](./权限配置说明.md) — 三端权限文件配置详解
- [发布指南.md](./发布指南.md) — 插件市场发布填写参考