← API | 列表 | 权限弹窗说明
提示信息
# 项目权限通知整理指引

本文档详细整理了【同伴】项目目前的权限申请逻辑、触发时机、UI 样式以及 Android 和 iOS 的差异点。

## 1. 权限概览表

| 权限类型 | 核心用途 | 触发时机 | UI 样式 |
| :--- | :--- | :--- | :--- |
| **推送通知** | 接收私信、信号回复、系统提醒 | 首次进入“消息”页 | 3D 动画底部弹窗 ([PermissionSheet](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/widgets/common/permission_sheet.dart#17-42)) |
| **地理位置** | 推荐附近用户、计算信号距离 | 首次进入“收件箱”页 | 水波纹动画底部弹窗 ([PermissionSheet](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/widgets/common/permission_sheet.dart#17-42)) |
| **相机** | 实名认证、拍摄头像/信号图片 | 身份核验、启动相机拍摄时 | 前置说明弹窗 ([PermissionUtil](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/core/utils/permission_util.dart#7-160)) + 系统弹窗 |
| **相册/存储** | 发送图片私信、上传个人主页图片 | 打开相册选择图片时 | 系统选择器 (微信样式) |
| **麦克风** | 录制语音信号、语音私信、声音签名 | 点击聊天栏“语音”图标时 | 前置说明弹窗 ([PermissionUtil](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/core/utils/permission_util.dart#7-160)) + 系统弹窗 |
| **跟踪 (iOS)** | 优化广告投放 (IDFA) | 隐私协议同意后 / 广告加载前 | 系统 ATT 弹窗 |

---

## 2. 核心权限深度解析

### 2.1 推送通知 (Push)
*   **触发路径**: [MessagesPage](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/features/chat/messages_page.dart#7-13) -> [_maybeAskPushPermission](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/features/chat/messages_page.dart#25-41)
*   **交互逻辑**: 
    - 检查 `SharedPreferences` 标记,确保每个版本仅主动引导一次。
    - 弹出自定义 [PermissionSheet](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/widgets/common/permission_sheet.dart#17-42)(带有摇摆的绿色铃铛动画)。
*   **双端差异**:
    - **Android**: 调用 `Permission.notification.request()`。
    - **iOS**: 通过 `MethodChannel` 调用原生 `registerAPNS`,触发系统的 `badge/sound/alert` 授权申请。

### 2.2 地理位置 (Location)
*   **触发路径**: [SignalInboxPage](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/features/signal/signal_inbox_page.dart#11-17) -> [_checkLocationPermission](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/features/signal/signal_inbox_page.dart#56-82)
*   **交互逻辑**:
    - 进入收件箱时若位置权限为 `isDenied`,弹出 [PermissionSheet](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/widgets/common/permission_sheet.dart#17-42)(蓝色水波纹动画)。
    - 强调“严格保密具体坐标,仅用于距离计算”以消除用户疑虑。
*   **关键代码**: `PermissionSheet.show(context, type: PermissionSheetType.location)`

### 2.3 媒体权限 (Camera / Microphone / Photos)
*   **触发逻辑**: 遵循“用到才申请”原则。
*   **样式策略**:
    - **Android**: 在调用系统弹窗前,先展示一个圆角的 `AlertDialog` 作为“前置教育说明”。
    - **iOS**: 麦克风、相机、相册权限直接触发系统弹窗(在 [PermissionUtil](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/core/utils/permission_util.dart#7-160) 中已配置 iOS 跳过自定义 rationale 说明,以符合 App Store 审核习惯)。
*   **组件**: 使用 [AppAssetPicker](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/core/utils/app_asset_picker.dart#5-51) (基于微信样式选择器),用户体验非常原生且流畅。

---

## 3. UI 样式规范

项目采用了双层引导策略,以提高权限通过率:

### A. 预引导底部弹窗 ([PermissionSheet](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/widgets/common/permission_sheet.dart#17-42))
*   **适用场景**: 推送、位置。
*   **设计要点**: 
    - 虽然是底部弹窗,但使用了 `useRootNavigator: true` 覆盖 TabBar。
    - 包含高品质微动画(Flare/Tween 效果)。
    - 提供“以后再说”作为软拒绝出口,避免用户直接在系统层面“永久拒绝”。

### B. 前置说明对话框 ([PermissionUtil](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/core/utils/permission_util.dart#7-160))
*   **适用场景**: 相机、麦克风。
*   - **文案规范**: 明确告知用户“为了[具体功能],【同伴】需要获取您的[XX]权限”。
*   - **路径引导**: 如果用户点击了系统“永久拒绝”,对话框会自动变为“去设置”引导。

---

## 4. Android 与 iOS 的技术差异总结

| 特性 | Android (Material/Aero) | iOS (Cupertino/Liquid) |
| :--- | :--- | :--- |
| **权限清单** | [AndroidManifest.xml](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/android/app/src/main/AndroidManifest.xml) 中声明 | [Info.plist](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/ios/Runner/Info.plist) 中配置 `UsageDescription` 字符串 |
| **存储权限** | 区分 `READ_EXTERNAL_STORAGE` 等 | 主要是 `NSPhotoLibraryUsageDescription` |
| **权限说明** | 建议在 Android 13+ 使用 POST_NOTIFICATIONS 前置说明 | 审核严,说明文案必须与 Info.plist 保持高度一致 |
| **广告跟踪** | 无需显式弹窗 (依赖 OAID/GAID) | 必须弹出 `AppTrackingTransparency` 授权框 |
| **位置模式** | 粗略/精确位置可选 | 始终包含 "Precise Location" 开关 (iOS 14+) |

---

## 5. 权限说明文案 (多语言/文案备份)

> [!TIP]
> 文案位于 [lib/features/settings/system_permissions_page.dart](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/lib/features/settings/system_permissions_page.dart) 和 [Info.plist](file:///Applications/MAMP/htdocs/flutterProject/%E5%90%8C%E4%BC%B4_old/flutter_project/ios/Runner/Info.plist)。

*   **位置**: “为了给您推荐附近的用户和信号,需要获取您的位置信息。”
*   **相机**: “为了进行实名认证及人脸核身,需要访问您的相机。”
*   **麦克风**: “需要访问麦克风以录制语音信号。”
*   **相册**: “需要访问相册以发布图片信号。”