公告

👇欢迎大家关注公众号&私信交流👇

Skip to content

Flutter 系统权限申请与配置详解

引言:权限管理在现代应用中的重要性

权限管理是移动应用开发中的核心环节,它不仅关系到应用功能的正常实现,还直接影响用户体验和应用的安全性。随着移动操作系统对用户隐私保护的日益重视,合理的权限申请和管理策略变得至关重要。

本文将通过一个实际案例——开发一款名为"SecureApp"的安全权限管理应用——来详细介绍 Flutter 中系统权限申请与配置的技术细节和最佳实践。

权限管理概述

权限类型

  1. 普通权限:对用户隐私影响较小的权限,系统自动授予
  2. 危险权限:可能影响用户隐私的权限,需要用户明确授权
  3. 签名权限:只有相同签名的应用才能获得的权限
  4. 特殊权限:需要特殊处理的权限,如系统设置修改

权限申请流程

  1. 权限检查:检查应用是否已获得所需权限
  2. 权限请求:向用户请求权限
  3. 权限处理:根据用户响应处理权限结果
  4. 权限引导:在权限被拒绝时提供引导说明

项目背景:SecureApp 安全权限管理应用

我们的项目是开发一款名为 SecureApp 的安全权限管理应用,支持以下功能:

  • 智能权限申请和管理
  • 权限状态监控和提醒
  • 权限使用情况分析
  • 权限安全评估
  • 权限配置备份和恢复
  • 权限申请最佳实践指导

技术架构设计

整体架构

┌─────────────────────────────────────────────────────────────┐
│                    Flutter应用层                              │
├─────────────────────────────────────────────────────────────┤
│  权限UI  │  监控UI  │  分析UI  │  设置UI                    │
├─────────────────────────────────────────────────────────────┤
│                  权限服务管理层                                │
├─────────────────────────────────────────────────────────────┤
│              平台通道桥接层                                   │
├─────────────────────────────────────────────────────────────┤
│  Android Permission APIs  │  iOS Permission APIs       │
└─────────────────────────────────────────────────────────────┘

核心组件

  1. PermissionService:权限管理服务
  2. PermissionMonitorService:权限监控服务
  3. PermissionAnalyticsService:权限分析服务
  4. PermissionConfigService:权限配置服务
  5. PlatformChannel:平台通道通信

实现步骤详解

第一步:添加依赖和配置

首先,我们需要添加必要的依赖包:

yaml
dependencies:
  flutter:
    sdk: flutter
  permission_handler: ^10.2.0
  app_settings: ^5.1.1
  shared_preferences: ^2.2.0
  package_info_plus: ^4.2.0
  device_info_plus: ^9.1.0
  flutter_local_notifications: ^15.1.1
  intl: ^0.18.1
  json_annotation: ^4.8.1
  crypto: ^3.0.3

Android 平台需要配置权限:

xml
<!-- android/app/src/main/AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 网络权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    <!-- 存储权限 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

    <!-- 相机权限 -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <!-- 位置权限 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

    <!-- 联系人权限 -->
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />

    <!-- 短信权限 -->
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_SMS" />

    <!-- 电话权限 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.READ_CALL_LOG" />
    <uses-permission android:name="android.permission.WRITE_CALL_LOG" />

    <!-- 日历权限 -->
    <uses-permission android:name="android.permission.READ_CALENDAR" />
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />

    <!-- 传感器权限 -->
    <uses-permission android:name="android.permission.BODY_SENSORS" />
    <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />

    <!-- 麦克风权限 -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <!-- 通知权限 -->
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

    <!-- 应用使用统计权限 -->
    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />

    <!-- 安装未知应用权限 -->
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

    <!-- 系统设置权限 -->
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    <!-- 蓝牙权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <!-- NFC权限 -->
    <uses-permission android:name="android.permission.NFC" />

    <!-- Android 13+ 媒体权限 -->
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />

    <application>
        <!-- 权限配置 -->
        <meta-data
            android:name="android.max_aspect"
            android:value="2.1" />
    </application>
</manifest>

iOS 平台需要在 Info.plist 中添加权限说明:

xml
<!-- ios/Runner/Info.plist -->
<dict>
    <!-- 相机权限 -->
    <key>NSCameraUsageDescription</key>
    <string>此应用需要访问相机来拍摄照片和视频</string>

    <!-- 麦克风权限 -->
    <key>NSMicrophoneUsageDescription</key>
    <string>此应用需要访问麦克风来录制音频</string>

    <!-- 相册权限 -->
    <key>NSPhotoLibraryUsageDescription</key>
    <string>此应用需要访问相册来选择和管理照片</string>

    <!-- 位置权限 -->
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>此应用需要访问位置来提供基于位置的服务</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>此应用需要访问位置来提供后台位置服务</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>此应用需要访问位置来提供后台位置服务</string>

    <!-- 联系人权限 -->
    <key>NSContactsUsageDescription</key>
    <string>此应用需要访问联系人来提供联系人管理功能</string>

    <!-- 日历权限 -->
    <key>NSCalendarsUsageDescription</key>
    <string>此应用需要访问日历来提供日历管理功能</string>

    <!-- 提醒事项权限 -->
    <key>NSRemindersUsageDescription</key>
    <string>此应用需要访问提醒事项来提供提醒功能</string>

    <!-- 语音识别权限 -->
    <key>NSSpeechRecognitionUsageDescription</key>
    <string>此应用需要访问语音识别来提供语音输入功能</string>

    <!-- 蓝牙权限 -->
    <key>NSBluetoothAlwaysUsageDescription</key>
    <string>此应用需要访问蓝牙来提供蓝牙设备连接功能</string>
    <key>NSBluetoothPeripheralUsageDescription</key>
    <string>此应用需要访问蓝牙来提供蓝牙设备连接功能</string>

    <!-- 健康数据权限 -->
    <key>NSHealthShareUsageDescription</key>
    <string>此应用需要访问健康数据来提供健康监测功能</string>
    <key>NSHealthUpdateUsageDescription</key>
    <string>此应用需要访问健康数据来提供健康监测功能</string>

    <!-- HomeKit权限 -->
    <key>NSHomeKitUsageDescription</key>
    <string>此应用需要访问HomeKit来提供智能家居控制功能</string>

    <!-- 运动数据权限 -->
    <key>NSMotionUsageDescription</key>
    <string>此应用需要访问运动数据来提供运动监测功能</string>

    <!-- 文件权限 -->
    <key>NSDocumentsFolderUsageDescription</key>
    <string>此应用需要访问文档文件夹来提供文件管理功能</string>

    <!-- 网络权限 -->
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
</dict>

iOS 平台还需要在 Podfile 中添加权限相关的依赖:

ruby
# ios/Podfile
platform :ios, '12.0'

target 'Runner' do
  use_frameworks!
  use_modular_headers!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

  # 权限相关依赖
  pod 'Permission-Camera', :path => '../node_modules/react-native-permissions/ios/Camera.podspec'
  pod 'Permission-Microphone', :path => '../node_modules/react-native-permissions/ios/Microphone.podspec'
  pod 'Permission-Photos', :path => '../node_modules/react-native-permissions/ios/Photos.podspec'
  pod 'Permission-Location', :path => '../node_modules/react-native-permissions/ios/Location.podspec'
  pod 'Permission-Contacts', :path => '../node_modules/react-native-permissions/ios/Contacts.podspec'
  pod 'Permission-Calendars', :path => '../node_modules/react-native-permissions/ios/Calendars.podspec'
  pod 'Permission-Reminders', :path => '../node_modules/react-native-permissions/ios/Reminders.podspec'
  pod 'Permission-Speech', :path => '../node_modules/react-native-permissions/ios/Speech.podspec'
  pod 'Permission-Bluetooth', :path => '../node_modules/react-native-permissions/ios/Bluetooth.podspec'
  pod 'Permission-Health', :path => '../node_modules/react-native-permissions/ios/Health.podspec'
  pod 'Permission-HomeKit', :path => '../node_modules/react-native-permissions/ios/HomeKit.podspec'
  pod 'Permission-Motion', :path => '../node_modules/react-native-permissions/ios/Motion.podspec'
  pod 'Permission-MediaLibrary', :path => '../node_modules/react-native-permissions/ios/MediaLibrary.podspec'
  pod 'Permission-Notifications', :path => '../node_modules/react-native-permissions/ios/Notifications.podspec'

  # iOS 14+ 特殊权限
  pod 'Permission-AppTrackingTransparency', :path => '../node_modules/react-native-permissions/ios/AppTrackingTransparency.podspec'

  # 本地网络权限 (iOS 14+)
  pod 'Permission-LocalNetwork', :path => '../node_modules/react-native-permissions/ios/LocalNetwork.podspec'

  target 'RunnerTests' do
    inherit! :search_paths
  end
end

# 后安装脚本,用于配置权限
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'

      # 配置权限相关设置
      if target.name.start_with?('Permission-')
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_CAMERA=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_MICROPHONE=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_PHOTOS=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_LOCATION=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_CONTACTS=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_CALENDARS=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_REMINDERS=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_SPEECH=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_BLUETOOTH=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_HEALTH=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_HOMEKIT=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_MOTION=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_MEDIA_LIBRARY=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_NOTIFICATIONS=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_APP_TRACKING_TRANSPARENCY=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_LOCAL_NETWORK=1'
      end
    end
  end
end

对于使用 Flutter 的项目,Podfile 配置应该如下:

ruby
# ios/Podfile
platform :ios, '12.0'

# CocoaPods analytics sends network requests to Google Analytics
# To disable this, uncomment the following line
# ENV['COCOAPODS_DISABLE_STATS'] = 'true'

# Prevent CocoaPods from generating a Pods.xcodeproj with Xcode 12+.
install! 'cocoapods', :deterministic_uuids => false

target 'Runner' do
  use_frameworks!
  use_modular_headers!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

  # 权限相关配置
  pod 'permission_handler', :path => '../.symlinks/plugins/permission_handler/ios'

  # 如果需要特定权限的额外配置
  # pod 'AppTrackingTransparency', '~> 2.0'  # iOS 14+ 广告追踪权限
  # pod 'CoreBluetooth', '~> 1.0'            # 蓝牙权限
  # pod 'CoreLocation', '~> 1.0'              # 位置权限
  # pod 'AVFoundation', '~> 1.0'             # 相机和麦克风权限
  # pod 'Photos', '~> 1.0'                    # 相册权限
  # pod 'Contacts', '~> 1.0'                  # 联系人权限
  # pod 'EventKit', '~> 1.0'                   # 日历和提醒权限
  # pod 'Speech', '~> 1.0'                    # 语音识别权限
  # pod 'HealthKit', '~> 1.0'                 # 健康数据权限
  # pod 'HomeKit', '~> 1.0'                   # HomeKit权限
  # pod 'CoreMotion', '~> 1.0'                 # 运动数据权限
  # pod 'MediaPlayer', '~> 1.0'               # 媒体库权限
  # pod 'UserNotifications', '~> 1.0'         # 通知权限

  target 'RunnerTests' do
    inherit! :search_paths
  end
end

