### 4. 权限申请流程图设计:规范、路径与输出物 #### 适用场景 当开发团队需要将权限申请逻辑实现为代码时,必须先依据业务需求绘制标准化流程图。该流程图服务于以下场景: - **新功能开发**:首次申请某项 Runtime 权限。 - **权限策略变更**:系统版本升级或隐私政策调整,需要重新设计申请链路。 - **技术评审**:架构师或安全审查人员评估申请逻辑是否合理、是否包含降级兜底。 --- #### 前置条件 1. 已确认所需权限列表(精确到 `Manifest.permission` 常量)。 2. 已明确每个权限的申请触发时机(用户点击、功能入口、后台任务)。 3. 团队成员掌握至少一种流程图绘制工具(如 draw.io、Visio、PlantUML 或 Mermaid)。 --- #### 操作步骤 ##### 4.1 流程图符号规范 所有申请流程必须遵循以下符号体系,确保多项目间可读性一致: | 符号 | 形状 / 颜色 | 名称 | 描述 | |------|-------------|------|------| | S | 圆角矩形 / 蓝底白字 | 开始 / 结束 | 流程起点和终点 | | P | 矩形 / 绿底白字 | 处理步骤 | 可执行的代码操作(如 `ContextCompat.checkSelfPermission`) | | ? | 菱形 / 橙底白字 | 决策节点 | 条件判断(如“权限是否已授予”) | | D | 矩形 + 左侧竖线 / 紫底白字 | 预定义流程 | 跳转到子流程图(如“系统授权对话框”子流程) | | D | 平行四边形 / 青底白字 | 文档 / 输出物 | 生成或读取的数据文件(如 `PermissionGrantResult`) | | | 带箭头实线 / 深灰 | 流线 | 流程控制方向 | > **强制要求**:同一项目中只使用以上 6 种符号,禁止自行发明新形状或颜色。 ##### 4.2 主流程分支 标准的权限申请流程图应包含以下 **3 条分支路径**: - **分支 A(已授予)** `开始 → 检查权限(自检) → 决策:已授予/未授予 → 已授予 → 直接执行功能 → 结束` - **分支 B(可以继续请求)** `已授予? 未授予 → 决策:shouldShowRationale → 否 → 调用requestPermissions → 系统授权对话框 → 监听ActivityResult → 决策:用户授权/拒绝` - **分支 C(需要解释后请求)** `决策:shouldShowRationale → 是 → 显示自定义解释弹窗 → 用户确认 → 调用requestPermissions → 同上` ##### 4.3 决策节点 每个流程图中的决策节点必须标注明确的 **Y / N** 标签,且所有分支必须终结于统一的“结束”节点: | 决策节点位置 | 判断条件 | Y(是)分支 | N(否)分支 | |-------------|---------|------------|------------| | D1 | `checkSelfPermission == PERMISSION_GRANTED` | 直接执行 | 进入 D2 | | D2 | `shouldShowRequestPermissionRationale` | 显示解释弹窗 | 直接请求 | | D3 | `resultCode == Activity.RESULT_OK && granted.length > 0` | 执行功能 | 降级 UI 或提示 | > 对于“永不再次询问”场景,必须在 D2 的子流程中增加一个额外决策节点,检测用户是否勾选了“不再询问”。若为 `true`,则直接跳转到“引导用户前往设置”的处理步骤。 ##### 4.4 输出物标注 每个处理步骤必须标注其输出物(数据或状态)。标注格式为 **【输出:<产出名称>】**,置于步骤框下方或右侧说明框内: | 处理步骤 | 输出物说明 | |----------|-----------| | `checkSelfPermission()` | 【输出:权限状态码】`int`(0=授予,-1=拒绝) | | `shouldShowRequestPermissionRationale()` | 【输出:布尔值】`true` 或 `false` | | `requestPermissions(array, requestCode)` | 【输出:PENDING_INTENT】系统授权请求实例 | | `ActivityResultCallback.onActivityResult()` | 【输出:授权结果表】`PermissionGrantResult` 对象集合 | --- #### 输入输出物 | 类型 | 名称 | 来源 / 去向 | 格式 / 载体 | |------|------|-------------|-------------| | **输入** | `AndroidManifest.xml` 权限声明 | 项目源码 | XML 文件 | | **输入** | 用户交互事件(按钮点击、页面加载) | View 层事件 | Android `Intent` / `Handler` | | **输出** | 流程审批图(PDF / PNG) | 技术评审会议 | draw.io / PlantUML 导出 | | **输出** | `PermissionGraph.json` 机器可读版本 | CI 代码检查 | JSON 文件(含节点 ID、分支条件、输出物标签) | --- #### 责任边界 - **开发工程师**:绘制第一版流程图,确保符号规范、分支完整。 - **技术组长**:审查决策节点是否遗漏“永不询问”分支;确认输出物标注与实际 API 返回值一致。 - **测试工程师**:依据流程图设计测试用例,确保每一条分支路径都有对应的冒烟/回归用例。 --- #### 记录材料 | 材料编号 | 材料名称 | 保存形式 | 保留周期 | |----------|---------|----------|----------| | SOC-RP-04-01 | 权限申请流程图(SVG 源文件) | Git 仓库 /docs/flowchart | 整个项目生命周期 | | SOC-RP-04-02 | 流程图符号规范表 | Wiki / 团队协作文档 | 永久 | | SOC-RP-04-03 | 流程图评审意见记录表 | Jira / 工单系统评论 | 项目交付后 6 个月 | --- #### 异常处理 | 异常场景 | 流程图处理方案 | 输出物标注调整 | |----------|---------------|----------------| | 用户连续两次拒绝且勾选“不再询问” | 新增决策节点检测 `neverAskAgain`,直接跳转至“引导前往设置”步骤 | 【输出:引导意图】`Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)` | | 系统授权对话框异常弹出(如 Activity 被销毁) | 在 D3 前增加“Activity 是否存活”决策节点,若否,则结束流程并记录日志 | 【输出:异常日志】`W/PERMISSION: Activity destroyed` | | 权限声明在运行时被系统撤回 | 在“直接执行功能”前增加二次检查决策节点(兜底) | 【输出:撤回通知】`BroadcastReceiver.onReceive()` | --- #### 验收标准 1. 流程图包含 **≥ 3 条** 独立分支路径(已授予、可以请求、需要解释)。 2. 所有决策节点均标注 **Y / N** 且无未完结箭头。 3. 每个处理步骤下方或说明框内标有**【输出:<产出名称>】**。 4. 符号使用严格对齐规范表,颜色与形状不允许偏差。 5. 在代码评审中,流程图与实际代码路径 **100%** 匹配。 --- #### 本章核心 SVG:权限申请主流程图 权限申请主流程图 开始:触发权限请求 checkSelfPermission() 【输出:权限状态码】 D1 已授予? Y 直接执行功能 N shouldShowRationale() 【输出:布尔值】 D2 需解释? Y 显示自定义解释弹窗 N requestPermissions() 【输出:授权结果表】 结束:完成申请 > **使用说明**:该 SVG 可直接嵌入开发文档或 draw.io。所有节点与分支均遵循本章符号规范,输出物标注以黄色说明框呈现。