Управление разрешениями в Flutter

Разрешения имеют решающее значение при создании мобильных приложений, которым требуется доступ к функциям устройства, таким как местоположение, камера, контакты и другие. В Flutter эффективная обработка этих разрешений гарантирует, что приложение обеспечивает бесперебойную работу пользователя, соблюдая при этом требования конфиденциальности и безопасности. Одним из популярных пакетов для управления разрешениями в Flutter является permission_handler.

Эта статья проведет вас через процесс запроса, проверки и обработки различных разрешений в Flutter с использованием permission_handler, с практическими примерами на основе permission_handler.

Сначала добавьте пакеты permission_handler и fluttertoast в ваш файл pubspec.yaml:

dependencies:
  permission_handler: ^11.3.1 
  fluttertoast: ^8.2.4

Затем выполните:

flutter pub get

Пакет permission_handler предоставляет простой способ запроса разрешений и проверки их статусов. Ниже представлено полное описание обработки различных разрешений, таких как телефонные звонки, контакты, местоположение, SMS и камера/микрофон.

Обработчик разрешений может обрабатывать все эти типы разрешений: Календарь, Камера, Контакты, Местоположение, Библиотека медиафайлов, Микрофон, Телефон, Фотографии, Напоминания, Сенсоры, SMS, Распознавание речи, Хранилище, Игнорировать оптимизацию батареи, Уведомления, Доступ к медиа-местоположению, Распознавание активности, Разрешения Bluetooth, Управление внешним хранилищем, Окно системного предупреждения, Запрос на установку пакетов, Прозрачность отслеживания приложения, Критические уведомления, Доступ к политике уведомлений, Устройства рядом по Wi-Fi, Аудио, Запланированный точный будильник, Постоянные сенсоры, Только чтение календаря и Полный доступ к календарю, но в этой статье мы рассмотрим лишь несколько из них

Ниже приведено подробное руководство по запросу каждого типа разрешения, обработке сценариев отказа или постоянного отказа и тому, к чему предоставляет доступ каждое разрешение.


  • Разрешения: calendar, calendarReadOnly, calendarFullAccess

  • Сценарий использования: Доступ к календарю пользователя для чтения или записи событий.

Future<void> requestCalendarPermission() async {
  var status = await Permission.calendar.request();

  if (status.isGranted) {
    // Permission granted, proceed with calendar access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Calendar permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Calendar permission denied',
    );
  }
}

  • Разрешение: camera

  • Сценарий использования: Доступ к камере устройства для создания фотографий или видео.

Future<void> requestCameraPermission() async {
  var status = await Permission.camera.request();

  if (status.isGranted) {
    // Permission granted, proceed with camera access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Camera permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Camera permission denied',
    );
  }
}

  • Разрешение: contacts

  • Случай использования: Доступ к контактному списку пользователя для чтения или изменения контактов.

Future<void> requestContactsPermission() async {
  var status = await Permission.contacts.request();

  if (status.isGranted) {
    // Permission granted, proceed with contacts access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Contacts permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Contacts permission denied',
    );
  }
}

  • Разрешения: location, locationAlways, locationWhenInUse, accessMediaLocation

  • Случай использования: Доступ к местоположению пользователя для навигации, геозон или ближайших услуг.

Future<void> requestLocationPermission() async {
  var status = await Permission.location.request();

  if (status.isGranted) {
    // Permission granted, proceed with location access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Location permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Location permission denied',
    );
  }
}

  • Разрешение: mediaLibrary

  • Случай использования: Доступ к медиатеке пользователя (только iOS).

Future<void> requestMediaLibraryPermission() async {
  var status = await Permission.mediaLibrary.request();

  if (status.isGranted) {
    // Permission granted, proceed with media library access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Media Library permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Media Library permission denied',
    );
  }
}

  • Разрешение: microphone

  • Сценарий использования: Доступ к микрофону устройства для записи аудио.

Future<void> requestMicrophonePermission() async {
  var status = await Permission.microphone.request();

  if (status.isGranted) {
    // Permission granted, proceed with microphone access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Microphone permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Microphone permission denied',
    );
  }
}

  • Разрешение: phone

  • Сценарий использования: Совершение телефонных звонков, чтение состояния телефона или доступ к журналу вызовов.

Future<void> requestPhonePermission() async {
  var status = await Permission.phone.request();

  if (status.isGranted) {
    // Permission granted, proceed with phone access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Phone permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Phone permission denied',
    );
  }
}

  • Разрешения: photos, photosAddOnly

  • Сценарий использования: Доступ к фотогалерее пользователя для чтения или добавления фото.

Future<void> requestPhotosPermission() async {
  var status = await Permission.photos.request();

  if (status.isGranted) {
    // Permission granted, proceed with photos access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Photos permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Photos permission denied',
    );
  }
}

  • Разрешение: reminders

  • Сценарий использования: Доступ и управление напоминаниями на устройстве пользователя.