# 后安装脚本,用于配置权限和构建设置
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      # 设置最低部署目标版本
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'

      # 配置权限相关设置
      case target.name
      when 'permission_handler'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_CAMERA=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_MICROPHONE=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_PHOTOS=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_LOCATION=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_CONTACTS=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_CALENDARS=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_REMINDERS=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_SPEECH=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_BLUETOOTH=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_HEALTH=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_HOMEKIT=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_MOTION=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_MEDIA_LIBRARY=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_NOTIFICATIONS=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_APP_TRACKING_TRANSPARENCY=1'
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'PERMISSION_CRITICAL_ALERTS=1'
      end

      # 修复 Xcode 14+ 的构建问题
      if config.build_settings['WRAPPER_EXTENSION'] == 'bundle'
        config.build_settings['DEVELOPMENT_TEAM'] = 'YourTeamID'
      end
    end
  end
end

第二步:创建权限数据模型

dart
// lib/models/permission_info.dart
import 'package:json_annotation/json_annotation.dart';
import 'package:permission_handler/permission_handler.dart';

part 'permission_info.g.dart';

@JsonSerializable()
class PermissionInfo {
  final Permission permission;
  final String name;
  final String description;
  final String rationale;
  final PermissionType type;
  final PermissionCategory category;
  final PermissionStatus status;
  final bool isRequired;
  final DateTime? lastRequested;
  final int requestCount;
  final bool isPermanentlyDenied;
  final bool isLimited;
  final bool isRestricted;
  final bool isProvisional;

  PermissionInfo({
    required this.permission,
    required this.name,
    required this.description,
    required this.rationale,
    required this.type,
    required this.category,
    required this.status,
    this.isRequired = false,
    this.lastRequested,
    this.requestCount = 0,
    this.isPermanentlyDenied = false,
    this.isLimited = false,
    this.isRestricted = false,
    this.isProvisional = false,
  });

  factory PermissionInfo.fromJson(Map<String, dynamic> json) => _$PermissionInfoFromJson(json);
  Map<String, dynamic> toJson() => _$PermissionInfoToJson(this);

  // 获取权限状态描述
  String get statusDescription {
    switch (status) {
      case PermissionStatus.granted:
        return '已授权';
      case PermissionStatus.denied:
        return '已拒绝';
      case PermissionStatus.restricted:
        return '受限制';
      case PermissionStatus.limited:
        return '有限授权';
      case PermissionStatus.permanentlyDenied:
        return '永久拒绝';
      case PermissionStatus.provisional:
        return '临时授权';
      default:
        return '未知状态';
    }
  }

  // 获取权限状态图标
  String get statusIcon {
    switch (status) {
      case PermissionStatus.granted:
        return '✅';
      case PermissionStatus.denied:
        return '❌';
      case PermissionStatus.restricted:
        return '🔒';
      case PermissionStatus.limited:
        return '⚠️';
      case PermissionStatus.permanentlyDenied:
        return '🚫';
      case PermissionStatus.provisional:
        return '🔄';
      default:
        return '❓';
    }
  }

  // 获取权限类型描述
  String get typeDescription {
    switch (type) {
      case PermissionType.normal:
        return '普通权限';
      case PermissionType.dangerous:
        return '危险权限';
      case PermissionType.signature:
        return '签名权限';
      case PermissionType.special:
        return '特殊权限';
    }
  }

  // 获取权限类别描述
  String get categoryDescription {
    switch (category) {
      case PermissionCategory.storage:
        return '存储';
      case PermissionCategory.camera:
        return '相机';
      case PermissionCategory.microphone:
        return '麦克风';
      case PermissionCategory.location:
        return '位置';
      case PermissionCategory.contacts:
        return '联系人';
      case PermissionCategory.sms:
        return '短信';
      case PermissionCategory.phone:
        return '电话';
      case PermissionCategory.calendar:
        return '日历';
      case PermissionCategory.sensors:
        return '传感器';
      case PermissionCategory.bluetooth:
        return '蓝牙';
      case PermissionCategory.nfc:
        return 'NFC';
      case PermissionCategory.network:
        return '网络';
      case PermissionCategory.system:
        return '系统';
      case PermissionCategory.notification:
        return '通知';
      case PermissionCategory.other:
        return '其他';
    }
  }

  // 是否需要特殊处理
  bool get needsSpecialHandling {
    return isPermanentlyDenied || isRestricted || isLimited;
  }

  // 是否可以请求
  bool get canRequest {
    return status == PermissionStatus.denied || status == PermissionStatus.permanentlyDenied;
  }

  // 复制并更新状态
  PermissionInfo copyWith({
    PermissionStatus? status,
    DateTime? lastRequested,
    int? requestCount,
    bool? isPermanentlyDenied,
    bool? isLimited,
    bool? isRestricted,
    bool? isProvisional,
  }) {
    return PermissionInfo(
      permission: permission,
      name: name,
      description: description,
      rationale: rationale,
      type: type,
      category: category,
      status: status ?? this.status,
      isRequired: isRequired,
      lastRequested: lastRequested ?? this.lastRequested,
      requestCount: requestCount ?? this.requestCount,
      isPermanentlyDenied: isPermanentlyDenied ?? this.isPermanentlyDenied,
      isLimited: isLimited ?? this.isLimited,
      isRestricted: isRestricted ?? this.isRestricted,
      isProvisional: isProvisional ?? this.isProvisional,
    );
  }
}

// 权限类型
enum PermissionType {
  normal,
  dangerous,
  signature,
  special,
}

// 权限类别
enum PermissionCategory {
  storage,
  camera,
  microphone,
  location,
  contacts,
  sms,
  phone,
  calendar,
  sensors,
  bluetooth,
  nfc,
  network,
  system,
  notification,
  other,
}

// 权限组
class PermissionGroup {
  final String name;
  final String description;
  final List<Permission> permissions;
  final PermissionCategory category;
  final bool isRequired;

  PermissionGroup({
    required this.name,
    required this.description,
    required this.permissions,
    required this.category,
    this.isRequired = false,
  });

  // 获取权限组状态
  PermissionStatus get status {
    bool allGranted = permissions.every((permission) =>
        _getPermissionStatus(permission) == PermissionStatus.granted);

    if (allGranted) return PermissionStatus.granted;

    bool anyDenied = permissions.any((permission) =>
        _getPermissionStatus(permission) == PermissionStatus.denied ||
        _getPermissionStatus(permission) == PermissionStatus.permanentlyDenied);

    if (anyDenied) return PermissionStatus.denied;

    return PermissionStatus.denied;
  }

  // 获取权限状态(简化实现)
  PermissionStatus _getPermissionStatus(Permission permission) {
    // 这里应该调用实际的权限检查
    return PermissionStatus.denied;
  }

  // 获取权限组描述
  String get statusDescription {
    switch (status) {
      case PermissionStatus.granted:
        return '已授权';
      case PermissionStatus.denied:
        return '部分或全部未授权';
      default:
        return '未知状态';
    }
  }
}

// 权限配置
class PermissionConfig {
  final Map<Permission, PermissionInfo> permissions;
  final List<PermissionGroup> groups;
  final Map<PermissionCategory, List<Permission>> categoryPermissions;

  PermissionConfig({
    required this.permissions,
    required this.groups,
    required this.categoryPermissions,
  });

  // 获取权限信息
  PermissionInfo? getPermissionInfo(Permission permission) {
    return permissions[permission];
  }

  // 获取权限组
  PermissionGroup? getPermissionGroup(String name) {
    try {
      return groups.firstWhere((group) => group.name == name);
    } catch (e) {
      return null;
    }
  }

  // 获取类别权限
  List<Permission> getCategoryPermissions(PermissionCategory category) {
    return categoryPermissions[category] ?? [];
  }

  // 获取所有必需权限
  List<Permission> get requiredPermissions {
    return permissions.entries
        .where((entry) => entry.value.isRequired)
        .map((entry) => entry.key)
        .toList();
  }

  // 获取所有已授权权限
  List<Permission> get grantedPermissions {
    return permissions.entries
        .where((entry) => entry.value.status == PermissionStatus.granted)
        .map((entry) => entry.key)
        .toList();
  }

  // 获取所有未授权权限
  List<Permission> get deniedPermissions {
    return permissions.entries
        .where((entry) => entry.value.status != PermissionStatus.granted)
        .map((entry) => entry.key)
        .toList();
  }
}

// 权限请求结果
class PermissionRequestResult {
  final Map<Permission, PermissionStatus> results;
  final bool allGranted;
  final bool anyGranted;
  final bool anyPermanentlyDenied;
  final bool anyDenied;
  final DateTime timestamp;

  PermissionRequestResult({
    required this.results,
    required this.timestamp,
  }) : allGranted = results.values.every((status) => status == PermissionStatus.granted),
       anyGranted = results.values.any((status) => status == PermissionStatus.granted),
       anyPermanentlyDenied = results.values.any((status) => status == PermissionStatus.permanentlyDenied),
       anyDenied = results.values.any((status) => status == PermissionStatus.denied || status == PermissionStatus.permanentlyDenied);

  // 获取授权的权限
  List<Permission> get grantedPermissions {
    return results.entries
        .where((entry) => entry.value == PermissionStatus.granted)
        .map((entry) => entry.key)
        .toList();
  }

  // 获取拒绝的权限
  List<Permission> get deniedPermissions {
    return results.entries
        .where((entry) => entry.value == PermissionStatus.denied || entry.value == PermissionStatus.permanentlyDenied)
        .map((entry) => entry.key)
        .toList();
  }

  // 获取永久拒绝的权限
  List<Permission> get permanentlyDeniedPermissions {
    return results.entries
        .where((entry) => entry.value == PermissionStatus.permanentlyDenied)
        .map((entry) => entry.key)
        .toList();
  }

  // 获取结果描述
  String get resultDescription {
    if (allGranted) return '所有权限已授权';
    if (anyGranted) return '部分权限已授权';
    return '所有权限被拒绝';
  }
}

第三步:创建权限管理服务

dart
// lib/services/permission_service.dart
import 'dart:async';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:app_settings/app_settings.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:device_info_plus/device_info_plus.dart';
import '../models/permission_info.dart';

class PermissionService {
  static final PermissionService _instance = PermissionService._internal();
  factory PermissionService() => _instance;
  PermissionService._internal();

  static const MethodChannel _permissionChannel = MethodChannel('secure_app/permission');

  final StreamController<PermissionEvent> _permissionEventStreamController = StreamController<PermissionEvent>.broadcast();
  PermissionConfig? _permissionConfig;

  // 权限事件流
  Stream<PermissionEvent> get permissionEventStream => _permissionEventStreamController.stream;

  // 初始化权限服务
  Future<void> initialize() async {
    try {
      await _loadPermissionConfig();
      await _checkAllPermissions();
    } catch (e) {
      throw PermissionException('初始化权限服务失败: $e');
    }
  }

