You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MyQRCode/docs/CAMERA_PERMISSION_README.md

7.6 KiB

相机授权功能实现说明

🎯 功能概述

为 MyQrCode 应用添加了完整的相机权限管理功能,包括权限检查、权限请求、权限状态显示和用户引导。

🔧 技术实现

1. 权限状态管理

ScannerViewModel 中添加了权限相关的状态:

@Published var cameraAuthorizationStatus: AVAuthorizationStatus = .notDetermined
@Published var showPermissionAlert = false

2. 权限检查流程

初始化时权限检查

override init() {
    super.init()
    checkCameraPermission() // 替换原来的 setupCaptureSession()
}

权限状态检查方法

private func checkCameraPermission() {
    switch AVCaptureDevice.authorizationStatus(for: .video) {
    case .authorized:
        // 已授权,设置相机会话
        setupCaptureSession()
        
    case .notDetermined:
        // 未确定,请求权限
        requestCameraPermission()
        
    case .denied, .restricted:
        // 被拒绝或受限,显示权限提示
        showPermissionAlert = true
        
    @unknown default:
        // 未知状态
        break
    }
}

3. 权限请求处理

自动权限请求

private func requestCameraPermission() {
    AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
        DispatchQueue.main.async {
            if granted {
                self?.cameraAuthorizationStatus = .authorized
                self?.setupCaptureSession()
            } else {
                self?.cameraAuthorizationStatus = .denied
                self?.showPermissionAlert = true
            }
        }
    }
}

手动权限刷新

func refreshCameraPermission() {
    checkCameraPermission()
}

4. 设置页面跳转

func openSettings() {
    if let settingsUrl = URL(string: UIApplication.openSettingsURLString) {
        UIApplication.shared.open(settingsUrl) { success in
            // 处理跳转结果
        }
    }
}

📱 用户界面

1. 权限状态视图

创建了 CameraPermissionView 来显示不同权限状态下的UI

未确定状态

  • 显示相机图标和说明文字
  • 提供"授予相机权限"按钮
  • 点击后自动请求权限

被拒绝状态

  • 显示权限被拒绝的说明
  • 提供"打开设置"按钮
  • 引导用户到系统设置中手动开启

受限状态

  • 显示权限受限的说明
  • 提供相应的解决方案

2. UI 组件结构

struct CameraPermissionView: View {
    let authorizationStatus: AVAuthorizationStatus
    let onRequestPermission: () -> Void
    let onOpenSettings: () -> Void
    
    var body: some View {
        VStack(spacing: 30) {
            // 相机图标
            Image(systemName: "camera.fill")
            
            // 标题和描述
            Text("camera_permission_title".localized)
            Text(getDescriptionText())
            
            // 操作按钮
            VStack(spacing: 15) {
                if authorizationStatus == .notDetermined {
                    // 请求权限按钮
                } else if authorizationStatus == .denied || authorizationStatus == .restricted {
                    // 打开设置按钮
                }
            }
        }
    }
}

3. 权限状态集成

ScannerView 中根据权限状态显示不同的UI

var body: some View {
    ZStack {
        if scannerViewModel.cameraAuthorizationStatus == .authorized {
            // 相机预览和扫描UI
            CameraPreviewView(...)
            ScanningOverlayView(...)
            // ... 其他扫描相关组件
        } else {
            // 权限相关UI
            CameraPermissionView(...)
        }
    }
}

🌐 多语言支持

1. 英文本地化

"camera_permission_title" = "Camera Permission Required";
"camera_permission_description" = "This app needs access to your camera to scan QR codes and barcodes. Please grant camera permission to continue.";
"camera_permission_denied" = "Camera access has been denied. Please enable camera permission in Settings to use the scanner.";
"request_camera_permission" = "Grant Camera Access";
"open_settings" = "Open Settings";

2. 中文本地化

"camera_permission_title" = "需要相机权限";
"camera_permission_description" = "此应用需要访问您的相机来扫描二维码和条形码。请授予相机权限以继续使用。";
"camera_permission_denied" = "相机访问被拒绝。请在设置中启用相机权限以使用扫描器。";
"request_camera_permission" = "授予相机权限";
"open_settings" = "打开设置";

🔄 权限状态监听

1. 自动状态更新

.onReceive(scannerViewModel.$cameraAuthorizationStatus) { status in
    if status == .authorized {
        logInfo("🎯 相机权限已授权,启动扫描", className: "ScannerView")
        scannerViewModel.startScanning()
    }
}

2. 扫描控制

.onAppear {
    // 只有在相机权限已授权时才启动扫描
    if scannerViewModel.cameraAuthorizationStatus == .authorized {
        scannerViewModel.startScanning()
    }
}

📋 权限状态类型

1. AVAuthorizationStatus 枚举

  • .notDetermined: 用户尚未做出选择
  • .authorized: 用户已授权访问相机
  • .denied: 用户拒绝访问相机
  • .restricted: 相机访问受限(如家长控制)

2. 状态转换流程

notDetermined → 请求权限 → authorized/denied
denied → 用户手动开启 → authorized
restricted → 需要管理员操作 → authorized

🧪 测试场景

1. 首次安装

  • 应用启动时自动请求权限
  • 用户可以选择允许或拒绝

2. 权限被拒绝

  • 显示权限被拒绝的说明
  • 提供打开设置的按钮
  • 用户可以从设置中重新开启

3. 权限恢复

  • 用户从设置返回后自动检测权限状态
  • 权限恢复后自动启动扫描功能

4. 权限受限

  • 显示相应的说明和解决方案
  • 引导用户联系管理员或检查设备设置

🔒 隐私和安全

1. 最小权限原则

  • 只请求必要的相机权限
  • 不收集或存储相机数据
  • 权限仅用于扫描功能

2. 用户控制

  • 用户可以随时在设置中关闭权限
  • 应用会优雅地处理权限变化
  • 提供清晰的权限说明

3. 错误处理

  • 权限被拒绝时提供友好的错误信息
  • 引导用户解决问题的方法
  • 不会因为权限问题导致应用崩溃

🚀 部署说明

1. Info.plist 配置

确保在 Info.plist 中添加相机权限描述:

<key>NSCameraUsageDescription</key>
<string>此应用需要访问相机来扫描二维码和条形码</string>

2. 权限测试

  • 在真机上测试权限流程
  • 验证不同权限状态下的UI显示
  • 测试权限恢复后的功能

3. 用户体验

  • 权限请求时机合理
  • 错误信息清晰易懂
  • 操作流程简单直观

📊 功能特性总结

  • 自动权限检查: 应用启动时自动检查相机权限
  • 智能权限请求: 只在必要时请求权限
  • 友好错误提示: 权限被拒绝时提供清晰的说明
  • 设置页面跳转: 一键跳转到系统设置
  • 状态自动更新: 权限状态变化时自动更新UI
  • 多语言支持: 支持中英文界面
  • 优雅降级: 无权限时显示相应的提示界面
  • 权限恢复: 权限恢复后自动启动扫描功能

通过这些功能,用户可以获得完整的相机权限管理体验,确保应用能够正常使用相机功能,同时尊重用户的隐私选择。