Future<void> requestRemindersPermission() async {
  var status = await Permission.reminders.request();

  if (status.isGranted) {
    // Permission granted, proceed with reminders access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Reminders permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Reminders permission denied',
    );
  }
}

  • Разрешения: sensors, sensorsAlways

  • Сценарий использования: Доступ к датчикам устройства, таким как акселерометр и гироскоп.

Future<void> requestSensorsPermission() async {
  var status = await Permission.sensors.request();

  if (status.isGranted) {
    // Permission granted, proceed with sensors access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Sensors permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Sensors permission denied',
    );
  }
}

  • Разрешение: sms

  • Сценарий использования: Доступ к функциям SMS, включая чтение или отправку SMS-сообщений.

Future<void> requestSmsPermission() async {
  var status = await Permission.sms.request();

  if (status.isGranted) {
    // Permission granted, proceed with SMS access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'SMS permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'SMS permission denied',
    );
  }
}

  • Разрешение: speech

  • Сценарий использования: Доступ к функциям преобразования речи в текст.

Future<void> requestSpeechPermission() async {
  var status = await Permission.speech.request();

  if (status.isGranted) {
    // Permission granted, proceed with speech recognition
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Speech recognition permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Speech recognition permission denied',
    );
  }
}

  • Разрешения: storage, manageExternalStorage

  • Сценарий использования: Доступ к внутреннему или внешнему хранилищу пользователя для чтения или записи файлов.

Future<void> requestStoragePermission() async {
  var status = await Permission.storage.request();

  if (status.isGranted) {
    // Permission granted, proceed with storage access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Storage permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Storage permission denied',
    );
  }
}

  • Разрешение: ignoreBatteryOptimizations

  • Вариант использования: Запросить систему исключить приложение из мер оптимизации батареи.

Future<void> requestIgnoreBatteryOptimizationsPermission() async {
  var status = await Permission.ignoreBatteryOptimizations.request();

  if (status.isGranted) {
    // Permission granted, proceed with ignoring battery optimizations
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Battery optimization permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Battery optimization permission denied',
    );
  }
}

  • Разрешение: notification

  • Вариант использования: Разрешить вашему приложению отправлять уведомления.

Future<void> requestNotificationPermission() async {
  var status = await Permission.notification.request();

  if (status.isGranted) {
    // Permission granted, proceed with notifications access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Notification permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Notification permission denied',
    );
  }
}

  • Разрешения: bluetooth, bluetoothScan, bluetoothAdvertise, bluetoothConnect

  • Вариант использования: Доступ к функциям Bluetooth для подключения или управления устройствами Bluetooth.

Future<void> requestBluetoothPermission() async {
  var status = await Permission.bluetooth.request();

  if (status.isGranted) {
    // Permission granted, proceed with Bluetooth access
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'Bluetooth permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'Bluetooth permission denied',
    );
  }
}

  • Разрешение: appTrackingTransparency

  • Сценарий использования: Запрос на разрешение от пользователя, требование для отслеживания приложения в iOS.

Future<void> requestAppTrackingTransparencyPermission() async {
  var status = await Permission.appTrackingTransparency.request();

  if (status.isGranted) {
    // Permission granted, proceed with app tracking
  } else if (status.isPermanentlyDenied) {
    ShowToast.showErrorText(
      text: 'App tracking permission permanently denied. Please enable it in the app settings.',
    );
    openAppSettings();
  } else {
    ShowToast.showErrorText(
      text: 'App tracking permission denied',
    );
  }
}

Разрешения играют ключевую роль в обеспечении пользователей беспрепятственным опытом, соблюдая при этом их конфиденциальность. Важно обращаться с этими разрешениями бережно и объяснять пользователям, почему вашему приложению они необходимы.

Используя пакет permission_handler, вы можете запрашивать, проверять и управлять всеми необходимыми разрешениями для вашего приложения Flutter на обеих платформах Android и iOS. Всегда предоставляйте пользователям содержательную обратную связь и рассмотрите добавление альтернативных потоков в случае отказа или отзыва разрешений.

Конфигурации для Android и iOS

Необходимо включить необходимые конфигурации для Android и iOS. Для Android это означает обновление AndroidManifest.xml с правильными объявлениями разрешений. Для iOS описания использования разрешений должны быть добавлены в файл Info.plist, чтобы информировать пользователей, зачем запрашиваются определенные разрешения.