  // 加载权限配置
  Future<void> _loadPermissionConfig() async {
    try {
      final platform = Platform.isAndroid ? 'android' : 'ios';
      final configData = await _permissionChannel.invokeMethod('loadPermissionConfig', {'platform': platform});

      final permissions = <Permission, PermissionInfo>{};
      final groups = <PermissionGroup>[];
      final categoryPermissions = <PermissionCategory, List<Permission>>{};

      // 解析权限配置
      for (final permissionData in configData['permissions']) {
        final permission = _parsePermission(permissionData['permission']);
        final permissionInfo = PermissionInfo(
          permission: permission,
          name: permissionData['name'],
          description: permissionData['description'],
          rationale: permissionData['rationale'],
          type: _parsePermissionType(permissionData['type']),
          category: _parsePermissionCategory(permissionData['category']),
          status: PermissionStatus.denied,
          isRequired: permissionData['isRequired'] ?? false,
        );

        permissions[permission] = permissionInfo;

        // 按类别分组
        final category = permissionInfo.category;
        if (!categoryPermissions.containsKey(category)) {
          categoryPermissions[category] = [];
        }
        categoryPermissions[category]!.add(permission);
      }

      // 解析权限组
      for (final groupData in configData['groups']) {
        final groupPermissions = <Permission>[];
        for (final permissionName in groupData['permissions']) {
          final permission = _parsePermission(permissionName);
          if (permissions.containsKey(permission)) {
            groupPermissions.add(permission);
          }
        }

        groups.add(PermissionGroup(
          name: groupData['name'],
          description: groupData['description'],
          permissions: groupPermissions,
          category: _parsePermissionCategory(groupData['category']),
          isRequired: groupData['isRequired'] ?? false,
        ));
      }

      _permissionConfig = PermissionConfig(
        permissions: permissions,
        groups: groups,
        categoryPermissions: categoryPermissions,
      );
    } catch (e) {
      throw PermissionException('加载权限配置失败: $e');
    }
  }

  // 解析权限
  Permission _parsePermission(String permissionName) {
    switch (permissionName) {
      case 'camera':
        return Permission.camera;
      case 'microphone':
        return Permission.microphone;
      case 'storage':
        return Permission.storage;
      case 'photos':
        return Permission.photos;
      case 'videos':
        return Permission.videos;
      case 'audio':
        return Permission.audio;
      case 'contacts':
        return Permission.contacts;
      case 'location':
        return Permission.location;
      case 'locationAlways':
        return Permission.locationAlways;
      case 'locationWhenInUse':
        return Permission.locationWhenInUse;
      case 'notification':
        return Permission.notification;
      case 'phone':
        return Permission.phone;
      case 'sms':
        return Permission.sms;
      case 'calendar':
        return Permission.calendar;
      case 'sensors':
        return Permission.sensors;
      case 'bluetooth':
        return Permission.bluetooth;
      case 'bluetoothAdvertise':
        return Permission.bluetoothAdvertise;
      case 'bluetoothConnect':
        return Permission.bluetoothConnect;
      case 'bluetoothScan':
        return Permission.bluetoothScan;
      case 'nfc':
        return Permission.nfc;
      case 'criticalAlerts':
        return Permission.criticalAlerts;
      case 'appTrackingTransparency':
        return Permission.appTrackingTransparency;
      case 'feedback':
        return Permission.feedback;
      case 'mediaLibrary':
        return Permission.mediaLibrary;
      case 'photosAddOnly':
        return Permission.photosAddOnly;
      case 'reminders':
        return Permission.reminders;
      case 'speech':
        return Permission.speech;
      case 'unknown':
        return Permission.unknown;
      default:
        return Permission.unknown;
    }
  }

  // 解析权限类型
  PermissionType _parsePermissionType(String type) {
    switch (type) {
      case 'normal':
        return PermissionType.normal;
      case 'dangerous':
        return PermissionType.dangerous;
      case 'signature':
        return PermissionType.signature;
      case 'special':
        return PermissionType.special;
      default:
        return PermissionType.dangerous;
    }
  }

  // 解析权限类别
  PermissionCategory _parsePermissionCategory(String category) {
    switch (category) {
      case 'storage':
        return PermissionCategory.storage;
      case 'camera':
        return PermissionCategory.camera;
      case 'microphone':
        return PermissionCategory.microphone;
      case 'location':
        return PermissionCategory.location;
      case 'contacts':
        return PermissionCategory.contacts;
      case 'sms':
        return PermissionCategory.sms;
      case 'phone':
        return PermissionCategory.phone;
      case 'calendar':
        return PermissionCategory.calendar;
      case 'sensors':
        return PermissionCategory.sensors;
      case 'bluetooth':
        return PermissionCategory.bluetooth;
      case 'nfc':
        return PermissionCategory.nfc;
      case 'network':
        return PermissionCategory.network;
      case 'system':
        return PermissionCategory.system;
      case 'notification':
        return PermissionCategory.notification;
      default:
        return PermissionCategory.other;
    }
  }

  // 检查所有权限状态
  Future<void> _checkAllPermissions() async {
    if (_permissionConfig == null) return;

    for (final entry in _permissionConfig!.permissions.entries) {
      final permission = entry.key;
      final permissionInfo = entry.value;

      try {
        final status = await permission.status;
        final isPermanentlyDenied = await permission.isPermanentlyDenied;
        final isLimited = await permission.isLimited;
        final isRestricted = await permission.isRestricted;

        final updatedInfo = permissionInfo.copyWith(
          status: status,
          isPermanentlyDenied: isPermanentlyDenied,
          isLimited: isLimited,
          isRestricted: isRestricted,
        );

        _permissionConfig!.permissions[permission] = updatedInfo;
      } catch (e) {
        // 处理权限检查错误
      }
    }
  }

  // 获取权限配置
  PermissionConfig? get permissionConfig => _permissionConfig;

  // 获取权限信息
  PermissionInfo? getPermissionInfo(Permission permission) {
    return _permissionConfig?.getPermissionInfo(permission);
  }

  // 检查权限状态
  Future<PermissionStatus> checkPermissionStatus(Permission permission) async {
    try {
      return await permission.status;
    } catch (e) {
      throw PermissionException('检查权限状态失败: $e');
    }
  }

  // 请求单个权限
  Future<PermissionStatus> requestPermission(Permission permission) async {
    try {
      final status = await permission.request();

      // 更新权限信息
      final permissionInfo = getPermissionInfo(permission);
      if (permissionInfo != null) {
        final updatedInfo = permissionInfo.copyWith(
          status: status,
          lastRequested: DateTime.now(),
          requestCount: permissionInfo.requestCount + 1,
          isPermanentlyDenied: await permission.isPermanentlyDenied,
        );

        _permissionConfig!.permissions[permission] = updatedInfo;
      }

      // 发送权限事件
      _permissionEventStreamController.add(PermissionEvent(
        type: PermissionEventType.requested,
        permission: permission,
        status: status,
        timestamp: DateTime.now(),
      ));

      return status;
    } catch (e) {
      throw PermissionException('请求权限失败: $e');
    }
  }

  // 请求多个权限
  Future<PermissionRequestResult> requestPermissions(List<Permission> permissions) async {
    try {
      final results = await permissions.request();

      // 更新权限信息
      for (final entry in results.entries) {
        final permission = entry.key;
        final status = entry.value;

        final permissionInfo = getPermissionInfo(permission);
        if (permissionInfo != null) {
          final updatedInfo = permissionInfo.copyWith(
            status: status,
            lastRequested: DateTime.now(),
            requestCount: permissionInfo.requestCount + 1,
            isPermanentlyDenied: await permission.isPermanentlyDenied,
          );

          _permissionConfig!.permissions[permission] = updatedInfo;
        }

        // 发送权限事件
        _permissionEventStreamController.add(PermissionEvent(
          type: PermissionEventType.requested,
          permission: permission,
          status: status,
          timestamp: DateTime.now(),
        ));
      }

      return PermissionRequestResult(
        results: results,
        timestamp: DateTime.now(),
      );
    } catch (e) {
      throw PermissionException('请求多个权限失败: $e');
    }
  }

  // 请求权限组
  Future<PermissionRequestResult> requestPermissionGroup(String groupName) async {
    final group = _permissionConfig?.getPermissionGroup(groupName);
    if (group == null) {
      throw PermissionException('权限组不存在: $groupName');
    }

    return await requestPermissions(group.permissions);
  }

  // 请求所有必需权限
  Future<PermissionRequestResult> requestRequiredPermissions() async {
    final requiredPermissions = _permissionConfig?.requiredPermissions ?? [];
    return await requestPermissions(requiredPermissions);
  }

  // 检查权限是否被永久拒绝
  Future<bool> isPermanentlyDenied(Permission permission) async {
    try {
      return await permission.isPermanentlyDenied;
    } catch (e) {
      throw PermissionException('检查权限永久拒绝状态失败: $e');
    }
  }

  // 检查权限是否受限
  Future<bool> isRestricted(Permission permission) async {
    try {
      return await permission.isRestricted;
    } catch (e) {
      throw PermissionException('检查权限受限状态失败: $e');
    }
  }

  // 检查权限是否有限授权
  Future<bool> isLimited(Permission permission) async {
    try {
      return await permission.isLimited;
    } catch (e) {
      throw PermissionException('检查权限有限授权状态失败: $e');
    }
  }

  // 打开应用设置
  Future<void> openAppSettings() async {
    try {
      await AppSettings.openAppSettings();
    } catch (e) {
      throw PermissionException('打开应用设置失败: $e');
    }
  }

  // 打开特定权限设置
  Future<void> openPermissionSettings(Permission permission) async {
    try {
      if (Platform.isAndroid) {
        // Android 打开应用设置页面
        await AppSettings.openAppSettings();
      } else {
        // iOS 打开特定权限设置
        await AppSettings.openAppSettings(type: _getAppSettingsType(permission));
      }
    } catch (e) {
      throw PermissionException('打开权限设置失败: $e');
    }
  }

  // 获取应用设置类型
  AppSettingsType _getAppSettingsType(Permission permission) {
    switch (permission) {
      case Permission.camera:
        return AppSettingsType.camera;
      case Permission.microphone:
        return AppSettingsType.microphone;
      case Permission.photos:
        return AppSettingsType.photos;
      case Permission.location:
        return AppSettingsType.location;
      case Permission.notification:
        return AppSettingsType.notification;
      default:
        return AppSettingsType.settings;
    }
  }

  // 检查是否应该显示权限说明
  bool shouldShowRationale(Permission permission) {
    final permissionInfo = getPermissionInfo(permission);
    if (permissionInfo == null) return false;

    // 首次请求或被拒绝后应该显示说明
    return permissionInfo.requestCount == 0 ||
           permissionInfo.status == PermissionStatus.denied;
  }

  // 获取权限说明文本
  String getRationaleText(Permission permission) {
    final permissionInfo = getPermissionInfo(permission);
    return permissionInfo?.rationale ?? '此应用需要此权限来提供相关功能';
  }

  // 保存权限配置
  Future<void> savePermissionConfig() async {
    try {
      final prefs = await SharedPreferences.getInstance();

      // 保存权限状态
      for (final entry in _permissionConfig!.permissions.entries) {
        final permission = entry.key;
        final permissionInfo = entry.value;

        await prefs.setString('permission_${permission.toString()}', permissionInfo.status.toString());
        await prefs.setInt('permission_${permission.toString()}_count', permissionInfo.requestCount);
        if (permissionInfo.lastRequested != null) {
          await prefs.setString('permission_${permission.toString()}_last', permissionInfo.lastRequested!.toIso8601String());
        }
      }
    } catch (e) {
      throw PermissionException('保存权限配置失败: $e');
    }
  }

  // 加载权限配置
  Future<void> loadPermissionConfig() async {
    try {
      final prefs = await SharedPreferences.getInstance();

      // 加载权限状态
      for (final entry in _permissionConfig!.permissions.entries) {
        final permission = entry.key;
        final permissionInfo = entry.value;

        final statusString = prefs.getString('permission_${permission.toString()}');
        final requestCount = prefs.getInt('permission_${permission.toString()}_count') ?? 0;
        final lastRequestedString = prefs.getString('permission_${permission.toString()}_last');

        if (statusString != null) {
          final status = _parsePermissionStatus(statusString);
          final lastRequested = lastRequestedString != null ? DateTime.parse(lastRequestedString) : null;

          final updatedInfo = permissionInfo.copyWith(
            status: status,
            requestCount: requestCount,
            lastRequested: lastRequested,
          );

          _permissionConfig!.permissions[permission] = updatedInfo;
        }
      }
    } catch (e) {
      throw PermissionException('加载权限配置失败: $e');
    }
  }

  // 解析权限状态
  PermissionStatus _parsePermissionStatus(String statusString) {
    switch (statusString) {
      case 'granted':
        return PermissionStatus.granted;
      case 'denied':
        return PermissionStatus.denied;
      case 'restricted':
        return PermissionStatus.restricted;
      case 'limited':
        return PermissionStatus.limited;
      case 'permanentlyDenied':
        return PermissionStatus.permanentlyDenied;
      case 'provisional':
        return PermissionStatus.provisional;
      default:
        return PermissionStatus.denied;
    }
  }

  // 获取权限统计信息
  PermissionStatistics getPermissionStatistics() {
    if (_permissionConfig == null) {
      return PermissionStatistics(
        totalPermissions: 0,
        grantedPermissions: 0,
        deniedPermissions: 0,
        permanentlyDeniedPermissions: 0,
        requiredPermissions: 0,
        requiredGrantedPermissions: 0,
      );
    }

    final totalPermissions = _permissionConfig!.permissions.length;
    final grantedPermissions = _permissionConfig!.grantedPermissions.length;
    final deniedPermissions = _permissionConfig!.deniedPermissions.length;
    final permanentlyDeniedPermissions = _permissionConfig!.permissions.values
        .where((info) => info.isPermanentlyDenied)
        .length;
    final requiredPermissions = _permissionConfig!.requiredPermissions.length;
    final requiredGrantedPermissions = _permissionConfig!.requiredPermissions
        .where((permission) => _permissionConfig!.permissions[permission]?.status == PermissionStatus.granted)
        .length;

    return PermissionStatistics(
      totalPermissions: totalPermissions,
      grantedPermissions: grantedPermissions,
      deniedPermissions: deniedPermissions,
      permanentlyDeniedPermissions: permanentlyDeniedPermissions,
      requiredPermissions: requiredPermissions,
      requiredGrantedPermissions: requiredGrantedPermissions,
    );
  }

  // 释放资源
  void dispose() {
    _permissionEventStreamController.close();
  }
}

// 权限事件
class PermissionEvent {
  final PermissionEventType type;
  final Permission permission;
  final PermissionStatus status;
  final DateTime timestamp;

  PermissionEvent({
    required this.type,
    required this.permission,
    required this.status,
    required this.timestamp,
  });
}

// 权限事件类型
enum PermissionEventType {
  requested,
  granted,
  denied,
  permanentlyDenied,
  restricted,
  limited,
}

// 权限统计信息
class PermissionStatistics {
  final int totalPermissions;
  final int grantedPermissions;
  final int deniedPermissions;
  final int permanentlyDeniedPermissions;
  final int requiredPermissions;
  final int requiredGrantedPermissions;

  PermissionStatistics({
    required this.totalPermissions,
    required this.grantedPermissions,
    required this.deniedPermissions,
    required this.permanentlyDeniedPermissions,
    required this.requiredPermissions,
    required this.requiredGrantedPermissions,
  });

  // 获取授权率
  double get grantRate {
    if (totalPermissions == 0) return 0.0;
    return grantedPermissions / totalPermissions;
  }

  // 获取必需权限授权率
  double get requiredGrantRate {
    if (requiredPermissions == 0) return 0.0;
    return requiredGrantedPermissions / requiredPermissions;
  }

  // 获取格式化的授权率
  String get formattedGrantRate {
    return '${(grantRate * 100).toStringAsFixed(1)}%';
  }

  // 获取格式化的必需权限授权率
  String get formattedRequiredGrantRate {
    return '${(requiredGrantRate * 100).toStringAsFixed(1)}%';
  }
}

// 权限异常
class PermissionException implements Exception {
  final String message;
  PermissionException(this.message);

  @override
  String toString() => message;
}

第四步:实现 Android 原生代码

kotlin
// android/app/src/main/kotlin/com/example/secure_app/PermissionPlugin.kt
package com.example.secure_app

import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel

class PermissionPlugin(private val context: Context) : MethodChannel.MethodCallHandler {

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        when (call.method) {
            "loadPermissionConfig" -> {
                result.success(loadPermissionConfig(call.argument("platform") ?: "android"))
            }
            "checkPermissionStatus" -> {
                result.success(checkPermissionStatus(call.argument("permission") ?: ""))
            }
            "openPermissionSettings" -> {
                result.success(openPermissionSettings(call.argument("permission") ?: ""))
            }
            else -> {
                result.notImplemented()
            }
        }
    }

    private fun loadPermissionConfig(platform: String): Map<String, Any> {
        return mapOf(
            "permissions" to getPermissionConfig(),
            "groups" to getPermissionGroups()
        )
    }

    private fun getPermissionConfig(): List<Map<String, Any>> {
        return listOf(
            mapOf(
                "permission" to "camera",
                "name" to "相机",
                "description" to "访问相机拍摄照片和视频",
                "rationale" to "此应用需要相机权限来拍摄照片和视频,以便您可以使用拍照功能",
                "type" to "dangerous",
                "category" to "camera",
                "isRequired" to false
            ),
            mapOf(
                "permission" to "microphone",
                "name" to "麦克风",
                "description" to "访问麦克风录制音频",
                "rationale" to "此应用需要麦克风权限来录制音频,以便您可以使用录音功能",
                "type" to "dangerous",
                "category" to "microphone",
                "isRequired" to false
            ),
            mapOf(
                "permission" to "storage",
                "name" to "存储",
                "description" to "访问设备存储空间",
                "rationale" to "此应用需要存储权限来保存和读取文件,以便您可以管理文件",
                "type" to "dangerous",
                "category" to "storage",
                "isRequired" to false
            ),
            mapOf(
                "permission" to "location",
                "name" to "位置",
                "description" to "访问设备位置信息",
                "rationale" to "此应用需要位置权限来提供基于位置的服务,如导航和位置标记",
                "type" to "dangerous",
                "category" to "location",
                "isRequired" to false
            ),
            mapOf(
                "permission" to "contacts",
                "name" to "联系人",
                "description" to "访问设备联系人",
                "rationale" to "此应用需要联系人权限来管理联系人,以便您可以使用联系人功能",
                "type" to "dangerous",
                "category" to "contacts",
                "isRequired" to false
            ),
            mapOf(
                "permission" to "phone",
                "name" to "电话",
                "description" to "访问电话功能",
                "rationale" to "此应用需要电话权限来拨打电话和读取通话记录",
                "type" to "dangerous",
                "category" to "phone",
                "isRequired" to false
            ),
            mapOf(
                "permission" to "sms",
                "name" to "短信",
                "description" to "访问短信功能",
                "rationale" to "此应用需要短信权限来发送和接收短信",
                "type" to "dangerous",
                "category" to "sms",
                "isRequired" to false
            ),
            mapOf(
                "permission" to "calendar",
                "name" to "日历",
                "description" to "访问日历功能",
                "rationale" to "此应用需要日历权限来管理日程安排",
                "type" to "dangerous",
                "category" to "calendar",
                "isRequired" to false
            ),
            mapOf(
                "permission" to "sensors",
                "name" to "传感器",
                "description" to "访问设备传感器",
                "rationale" to "此应用需要传感器权限来监测设备状态和环境",
                "type" to "dangerous",
                "category" to "sensors",
                "isRequired" to false
            ),
            mapOf(
                "permission" to "bluetooth",
                "name" to "蓝牙",
                "description" to "访问蓝牙功能",
                "rationale" to "此应用需要蓝牙权限来连接蓝牙设备",
                "type" to "dangerous",
                "category" to "bluetooth",
                "isRequired" to false
            ),
            mapOf(
                "permission" to "nfc",
                "name" to "NFC",
                "description" to "访问NFC功能",
                "rationale" to "此应用需要NFC权限来读取NFC标签",
                "type" to "dangerous",
                "category" to "nfc",
                "isRequired" to false
            ),
            mapOf(
                "permission" to "notification",
                "name" to "通知",
                "description" to "发送通知",
                "rationale" to "此应用需要通知权限来发送重要信息提醒",
                "type" to if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) "dangerous" else "normal",
                "category" to "notification",
                "isRequired" to false
            )
        )
    }

    private fun getPermissionGroups(): List<Map<String, Any>> {
        return listOf(
            mapOf(
                "name" to "媒体权限",
                "description" to "相机、麦克风和存储权限",
                "permissions" to listOf("camera", "microphone", "storage"),
                "category" to "media",
                "isRequired" to false
            ),
            mapOf(
                "name" to "位置权限",
                "description" to "位置相关权限",
                "permissions" to listOf("location"),
                "category" to "location",
                "isRequired" to false
            ),
            mapOf(
                "name" to "通信权限",
                "description" to "联系人、电话和短信权限",
                "permissions" to listOf("contacts", "phone", "sms"),
                "category" to "communication",
                "isRequired" to false
            ),
            mapOf(
                "name" to "设备权限",
                "description" to "传感器、蓝牙和NFC权限",
                "permissions" to listOf("sensors", "bluetooth", "nfc"),
                "category" to "device",
                "isRequired" to false
            ),
            mapOf(
                "name" to "系统权限",
                "description" to "日历和通知权限",
                "permissions" to listOf("calendar", "notification"),
                "category" to "system",
                "isRequired" to false
            )
        )
    }

    private fun checkPermissionStatus(permission: String): String {
        val androidPermission = getAndroidPermission(permission)
        return when (ContextCompat.checkSelfPermission(context, androidPermission)) {
            PackageManager.PERMISSION_GRANTED -> "granted"
            PackageManager.PERMISSION_DENIED -> "denied"
            else -> "denied"
        }
    }

    private fun getAndroidPermission(permission: String): String {
        return when (permission) {
            "camera" -> android.Manifest.permission.CAMERA
            "microphone" -> android.Manifest.permission.RECORD_AUDIO
            "storage" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                android.Manifest.permission.READ_MEDIA_IMAGES
            } else {
                android.Manifest.permission.READ_EXTERNAL_STORAGE
            }
            "location" -> android.Manifest.permission.ACCESS_FINE_LOCATION
            "contacts" -> android.Manifest.permission.READ_CONTACTS
            "phone" -> android.Manifest.permission.READ_PHONE_STATE
            "sms" -> android.Manifest.permission.READ_SMS
            "calendar" -> android.Manifest.permission.READ_CALENDAR
            "sensors" -> android.Manifest.permission.BODY_SENSORS
            "bluetooth" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                android.Manifest.permission.BLUETOOTH_CONNECT
            } else {
                android.Manifest.permission.BLUETOOTH
            }
            "nfc" -> android.Manifest.permission.NFC
            "notification" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                android.Manifest.permission.POST_NOTIFICATIONS
            } else {
                ""
            }
            else -> ""
        }
    }

    private fun openPermissionSettings(permission: String): Boolean {
        return try {
            val intent = android.content.Intent(android.content.Intent.ACTION_APPLICATION_DETAILS_SETTINGS)
            intent.data = android.net.Uri.fromParts("package", context.packageName, null)
            intent.flags = android.content.Intent.FLAG_ACTIVITY_NEW_TASK
            context.startActivity(intent)
            true
        } catch (e: Exception) {
            false
        }
    }
}