Для каждого разрешения из 17 примеров вам нужно добавить соответствующий тег <uses-permission> в AndroidManifest.xml. Вот как разрешения соотносятся с пакетом permission_handler:

  1. Разрешение на камеру

     <uses-permission android:name="android.permission.CAMERA" />
    
  2. Разрешение на контакты

     <uses-permission android:name="android.permission.READ_CONTACTS" />
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    
  3. Разрешения местоположения

     <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" />
    
  4. Разрешение на доступ к медиабиблиотеке/хранилищу

     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage"/>
     <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
     <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
     <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
    
  5. Разрешение на доступ к микрофону

     <uses-permission android:name="android.permission.RECORD_AUDIO" />
    
  6. Разрешение на доступ к телефону

     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    
  7. Разрешение на доступ к фотографиям

     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
  8. Разрешение на доступ к напоминаниям (нет явного разрешения Android)

  9. Разрешение на доступ к датчикам

     <uses-permission android:name="android.permission.BODY_SENSORS" />
    
  10. Разрешение на отправку SMS

    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    
  11. Разрешение на распознавание речи

    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    
  12. Игнорировать оптимизацию батареи

    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
    
  13. Разрешение на уведомления (Обрабатывается нативно в Android 13+)

  14. Разрешение на доступ к местоположению медиа

    <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
    
  15. Разрешение на распознавание активности

    <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
    
  16. Разрешения Bluetooth

    <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_ADVERTISE" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    
  17. Разрешение на отслеживание приложений (только для iOS)


Для iOS вам необходимо предоставить описательные ключи в файле Info.plist, чтобы сообщить пользователям, зачем вашему приложению нужны определенные разрешения. Ниже приведены конфигурации для каждого примера разрешения:

  1. Разрешение на использование камеры

     <key>NSCameraUsageDescription</key>
     <string>Нам нужен доступ к вашей камере для съемки фотографий.</string>
    
  2. Разрешение на использование контактов

     <key>NSContactsUsageDescription</key>
     <string>Нам нужен доступ к вашим контактам для улучшения коммуникации.</string>
    
  3. Разрешения на доступ к местоположению

     <key>NSLocationWhenInUseUsageDescription</key>
     <string>Нам нужен доступ к вашему местоположению для предоставления услуг на основе местоположения.</string>
     <key>NSLocationAlwaysUsageDescription</key>
     <string>Нам нужен доступ к вашему местоположению, чтобы отслеживать ваше движение, даже когда приложение не активно.</string>
    
  4. Разрешение на доступ к медиабиблиотеке/хранилищу

     <key>NSPhotoLibraryUsageDescription</key>
     <string>Нам нужен доступ к вашим фотографиям для обмена или загрузки медиафайлов.</string>
    
  5. Разрешение на использование микрофона

     <key>NSMicrophoneUsageDescription</key>
     <string>Нам нужен доступ к вашему микрофону для записи звука.</string>
    
  6. Разрешение на использование телефона

     <key>NSPhoneUsageDescription</key>
     <string>Нам нужен доступ к телефонным услугам для совершения звонков.</string>
    
  7. Разрешение на доступ к фотографиям

     <key>NSPhotoLibraryAddUsageDescription</key>
     <string>Нам нужно разрешение на добавление фотографий в вашу библиотеку.</string>
    
  8. Разрешение на доступ к напоминаниям

     <key>NSRemindersUsageDescription</key>
     <string>Нам нужен доступ к вашим напоминаниям для управления задачами.</string>
    
  9. Разрешение на датчики

     <key>NSSensorsUsageDescription</key>
     <string>Нам нужен доступ к вашим датчикам для отслеживания фитнеса.</string>
    
  10. Разрешение на SMS (Обрабатывается автоматически iOS, если запрашиваются услуги SMS)

  11. Разрешение на распознавание речи

<key>NSSpeechRecognitionUsageDescription</key>
<string>We need access to speech recognition for voice commands.</string>
  1. Игнорировать оптимизацию батареи (Не применимо в iOS)

  2. Разрешение на уведомления

<key>NSUserNotificationUsageDescription</key>
<string>We need permission to send notifications.</string>
  1. Доступ к местоположению медиафайлов (Обрабатывается автоматически в iOS)

  2. Разрешение на распознавание активности

<key>NSMotionUsageDescription</key>
<string>We need access to motion data for fitness tracking.</string>
  1. Разрешения Bluetooth
<key>NSBluetoothPeripheralUsageDescription</key>
<string>We need access to Bluetooth for device connectivity.</string>
  1. Прозрачность отслеживания приложений
<key>NSUserTrackingUsageDescription</key>
<string>We need permission to track your activity across apps and websites for personalized ads.</string>

Чтобы ваше приложение функционировало полностью и соответствовало последним нормам конфиденциальности, необходимо правильно управлять разрешениями. Обновив как AndroidManifest.xml, так и Info.plist, а также реализовав корректную логику обработки разрешений в вашем приложении Flutter, вы обеспечите пользователям бесшовный и прозрачный опыт при запросе доступа к чувствительным функциям.

Всегда проверяйте разрешения на обеих платформах и предоставляйте пользователям значимые объяснения о том, почему разрешения необходимы, чтобы избежать отказов во время проверки в магазинах приложений.

Для более глубокого изучения рассмотрите возможность ознакомления с официальной документацией по обработке разрешений, чтобы узнать о других типах разрешений. Убедитесь, что вы также обновили свои файлы для конкретных платформ (такие как AndroidManifest.xml и Info.plist) с необходимыми декларациями для каждого типа разрешения.

Source:
https://atuoha.hashnode.dev/permission-handling-in-flutter