第五步:实现 iOS 原生代码

swift
// ios/Runner/PermissionPlugin.swift
import Foundation
import UIKit
import AVFoundation
import Photos
import CoreLocation
import Contacts
import EventKit
import CoreBluetooth
import CoreMotion
import UserNotifications

class PermissionPlugin: NSObject, FlutterPlugin {

    static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "secure_app/permission", binaryMessenger: registrar.messenger())
        let instance = PermissionPlugin()
        registrar.addMethodCallDelegate(instance, channel: channel)
    }

    func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        switch call.method {
        case "loadPermissionConfig":
            result(loadPermissionConfig(call.arguments as? [String: Any]? ?? [:]))
        case "checkPermissionStatus":
            result(checkPermissionStatus(call.arguments as? String ?? ""))
        case "openPermissionSettings":
            result(openPermissionSettings(call.arguments as? String ?? ""))
        default:
            result(FlutterMethodNotImplemented)
        }
    }

    private func loadPermissionConfig(_ arguments: [String: Any]) -> [String: Any] {
        return [
            "permissions": getPermissionConfig(),
            "groups": getPermissionGroups()
        ]
    }

    private func getPermissionConfig() -> [[String: Any]] {
        return [
            [
                "permission": "camera",
                "name": "相机",
                "description": "访问相机拍摄照片和视频",
                "rationale": "此应用需要相机权限来拍摄照片和视频,以便您可以使用拍照功能",
                "type": "dangerous",
                "category": "camera",
                "isRequired": false
            ],
            [
                "permission": "microphone",
                "name": "麦克风",
                "description": "访问麦克风录制音频",
                "rationale": "此应用需要麦克风权限来录制音频,以便您可以使用录音功能",
                "type": "dangerous",
                "category": "microphone",
                "isRequired": false
            ],
            [
                "permission": "photos",
                "name": "相册",
                "description": "访问相册中的照片和视频",
                "rationale": "此应用需要相册权限来选择和管理照片,以便您可以使用相册功能",
                "type": "dangerous",
                "category": "storage",
                "isRequired": false
            ],
            [
                "permission": "location",
                "name": "位置",
                "description": "访问设备位置信息",
                "rationale": "此应用需要位置权限来提供基于位置的服务,如导航和位置标记",
                "type": "dangerous",
                "category": "location",
                "isRequired": false
            ],
            [
                "permission": "contacts",
                "name": "联系人",
                "description": "访问设备联系人",
                "rationale": "此应用需要联系人权限来管理联系人,以便您可以使用联系人功能",
                "type": "dangerous",
                "category": "contacts",
                "isRequired": false
            ],
            [
                "permission": "calendar",
                "name": "日历",
                "description": "访问日历功能",
                "rationale": "此应用需要日历权限来管理日程安排",
                "type": "dangerous",
                "category": "calendar",
                "isRequired": false
            ],
            [
                "permission": "bluetooth",
                "name": "蓝牙",
                "description": "访问蓝牙功能",
                "rationale": "此应用需要蓝牙权限来连接蓝牙设备",
                "type": "dangerous",
                "category": "bluetooth",
                "isRequired": false
            ],
            [
                "permission": "notification",
                "name": "通知",
                "description": "发送通知",
                "rationale": "此应用需要通知权限来发送重要信息提醒",
                "type": "dangerous",
                "category": "notification",
                "isRequired": false
            ],
            [
                "permission": "sensors",
                "name": "传感器",
                "description": "访问设备传感器",
                "rationale": "此应用需要传感器权限来监测设备状态和环境",
                "type": "dangerous",
                "category": "sensors",
                "isRequired": false
            ],
            [
                "permission": "speech",
                "name": "语音识别",
                "description": "访问语音识别功能",
                "rationale": "此应用需要语音识别权限来提供语音输入功能",
                "type": "dangerous",
                "category": "microphone",
                "isRequired": false
            ],
            [
                "permission": "mediaLibrary",
                "name": "媒体库",
                "description": "访问媒体库",
                "rationale": "此应用需要媒体库权限来管理媒体文件",
                "type": "dangerous",
                "category": "storage",
                "isRequired": false
            ]
        ]
    }

    private func getPermissionGroups() -> [[String: Any]] {
        return [
            [
                "name": "媒体权限",
                "description": "相机、麦克风和相册权限",
                "permissions": ["camera", "microphone", "photos"],
                "category": "media",
                "isRequired": false
            ],
            [
                "name": "位置权限",
                "description": "位置相关权限",
                "permissions": ["location"],
                "category": "location",
                "isRequired": false
            ],
            [
                "name": "通信权限",
                "description": "联系人和日历权限",
                "permissions": ["contacts", "calendar"],
                "category": "communication",
                "isRequired": false
            ],
            [
                "name": "设备权限",
                "description": "传感器和蓝牙权限",
                "permissions": ["sensors", "bluetooth"],
                "category": "device",
                "isRequired": false
            ],
            [
                "name": "系统权限",
                "description": "通知和语音识别权限",
                "permissions": ["notification", "speech"],
                "category": "system",
                "isRequired": false
            ]
        ]
    }

    private func checkPermissionStatus(_ permission: String) -> String {
        switch permission {
        case "camera":
            return checkCameraPermission()
        case "microphone":
            return checkMicrophonePermission()
        case "photos":
            return checkPhotosPermission()
        case "location":
            return checkLocationPermission()
        case "contacts":
            return checkContactsPermission()
        case "calendar":
            return checkCalendarPermission()
        case "bluetooth":
            return checkBluetoothPermission()
        case "notification":
            return checkNotificationPermission()
        case "sensors":
            return checkSensorsPermission()
        case "speech":
            return checkSpeechPermission()
        case "mediaLibrary":
            return checkMediaLibraryPermission()
        default:
            return "denied"
        }
    }

    private func checkCameraPermission() -> String {
        let status = AVCaptureDevice.authorizationStatus(for: .video)
        switch status {
        case .authorized:
            return "granted"
        case .denied:
            return "denied"
        case .restricted:
            return "restricted"
        case .notDetermined:
            return "denied"
        @unknown default:
            return "denied"
        }
    }

    private func checkMicrophonePermission() -> String {
        let status = AVCaptureDevice.authorizationStatus(for: .audio)
        switch status {
        case .authorized:
            return "granted"
        case .denied:
            return "denied"
        case .restricted:
            return "restricted"
        case .notDetermined:
            return "denied"
        @unknown default:
            return "denied"
        }
    }

    private func checkPhotosPermission() -> String {
        let status = PHPhotoLibrary.authorizationStatus()
        switch status {
        case .authorized:
            return "granted"
        case .denied:
            return "denied"
        case .restricted:
            return "restricted"
        case .notDetermined:
            return "denied"
        case .limited:
            return "limited"
        @unknown default:
            return "denied"
        }
    }

    private func checkLocationPermission() -> String {
        let status = CLLocationManager.authorizationStatus()
        switch status {
        case .authorizedAlways:
            return "granted"
        case .authorizedWhenInUse:
            return "granted"
        case .denied:
            return "denied"
        case .restricted:
            return "restricted"
        case .notDetermined:
            return "denied"
        @unknown default:
            return "denied"
        }
    }

    private func checkContactsPermission() -> String {
        let status = CNContactStore.authorizationStatus(for: .contacts)
        switch status {
        case .authorized:
            return "granted"
        case .denied:
            return "denied"
        case .restricted:
            return "restricted"
        case .notDetermined:
            return "denied"
        @unknown default:
            return "denied"
        }
    }

    private func checkCalendarPermission() -> String {
        let status = EKEventStore.authorizationStatus(for: .event)
        switch status {
        case .authorized:
            return "granted"
        case .denied:
            return "denied"
        case .restricted:
            return "restricted"
        case .notDetermined:
            return "denied"
        @unknown default:
            return "denied"
        }
    }

    private func checkBluetoothPermission() -> String {
        if #available(iOS 13.0, *) {
            let status = CBCentralManager.authorization
            switch status {
            case .allowedAlways:
                return "granted"
            case .denied:
                return "denied"
            case .restricted:
                return "restricted"
            case .notDetermined:
                return "denied"
            @unknown default:
                return "denied"
            }
        } else {
            return "granted"
        }
    }

    private func checkNotificationPermission() -> String {
        if #available(iOS 10.0, *) {
            let center = UNUserNotificationCenter.current()
            var notificationSettings: UNNotificationSettings?
            let semaphore = DispatchSemaphore(value: 0)

            center.getNotificationSettings { settings in
                notificationSettings = settings
                semaphore.signal()
            }

            semaphore.wait()

            guard let settings = notificationSettings else {
                return "denied"
            }

            switch settings.authorizationStatus {
            case .authorized:
                return "granted"
            case .denied:
                return "denied"
            case .provisional:
                return "provisional"
            case .notDetermined:
                return "denied"
            case .ephemeral:
                return "granted"
            @unknown default:
                return "denied"
            }
        } else {
            return "granted"
        }
    }

    private func checkSensorsPermission() -> String {
        if #available(iOS 11.0, *) {
            let status = CMMotionActivityManager.authorizationStatus()
            switch status {
            case .authorized:
                return "granted"
            case .denied:
                return "denied"
            case .restricted:
                return "restricted"
            case .notDetermined:
                return "denied"
            @unknown default:
                return "denied"
            }
        } else {
            return "granted"
        }
    }

    private func checkSpeechPermission() -> String {
        if #available(iOS 10.0, *) {
            let status = SFSpeechRecognizer.authorizationStatus()
            switch status {
            case .authorized:
                return "granted"
            case .denied:
                return "denied"
            case .restricted:
                return "restricted"
            case .notDetermined:
                return "denied"
            @unknown default:
                return "denied"
            }
        } else {
            return "granted"
        }
    }

    private func checkMediaLibraryPermission() -> String {
        if #available(iOS 9.3, *) {
            let status = MPMediaLibrary.authorizationStatus()
            switch status {
            case .authorized:
                return "granted"
            case .denied:
                return "denied"
            case .restricted:
                return "restricted"
            case .notDetermined:
                return "denied"
            @unknown default:
                return "denied"
            }
        } else {
            return "granted"
        }
    }

    private func openPermissionSettings(_ permission: String) -> Bool {
        guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
            return false
        }

        if UIApplication.shared.canOpenURL(settingsUrl) {
            UIApplication.shared.open(settingsUrl, completionHandler: nil)
            return true
        }

        return false
    }
}

第六步:创建主应用界面

dart
// lib/main.dart
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'widgets/permission_list_widget.dart';
import 'widgets/permission_group_widget.dart';
import 'widgets/permission_statistics_widget.dart';
import 'models/permission_info.dart';
import 'services/permission_service.dart';

void main() {
  runApp(const SecureApp());
}

class SecureApp extends StatelessWidget {
  const SecureApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SecureApp',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        brightness: Brightness.light,
      ),
      home: const MainScreen(),
    );
  }
}

class MainScreen extends StatefulWidget {
  const MainScreen({Key? key}) : super(key: key);

  @override
  _MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> with SingleTickerProviderStateMixin {
  late TabController _tabController;
  final PermissionService _permissionService = PermissionService();

  bool _isLoading = false;
  PermissionConfig? _permissionConfig;
  PermissionStatistics? _statistics;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 3, vsync: this);
    _initializeApp();
  }

  @override
  void dispose() {
    _tabController.dispose();
    _permissionService.dispose();
    super.dispose();
  }

  Future<void> _initializeApp() async {
    setState(() => _isLoading = true);

    try {
      await _permissionService.initialize();
      setState(() {
        _permissionConfig = _permissionService.permissionConfig;
        _statistics = _permissionService.getPermissionStatistics();
      });
    } catch (e) {
      _showErrorSnackBar('初始化应用失败: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  void _showErrorSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        backgroundColor: Colors.red,
      ),
    );
  }

  void _showSuccessSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        backgroundColor: Colors.green,
      ),
    );
  }

  Future<void> _refreshPermissions() async {
    try {
      await _permissionService.initialize();
      setState(() {
        _permissionConfig = _permissionService.permissionConfig;
        _statistics = _permissionService.getPermissionStatistics();
      });
      _showSuccessSnackBar('权限状态已更新');
    } catch (e) {
      _showErrorSnackBar('刷新权限状态失败: $e');
    }
  }

  Future<void> _requestAllRequiredPermissions() async {
    try {
      final result = await _permissionService.requestRequiredPermissions();

      if (result.allGranted) {
        _showSuccessSnackBar('所有必需权限已授权');
      } else if (result.anyGranted) {
        _showSuccessSnackBar('部分权限已授权');
      } else {
        _showErrorSnackBar('所有权限被拒绝');
      }

      await _refreshPermissions();
    } catch (e) {
      _showErrorSnackBar('请求权限失败: $e');
    }
  }

  Future<void> _openAppSettings() async {
    try {
      await _permissionService.openAppSettings();
    } catch (e) {
      _showErrorSnackBar('打开设置失败: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    if (_isLoading) {
      return const Scaffold(
        body: Center(child: CircularProgressIndicator()),
      );
    }

    if (_permissionConfig == null) {
      return Scaffold(
        appBar: AppBar(
          title: const Text('SecureApp'),
          backgroundColor: Colors.blue,
        ),
        body: const Center(
          child: Text('无法加载权限配置'),
        ),
      );
    }

    return Scaffold(
      appBar: AppBar(
        title: const Text('SecureApp'),
        backgroundColor: Colors.blue,
        actions: [
          IconButton(
            icon: const Icon(Icons.refresh),
            onPressed: _refreshPermissions,
            tooltip: '刷新',
          ),
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: _openAppSettings,
            tooltip: '设置',
          ),
        ],
        bottom: TabBar(
          controller: _tabController,
          tabs: const [
            Tab(icon: Icon(Icons.list), text: '权限列表'),
            Tab(icon: Icon(Icons.category), text: '权限分组'),
            Tab(icon: Icon(Icons.analytics), text: '统计分析'),
          ],
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: [
          // 权限列表页面
          PermissionListWidget(
            permissionConfig: _permissionConfig!,
            permissionService: _permissionService,
            onRefresh: _refreshPermissions,
          ),

          // 权限分组页面
          PermissionGroupWidget(
            permissionConfig: _permissionConfig!,
            permissionService: _permissionService,
            onRefresh: _refreshPermissions,
          ),

          // 统计分析页面
          PermissionStatisticsWidget(
            statistics: _statistics!,
            permissionConfig: _permissionConfig!,
            onRequestRequiredPermissions: _requestAllRequiredPermissions,
            onOpenSettings: _openAppSettings,
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _requestAllRequiredPermissions,
        child: const Icon(Icons.security),
        tooltip: '请求所有必需权限',
      ),
    );
  }
}

高级功能实现

1. 权限监控服务

dart
// lib/services/permission_monitor_service.dart
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';
import '../models/permission_info.dart';
import 'permission_service.dart';

class PermissionMonitorService {
  static final PermissionMonitorService _instance = PermissionMonitorService._internal();
  factory PermissionMonitorService() => _instance;
  PermissionMonitorService._internal();

  static const MethodChannel _monitorChannel = MethodChannel('secure_app/monitor');

  final StreamController<PermissionMonitorEvent> _monitorEventStreamController = StreamController<PermissionMonitorEvent>.broadcast();
  Timer? _monitorTimer;
  Map<Permission, PermissionStatus> _lastStatusMap = {};

  // 监控事件流
  Stream<PermissionMonitorEvent> get monitorEventStream => _monitorEventStreamController.stream;

  // 开始权限监控
  void startMonitoring({Duration interval = const Duration(seconds: 30)}) {
    stopMonitoring();

    _monitorTimer = Timer.periodic(interval, (timer) async {
      await _checkPermissionChanges();
    });
  }

  // 停止权限监控
  void stopMonitoring() {
    _monitorTimer?.cancel();
    _monitorTimer = null;
  }

  // 检查权限变化
  Future<void> _checkPermissionChanges() async {
    try {
      final permissionService = PermissionService();
      final permissionConfig = permissionService.permissionConfig;

      if (permissionConfig == null) return;

      for (final entry in permissionConfig.permissions.entries) {
        final permission = entry.key;
        final currentStatus = await permission.status;
        final lastStatus = _lastStatusMap[permission];

        if (lastStatus != null && lastStatus != currentStatus) {
          // 权限状态发生变化
          _monitorEventStreamController.add(PermissionMonitorEvent(
            type: PermissionMonitorEventType.statusChanged,
            permission: permission,
            oldStatus: lastStatus,
            newStatus: currentStatus,
            timestamp: DateTime.now(),
          ));
        }

        _lastStatusMap[permission] = currentStatus;
      }
    } catch (e) {
      // 处理错误
    }
  }

  // 获取权限使用统计
  Future<PermissionUsageStatistics> getPermissionUsageStatistics() async {
    try {
      final usageData = await _monitorChannel.invokeMethod('getPermissionUsageStatistics');

      return PermissionUsageStatistics(
        totalUsageTime: Duration(milliseconds: usageData['totalUsageTime'] ?? 0),
        permissionUsageTimes: Map.from(usageData['permissionUsageTimes'] ?? {}),
        lastUsageTime: DateTime.fromMillisecondsSinceEpoch(usageData['lastUsageTime'] ?? 0),
        mostUsedPermission: usageData['mostUsedPermission'],
        usageCount: usageData['usageCount'] ?? 0,
      );
    } catch (e) {
      throw PermissionMonitorException('获取权限使用统计失败: $e');
    }
  }

  // 获取权限安全评估
  Future<PermissionSecurityAssessment> getPermissionSecurityAssessment() async {
    try {
      final assessmentData = await _monitorChannel.invokeMethod('getPermissionSecurityAssessment');

      return PermissionSecurityAssessment(
        securityScore: assessmentData['securityScore'] ?? 0,
        riskLevel: _parseRiskLevel(assessmentData['riskLevel']),
        riskyPermissions: List<String>.from(assessmentData['riskyPermissions'] ?? []),
        recommendations: List<String>.from(assessmentData['recommendations'] ?? []),
        lastAssessmentTime: DateTime.fromMillisecondsSinceEpoch(assessmentData['lastAssessmentTime'] ?? 0),
      );
    } catch (e) {
      throw PermissionMonitorException('获取权限安全评估失败: $e');
    }
  }

  // 解析风险级别
  RiskLevel _parseRiskLevel(String riskLevel) {
    switch (riskLevel) {
      case 'low':
        return RiskLevel.low;
      case 'medium':
        return RiskLevel.medium;
      case 'high':
        return RiskLevel.high;
      case 'critical':
        return RiskLevel.critical;
      default:
        return RiskLevel.low;
    }
  }

  // 释放资源
  void dispose() {
    stopMonitoring();
    _monitorEventStreamController.close();
  }
}

// 权限监控事件
class PermissionMonitorEvent {
  final PermissionMonitorEventType type;
  final Permission permission;
  final PermissionStatus? oldStatus;
  final PermissionStatus? newStatus;
  final DateTime timestamp;

  PermissionMonitorEvent({
    required this.type,
    required this.permission,
    this.oldStatus,
    this.newStatus,
    required this.timestamp,
  });
}

// 权限监控事件类型
enum PermissionMonitorEventType {
  statusChanged,
  usageDetected,
  securityAlert,
}

// 权限使用统计
class PermissionUsageStatistics {
  final Duration totalUsageTime;
  final Map<String, int> permissionUsageTimes;
  final DateTime lastUsageTime;
  final String? mostUsedPermission;
  final int usageCount;

  PermissionUsageStatistics({
    required this.totalUsageTime,
    required this.permissionUsageTimes,
    required this.lastUsageTime,
    this.mostUsedPermission,
    required this.usageCount,
  });

  // 获取格式化的总使用时间
  String get formattedTotalUsageTime {
    final hours = totalUsageTime.inHours;
    final minutes = totalUsageTime.inMinutes % 60;
    final seconds = totalUsageTime.inSeconds % 60;

    if (hours > 0) {
      return '${hours}小时${minutes}分钟';
    } else if (minutes > 0) {
      return '${minutes}分钟${seconds}秒';
    } else {
      return '${seconds}秒';
    }
  }

  // 获取最常用权限描述
  String get mostUsedPermissionDescription {
    return mostUsedPermission ?? '无';
  }
}

// 权限安全评估
class PermissionSecurityAssessment {
  final int securityScore;
  final RiskLevel riskLevel;
  final List<String> riskyPermissions;
  final List<String> recommendations;
  final DateTime lastAssessmentTime;

  PermissionSecurityAssessment({
    required this.securityScore,
    required this.riskLevel,
    required this.riskyPermissions,
    required this.recommendations,
    required this.lastAssessmentTime,
  });

  // 获取安全分数描述
  String get securityScoreDescription {
    if (securityScore >= 90) return '非常安全';
    if (securityScore >= 70) return '安全';
    if (securityScore >= 50) return '一般';
    if (securityScore >= 30) return '有风险';
    return '高风险';
  }

  // 获取风险级别描述
  String get riskLevelDescription {
    switch (riskLevel) {
      case RiskLevel.low:
        return '低风险';
      case RiskLevel.medium:
        return '中等风险';
      case RiskLevel.high:
        return '高风险';
      case RiskLevel.critical:
        return '严重风险';
    }
  }
}

// 风险级别
enum RiskLevel {
  low,
  medium,
  high,
  critical,
}

// 权限监控异常
class PermissionMonitorException implements Exception {
  final String message;
  PermissionMonitorException(this.message);

  @override
  String toString() => message;
}

2. 权限分析服务

dart
// lib/services/permission_analytics_service.dart
import 'dart:async';
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:permission_handler/permission_handler.dart';
import '../models/permission_info.dart';
import 'permission_service.dart';

class PermissionAnalyticsService {
  static final PermissionAnalyticsService _instance = PermissionAnalyticsService._internal();
  factory PermissionAnalyticsService() => _instance;
  PermissionAnalyticsService._internal();

  static const String _analyticsKey = 'permission_analytics';
  static const String _eventsKey = 'permission_events';

  List<PermissionAnalyticsEvent> _events = [];
  PermissionAnalyticsData? _analyticsData;

  // 初始化分析服务
  Future<void> initialize() async {
    try {
      await _loadAnalyticsData();
      await _loadEvents();
    } catch (e) {
      throw PermissionAnalyticsException('初始化分析服务失败: $e');
    }
  }

  // 记录权限事件
  Future<void> recordEvent(PermissionAnalyticsEvent event) async {
    try {
      _events.add(event);

      // 限制事件数量
      if (_events.length > 1000) {
        _events = _events.sublist(_events.length - 1000);
      }

      await _saveEvents();
      await _updateAnalyticsData();
    } catch (e) {
      throw PermissionAnalyticsException('记录权限事件失败: $e');
    }
  }

  // 记录权限请求事件
  Future<void> recordPermissionRequest(
    Permission permission,
    PermissionStatus status,
    {String? context}
  ) async {
    final event = PermissionAnalyticsEvent(
      type: PermissionAnalyticsEventType.request,
      permission: permission,
      status: status,
      timestamp: DateTime.now(),
      context: context,
    );

    await recordEvent(event);
  }

  // 记录权限使用事件
  Future<void> recordPermissionUsage(
    Permission permission,
    Duration usageDuration,
    {String? context}
  ) async {
    final event = PermissionAnalyticsEvent(
      type: PermissionAnalyticsEventType.usage,
      permission: permission,
      timestamp: DateTime.now(),
      usageDuration: usageDuration,
      context: context,
    );

    await recordEvent(event);
  }

  // 记录权限拒绝事件
  Future<void> recordPermissionDenial(
    Permission permission,
    String reason,
    {String? context}
  ) async {
    final event = PermissionAnalyticsEvent(
      type: PermissionAnalyticsEventType.denial,
      permission: permission,
      timestamp: DateTime.now(),
      reason: reason,
      context: context,
    );

    await recordEvent(event);
  }

  // 获取分析数据
  PermissionAnalyticsData? get analyticsData => _analyticsData;

  // 获取权限请求统计
  Map<Permission, PermissionRequestStatistics> getPermissionRequestStatistics() {
    final statistics = <Permission, PermissionRequestStatistics>{};

    for (final event in _events) {
      if (event.type != PermissionAnalyticsEventType.request) continue;

      final permission = event.permission;
      if (!statistics.containsKey(permission)) {
        statistics[permission] = PermissionRequestStatistics(
          permission: permission,
          requestCount: 0,
          grantCount: 0,
          denialCount: 0,
          lastRequestTime: DateTime.now(),
        );
      }

      final stat = statistics[permission]!;
      stat.requestCount++;

      if (event.status == PermissionStatus.granted) {
        stat.grantCount++;
      } else {
        stat.denialCount++;
      }

      if (event.timestamp.isAfter(stat.lastRequestTime)) {
        stat.lastRequestTime = event.timestamp;
      }
    }

    return statistics;
  }

  // 获取权限使用统计
  Map<Permission, PermissionUsageStatistics> getPermissionUsageStatistics() {
    final statistics = <Permission, PermissionUsageStatistics>{};

    for (final event in _events) {
      if (event.type != PermissionAnalyticsEventType.usage) continue;

      final permission = event.permission;
      if (!statistics.containsKey(permission)) {
        statistics[permission] = PermissionUsageStatistics(
          permission: permission,
          usageCount: 0,
          totalUsageDuration: Duration.zero,
          lastUsageTime: DateTime.now(),
        );
      }

      final stat = statistics[permission]!;
      stat.usageCount++;
      stat.totalUsageDuration += event.usageDuration ?? Duration.zero;

      if (event.timestamp.isAfter(stat.lastUsageTime)) {
        stat.lastUsageTime = event.timestamp;
      }
    }

    return statistics;
  }

  // 获取权限拒绝分析
  PermissionDenialAnalysis getPermissionDenialAnalysis() {
    final denialEvents = _events.where((event) => event.type == PermissionAnalyticsEventType.denial);
    final reasonCounts = <String, int>{};
    final permissionDenials = <Permission, int>{};

    for (final event in denialEvents) {
      final reason = event.reason ?? '未知原因';
      reasonCounts[reason] = (reasonCounts[reason] ?? 0) + 1;

      final permission = event.permission;
      permissionDenials[permission] = (permissionDenials[permission] ?? 0) + 1;
    }

    return PermissionDenialAnalysis(
      totalDenials: denialEvents.length,
      denialReasons: reasonCounts,
      permissionDenials: permissionDenials,
      mostCommonReason: reasonCounts.entries.isNotEmpty
          ? reasonCounts.entries.reduce((a, b) => a.value > b.value ? a : b).key
          : '无',
      mostDeniedPermission: permissionDenials.entries.isNotEmpty
          ? permissionDenials.entries.reduce((a, b) => a.value > b.value ? a : b).key
          : Permission.unknown,
    );
  }

  // 获取权限趋势分析
  PermissionTrendAnalysis getPermissionTrendAnalysis({int days = 30}) {
    final now = DateTime.now();
    final startDate = now.subtract(Duration(days: days));
    final dailyEvents = <DateTime, List<PermissionAnalyticsEvent>>{};

    for (final event in _events) {
      if (event.timestamp.isBefore(startDate)) continue;

      final day = DateTime(event.timestamp.year, event.timestamp.month, event.timestamp.day);
      if (!dailyEvents.containsKey(day)) {
        dailyEvents[day] = [];
      }
      dailyEvents[day]!.add(event);
    }

    final trendData = <DateTime, PermissionTrendData>{};

    for (final entry in dailyEvents.entries) {
      final day = entry.key;
      final events = entry.value;

      final requestCount = events.where((e) => e.type == PermissionAnalyticsEventType.request).length;
      final grantCount = events.where((e) => e.type == PermissionAnalyticsEventType.request && e.status == PermissionStatus.granted).length;
      final denialCount = events.where((e) => e.type == PermissionAnalyticsEventType.denial).length;
      final usageCount = events.where((e) => e.type == PermissionAnalyticsEventType.usage).length;

      trendData[day] = PermissionTrendData(
        date: day,
        requestCount: requestCount,
        grantCount: grantCount,
        denialCount: denialCount,
        usageCount: usageCount,
      );
    }

    return PermissionTrendAnalysis(
      period: Duration(days: days),
      trendData: trendData,
      startDate: startDate,
      endDate: now,
    );
  }

  // 生成权限报告
  Future<PermissionReport> generateReport({int days = 30}) async {
    try {
      final requestStatistics = getPermissionRequestStatistics();
      final usageStatistics = getPermissionUsageStatistics();
      final denialAnalysis = getPermissionDenialAnalysis();
      final trendAnalysis = getPermissionTrendAnalysis(days: days);

      return PermissionReport(
        generatedAt: DateTime.now(),
        period: Duration(days: days),
        requestStatistics: requestStatistics,
        usageStatistics: usageStatistics,
        denialAnalysis: denialAnalysis,
        trendAnalysis: trendAnalysis,
      );
    } catch (e) {
      throw PermissionAnalyticsException('生成权限报告失败: $e');
    }
  }

  // 导出分析数据
  Future<String> exportAnalyticsData() async {
    try {
      final exportData = {
        'events': _events.map((e) => e.toJson()).toList(),
        'analyticsData': _analyticsData?.toJson(),
        'exportedAt': DateTime.now().toIso8601String(),
      };

      return jsonEncode(exportData);
    } catch (e) {
      throw PermissionAnalyticsException('导出分析数据失败: $e');
    }
  }

  // 导入分析数据
  Future<void> importAnalyticsData(String jsonData) async {
    try {
      final importData = jsonDecode(jsonData);

      if (importData['events'] != null) {
        _events = (importData['events'] as List)
            .map((e) => PermissionAnalyticsEvent.fromJson(e))
            .toList();
      }

      if (importData['analyticsData'] != null) {
        _analyticsData = PermissionAnalyticsData.fromJson(importData['analyticsData']);
      }

      await _saveEvents();
      await _saveAnalyticsData();
    } catch (e) {
      throw PermissionAnalyticsException('导入分析数据失败: $e');
    }
  }

  // 清除分析数据
  Future<void> clearAnalyticsData() async {
    try {
      _events.clear();
      _analyticsData = null;

      final prefs = await SharedPreferences.getInstance();
      await prefs.remove(_eventsKey);
      await prefs.remove(_analyticsKey);
    } catch (e) {
      throw PermissionAnalyticsException('清除分析数据失败: $e');
    }
  }

  // 加载分析数据
  Future<void> _loadAnalyticsData() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      final analyticsJson = prefs.getString(_analyticsKey);

      if (analyticsJson != null) {
        _analyticsData = PermissionAnalyticsData.fromJson(jsonDecode(analyticsJson));
      }
    } catch (e) {
      // 处理错误
    }
  }

  // 保存分析数据
  Future<void> _saveAnalyticsData() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      if (_analyticsData != null) {
        await prefs.setString(_analyticsKey, jsonEncode(_analyticsData!.toJson()));
      }
    } catch (e) {
      // 处理错误
    }
  }

  // 加载事件
  Future<void> _loadEvents() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      final eventsJson = prefs.getString(_eventsKey);

      if (eventsJson != null) {
        final eventsList = jsonDecode(eventsJson) as List;
        _events = eventsList.map((e) => PermissionAnalyticsEvent.fromJson(e)).toList();
      }
    } catch (e) {
      // 处理错误
    }
  }

  // 保存事件
  Future<void> _saveEvents() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      await prefs.setString(_eventsKey, jsonEncode(_events.map((e) => e.toJson()).toList()));
    } catch (e) {
      // 处理错误
    }
  }

  // 更新分析数据
  Future<void> _updateAnalyticsData() async {
    try {
      _analyticsData = PermissionAnalyticsData(
        totalEvents: _events.length,
        lastUpdated: DateTime.now(),
        requestCount: _events.where((e) => e.type == PermissionAnalyticsEventType.request).length,
        usageCount: _events.where((e) => e.type == PermissionAnalyticsEventType.usage).length,
        denialCount: _events.where((e) => e.type == PermissionAnalyticsEventType.denial).length,
      );

      await _saveAnalyticsData();
    } catch (e) {
      // 处理错误
    }
  }
}

// 权限分析事件
class PermissionAnalyticsEvent {
  final PermissionAnalyticsEventType type;
  final Permission permission;
  final PermissionStatus? status;
  final DateTime timestamp;
  final Duration? usageDuration;
  final String? reason;
  final String? context;

  PermissionAnalyticsEvent({
    required this.type,
    required this.permission,
    this.status,
    required this.timestamp,
    this.usageDuration,
    this.reason,
    this.context,
  });

  Map<String, dynamic> toJson() {
    return {
      'type': type.index,
      'permission': permission.toString(),
      'status': status?.index,
      'timestamp': timestamp.toIso8601String(),
      'usageDuration': usageDuration?.inMilliseconds,
      'reason': reason,
      'context': context,
    };
  }

  factory PermissionAnalyticsEvent.fromJson(Map<String, dynamic> json) {
    return PermissionAnalyticsEvent(
      type: PermissionAnalyticsEventType.values[json['type']],
      permission: _parsePermission(json['permission']),
      status: json['status'] != null ? PermissionStatus.values[json['status']] : null,
      timestamp: DateTime.parse(json['timestamp']),
      usageDuration: json['usageDuration'] != null ? Duration(milliseconds: json['usageDuration']) : null,
      reason: json['reason'],
      context: json['context'],
    );
  }

  static Permission _parsePermission(String permissionString) {
    switch (permissionString) {
      case 'Permission.camera':
        return Permission.camera;
      case 'Permission.microphone':
        return Permission.microphone;
      case 'Permission.storage':
        return Permission.storage;
      case 'Permission.photos':
        return Permission.photos;
      case 'Permission.location':
        return Permission.location;
      case 'Permission.contacts':
        return Permission.contacts;
      case 'Permission.phone':
        return Permission.phone;
      case 'Permission.sms':
        return Permission.sms;
      case 'Permission.calendar':
        return Permission.calendar;
      case 'Permission.sensors':
        return Permission.sensors;
      case 'Permission.bluetooth':
        return Permission.bluetooth;
      case 'Permission.nfc':
        return Permission.nfc;
      case 'Permission.notification':
        return Permission.notification;
      default:
        return Permission.unknown;
    }
  }
}

// 权限分析事件类型
enum PermissionAnalyticsEventType {
  request,
  usage,
  denial,
}

// 权限分析数据
class PermissionAnalyticsData {
  final int totalEvents;
  final DateTime lastUpdated;
  final int requestCount;
  final int usageCount;
  final int denialCount;

  PermissionAnalyticsData({
    required this.totalEvents,
    required this.lastUpdated,
    required this.requestCount,
    required this.usageCount,
    required this.denialCount,
  });

  Map<String, dynamic> toJson() {
    return {
      'totalEvents': totalEvents,
      'lastUpdated': lastUpdated.toIso8601String(),
      'requestCount': requestCount,
      'usageCount': usageCount,
      'denialCount': denialCount,
    };
  }

  factory PermissionAnalyticsData.fromJson(Map<String, dynamic> json) {
    return PermissionAnalyticsData(
      totalEvents: json['totalEvents'],
      lastUpdated: DateTime.parse(json['lastUpdated']),
      requestCount: json['requestCount'],
      usageCount: json['usageCount'],
      denialCount: json['denialCount'],
    );
  }
}

// 权限请求统计
class PermissionRequestStatistics {
  final Permission permission;
  int requestCount;
  int grantCount;
  int denialCount;
  DateTime lastRequestTime;

  PermissionRequestStatistics({
    required this.permission,
    required this.requestCount,
    required this.grantCount,
    required this.denialCount,
    required this.lastRequestTime,
  });

  // 获取授权率
  double get grantRate {
    if (requestCount == 0) return 0.0;
    return grantCount / requestCount;
  }

  // 获取格式化的授权率
  String get formattedGrantRate {
    return '${(grantRate * 100).toStringAsFixed(1)}%';
  }
}

// 权限使用统计
class PermissionUsageStatistics {
  final Permission permission;
  int usageCount;
  Duration totalUsageDuration;
  DateTime lastUsageTime;

  PermissionUsageStatistics({
    required this.permission,
    required this.usageCount,
    required this.totalUsageDuration,
    required this.lastUsageTime,
  });

  // 获取平均使用时长
  Duration get averageUsageDuration {
    if (usageCount == 0) return Duration.zero;
    return Duration(milliseconds: totalUsageDuration.inMilliseconds ~/ usageCount);
  }

  // 获取格式化的总使用时长
  String get formattedTotalUsageDuration {
    final hours = totalUsageDuration.inHours;
    final minutes = totalUsageDuration.inMinutes % 60;
    final seconds = totalUsageDuration.inSeconds % 60;

    if (hours > 0) {
      return '${hours}小时${minutes}分钟';
    } else if (minutes > 0) {
      return '${minutes}分钟${seconds}秒';
    } else {
      return '${seconds}秒';
    }
  }
}

// 权限拒绝分析
class PermissionDenialAnalysis {
  final int totalDenials;
  final Map<String, int> denialReasons;
  final Map<Permission, int> permissionDenials;
  final String mostCommonReason;
  final Permission mostDeniedPermission;

  PermissionDenialAnalysis({
    required this.totalDenials,
    required this.denialReasons,
    required this.permissionDenials,
    required this.mostCommonReason,
    required this.mostDeniedPermission,
  });
}

// 权限趋势分析
class PermissionTrendAnalysis {
  final Duration period;
  final Map<DateTime, PermissionTrendData> trendData;
  final DateTime startDate;
  final DateTime endDate;

  PermissionTrendAnalysis({
    required this.period,
    required this.trendData,
    required this.startDate,
    required this.endDate,
  });
}

// 权限趋势数据
class PermissionTrendData {
  final DateTime date;
  final int requestCount;
  final int grantCount;
  final int denialCount;
  final int usageCount;

  PermissionTrendData({
    required this.date,
    required this.requestCount,
    required this.grantCount,
    required this.denialCount,
    required this.usageCount,
  });

  // 获取授权率
  double get grantRate {
    if (requestCount == 0) return 0.0;
    return grantCount / requestCount;
  }
}

// 权限报告
class PermissionReport {
  final DateTime generatedAt;
  final Duration period;
  final Map<Permission, PermissionRequestStatistics> requestStatistics;
  final Map<Permission, PermissionUsageStatistics> usageStatistics;
  final PermissionDenialAnalysis denialAnalysis;
  final PermissionTrendAnalysis trendAnalysis;

  PermissionReport({
    required this.generatedAt,
    required this.period,
    required this.requestStatistics,
    required this.usageStatistics,
    required this.denialAnalysis,
    required this.trendAnalysis,
  });

  // 导出为JSON
  String toJson() {
    return jsonEncode({
      'generatedAt': generatedAt.toIso8601String(),
      'period': period.inDays,
      'requestStatistics': requestStatistics.map((key, value) => MapEntry(key.toString(), {
        'requestCount': value.requestCount,
        'grantCount': value.grantCount,
        'denialCount': value.denialCount,
        'grantRate': value.grantRate,
        'lastRequestTime': value.lastRequestTime.toIso8601String(),
      })),
      'usageStatistics': usageStatistics.map((key, value) => MapEntry(key.toString(), {
        'usageCount': value.usageCount,
        'totalUsageDuration': value.totalUsageDuration.inMilliseconds,
        'averageUsageDuration': value.averageUsageDuration.inMilliseconds,
        'lastUsageTime': value.lastUsageTime.toIso8601String(),
      })),
      'denialAnalysis': {
        'totalDenials': denialAnalysis.totalDenials,
        'denialReasons': denialAnalysis.denialReasons,
        'mostCommonReason': denialAnalysis.mostCommonReason,
        'mostDeniedPermission': denialAnalysis.mostDeniedPermission.toString(),
      },
      'trendAnalysis': {
        'period': trendAnalysis.period.inDays,
        'startDate': trendAnalysis.startDate.toIso8601String(),
        'endDate': trendAnalysis.endDate.toIso8601String(),
        'trendData': trendAnalysis.trendData.map((key, value) => MapEntry(key.toIso8601String(), {
          'requestCount': value.requestCount,
          'grantCount': value.grantCount,
          'denialCount': value.denialCount,
          'usageCount': value.usageCount,
          'grantRate': value.grantRate,
        })),
      },
    });
  }
}

// 权限分析异常
class PermissionAnalyticsException implements Exception {
  final String message;
  PermissionAnalyticsException(this.message);

  @override
  String toString() => message;
}

测试与调试

1. 权限服务测试

dart
// test/permission_service_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:secure_app/services/permission_service.dart';

void main() {
  group('PermissionService Tests', () {
    late PermissionService permissionService;

    setUp(() {
      permissionService = PermissionService();
    });

    test('should initialize successfully', () async {
      await expectLater(permissionService.initialize(), completes);
    });

    test('should check permission status correctly', () async {
      final status = await permissionService.checkPermissionStatus(Permission.camera);
      expect(status, isA<PermissionStatus>());
    });

    test('should request permission correctly', () async {
      final status = await permissionService.requestPermission(Permission.camera);
      expect(status, isA<PermissionStatus>());
    });

    test('should request multiple permissions correctly', () async {
      final result = await permissionService.requestPermissions([
        Permission.camera,
        Permission.microphone,
      ]);
      expect(result, isA<PermissionRequestResult>());
    });

    test('should check if permission is permanently denied', () async {
      final isPermanentlyDenied = await permissionService.isPermanentlyDenied(Permission.camera);
      expect(isPermanentlyDenied, isA<bool>());
    });

    test('should open app settings correctly', () async {
      await expectLater(permissionService.openAppSettings(), completes);
    });
  });
}

2. 权限监控服务测试

dart
// test/permission_monitor_service_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:secure_app/services/permission_monitor_service.dart';

void main() {
  group('PermissionMonitorService Tests', () {
    late PermissionMonitorService monitorService;

    setUp(() {
      monitorService = PermissionMonitorService();
    });

    test('should start monitoring correctly', () {
      monitorService.startMonitoring();
      expect(monitorService.monitorEventStream, isA<Stream>());
    });

    test('should stop monitoring correctly', () {
      monitorService.startMonitoring();
      monitorService.stopMonitoring();
      // 验证监控已停止
    });

    test('should get permission usage statistics correctly', () async {
      final statistics = await monitorService.getPermissionUsageStatistics();
      expect(statistics, isA<PermissionUsageStatistics>());
    });

    test('should get permission security assessment correctly', () async {
      final assessment = await monitorService.getPermissionSecurityAssessment();
      expect(assessment, isA<PermissionSecurityAssessment>());
    });
  });
}

最佳实践与注意事项

1. 权限申请策略

  • 渐进式申请:按需申请权限,避免一次性申请过多权限
  • 权限说明:在申请权限前提供清晰的说明
  • 时机选择:在用户需要相关功能时再申请权限
  • 优雅降级:在权限被拒绝时提供替代功能

2. 用户体验优化

  • 权限状态可视化:清晰展示权限状态
  • 权限引导:提供权限申请引导和说明
  • 设置跳转:方便用户跳转到设置页面
  • 状态同步:及时同步权限状态变化

3. 安全考虑

  • 最小权限原则:只申请必要的权限
  • 权限审计:定期审计权限使用情况
  • 数据保护:保护用户隐私数据
  • 权限监控:监控权限异常使用

4. 平台差异处理

  • API 差异:处理 Android 和 iOS 平台 API 差异
  • 权限类型:了解不同平台的权限类型
  • 申请流程:适配不同平台的申请流程
  • 状态映射:统一不同平台的权限状态

5. 错误处理

  • 异常捕获:捕获权限申请异常
  • 重试机制:提供权限申请重试机制
  • 用户反馈:提供清晰的错误反馈
  • 日志记录:记录权限相关日志

总结

通过本文的详细介绍,我们成功实现了一个功能完整的安全权限管理应用 SecureApp。这个项目涵盖了:

  1. 权限管理基础:全面的权限申请和管理功能
  2. 权限监控:实时监控权限状态变化
  3. 权限分析:深度分析权限使用情况
  4. 权限安全:权限安全评估和风险分析
  5. 权限报告:生成详细的权限使用报告
  6. 跨平台支持:同时支持 Android 和 iOS 平台

权限管理是移动应用开发中的重要环节,通过 Flutter 的权限管理能力,我们可以轻松实现跨平台的权限申请和管理。在实际项目中,还可以根据具体需求进一步扩展功能,比如:

  • 集成更多权限类型
  • 添加权限申请模板
  • 实现权限申请自动化
  • 集成权限合规检查
  • 添加权限使用预测
  • 实现权限申请优化建议

希望本文能够帮助开发者更好地理解和实现 Flutter 中的权限管理功能。