Manipulação de Permissões no Flutter

As permissões são cruciais ao construir aplicações móveis que requerem acesso a recursos do dispositivo, como localização, câmera, contatos e outros. No Flutter, lidar com essas permissões de forma eficaz garante que o aplicativo forneça uma experiência do usuário contínua, ao mesmo tempo que respeita os requisitos de privacidade e segurança. Um pacote popular para gerenciar permissões no Flutter é permission_handler.

Este artigo irá guiá-lo sobre como solicitar, verificar e lidar com diferentes permissões no Flutter usando o permission_handler, com exemplos práticos baseados no permission_handler.

Primeiramente, adicione o pacote permission_handler e fluttertoast ao seu arquivo pubspec.yaml:

dependencies:
  permission_handler: ^11.3.1 
  fluttertoast: ^8.2.4

Depois, execute:

flutter pub get

O pacote permission_handler fornece uma maneira simples de solicitar permissões e verificar seus status. Abaixo está uma análise completa de como lidar com diferentes permissões como chamadas telefônicas, contatos, localização, SMS e câmera/microfone.

O Permission Handler pode gerenciar todos esses tipos de permissões: Calendário, Câmera, Contatos, Localização, Biblioteca de Mídia, Microfone, Telefone, Fotos, Lembretes, Sensores, SMS, Reconhecimento de Fala, Armazenamento, Ignorar Otimizações de Bateria, Notificações, Acesso à Localização da Mídia, Reconhecimento de Atividade, Permissões de Bluetooth, Gerenciar Armazenamento Externo, Janela de Alerta do Sistema, Solicitar Instalação de Pacotes, Transparência de Rastreamento de Aplicativos, Alertas Críticos, Acesso à Política de Notificações, Dispositivos Wi-Fi Próximos, Áudio, Agendar Alarme Exato, SensoresSempre, Leitura de Calendário e Acesso Completo ao Calendário, mas vamos cobrir alguns neste artigo

Abaixo está um guia detalhado sobre como solicitar cada tipo de permissão, lidar com cenários como negação ou negação permanente, e o que cada permissão concede acesso.


  • Permissões: calendar, calendarReadOnly, calendarFullAccess

  • Caso de Uso: Acessar o calendário do usuário para ler ou escrever eventos.

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',
    );
  }
}

  • Permissão: camera

  • Caso de Uso: Acessar a câmera do dispositivo para capturar fotos ou vídeos.

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',
    );
  }
}

  • Permissão: contatos

  • Caso de Uso: Acessar a lista de contatos do usuário para leitura ou modificação de contatos.

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',
    );
  }
}

  • Permissões: localização, localizaçãoSempre, localizaçãoQuandoEmUso, acessoLocalMídia

  • Caso de Uso: Acessar a localização do usuário para navegação, geofencing ou serviços próximos.

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',
    );
  }
}

  • Permissão: bibliotecaDeMídia

  • Caso de Uso: Acessar a biblioteca de mídia do usuário (apenas 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',
    );
  }
}

  • Permissão: microfone

  • Caso de Uso: Acessar o microfone do dispositivo para gravar áudio.

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',
    );
  }
}

  • Permissão: phone

  • Caso de Uso: Fazer chamadas telefônicas, ler o estado do telefone ou acessar registros de chamadas.

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',
    );
  }
}

  • Permissões: photos, photosAddOnly

  • Caso de Uso: Acessar a biblioteca de fotos do usuário para ler ou adicionar fotos.

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',
    );
  }
}

  • Permissão: reminders

  • Caso de Uso: Acessar e gerenciar lembretes no dispositivo do usuário.

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',
    );
  }
}

  • Permissões: sensors, sensorsAlways

  • Caso de Uso: Acessar os sensores do dispositivo, como acelerômetro e giroscópio.

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',
    );
  }
}

  • Permissão: sms

  • Caso de Uso: Acessar recursos de SMS, incluindo leitura ou envio de mensagens 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',
    );
  }
}

  • Permissão: speech

  • Caso de Uso: Acessar recursos de conversão de fala em texto.

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',
    );
  }
}

  • Permissões: storage, manageExternalStorage

  • Caso de Uso: Acessar o armazenamento interno ou externo do usuário para ler ou gravar arquivos.

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',
    );
  }
}

  • Permissão: ignoreBatteryOptimizations

  • Caso de Uso: Solicitar ao sistema que exclua o aplicativo das medidas de otimização de bateria.

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',
    );
  }
}

  • Permissão: notification

  • Caso de Uso: Permitir que seu aplicativo envie notificações.

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',
    );
  }
}

  • Permissões: bluetooth, bluetoothScan, bluetoothAdvertise, bluetoothConnect

  • Caso de Uso: Acessar recursos de Bluetooth para conectar ou gerenciar dispositivos 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',
    );
  }
}

  • Permissão: appTrackingTransparency

  • Caso de Uso: Solicitar permissão de rastreamento do usuário, um requisito para o rastreamento de aplicativos no 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',
    );
  }
}

As permissões desempenham um papel crítico ao fornecer aos usuários uma experiência perfeita, respeitando sua privacidade. É essencial lidar com essas permissões de forma cuidadosa e educar os usuários sobre por que seu aplicativo precisa delas.

Ao usar o pacote permission_handler, você pode solicitar, verificar e gerenciar todas as permissões necessárias para o seu aplicativo Flutter em ambas as plataformas Android e iOS. Sempre forneça aos usuários um feedback significativo e considere adicionar fluxos alternativos no caso de permissões serem negadas ou revogadas.

Configurações para Android e iOS

É essencial incluir as configurações necessárias para Android e iOS. Para Android, isso significa atualizar o AndroidManifest.xml com as declarações de permissão corretas. Para iOS, as descrições de uso das permissões devem ser adicionadas ao arquivo Info.plist para informar aos usuários por que determinadas permissões estão sendo solicitadas.

Para cada permissão nos 17 exemplos, você precisa adicionar a tag correspondente <uses-permission> no AndroidManifest.xml. Aqui está como as permissões se alinham com o pacote permission_handler:

  1. Permissão da Câmera

     <uses-permission android:name="android.permission.CAMERA" />
    
  2. Permissão de Contatos

     <uses-permission android:name="android.permission.READ_CONTACTS" />
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    
  3. Permissões de Localização

     <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. Biblioteca de Mídia/Permissão de Armazenamento

     <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. Permissão de Microfone

     <uses-permission android:name="android.permission.RECORD_AUDIO" />
    
  6. Permissão do Telefone

     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    
  7. Permissão de Fotos

     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
  8. Permissão de Lembretes (Sem permissão explícita do Android)

  9. Permissão de Sensores

     <uses-permission android:name="android.permission.BODY_SENSORS" />
    
  10. Permissão de SMS

    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    
  11. Permissão de Reconhecimento de Voz

    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    
  12. Ignorar Otimizações de Bateria

    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
    
  13. Permissão de Notificações (Tratada nativamente no Android 13+)

  14. Permissão de Acesso à Localização da Mídia

    <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
    
  15. Permissão de Reconhecimento de Atividade

    <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
    
  16. Permissões do 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. Permissão de Transparência do Rastreamento do Aplicativo (apenas iOS)


Para iOS, você deve fornecer chaves descritivas no arquivo Info.plist para informar aos usuários por que seu aplicativo precisa de permissões específicas. Abaixo estão as configurações para cada exemplo de permissão:

  1. Permissão da Câmera

     <key>NSCameraUsageDescription</key>
     <string>Precisamos de acesso à sua câmera para tirar fotos.</string>
    
  2. Permissão de Contatos

     <key>NSContactsUsageDescription</key>
     <string>Precisamos de acesso aos seus contatos para melhor comunicação.</string>
    
  3. Permissões de Localização

     <key>NSLocationWhenInUseUsageDescription</key>
     <string>Precisamos de acesso à sua localização para fornecer serviços baseados em localização.</string>
     <key>NSLocationAlwaysUsageDescription</key>
     <string>Precisamos de acesso à sua localização para rastrear seu movimento mesmo quando o aplicativo não está ativo.</string>
    
  4. Permissão de Biblioteca de Mídia/Armazenamento

     <key>NSPhotoLibraryUsageDescription</key>
     <string>Precisamos de acesso às suas fotos para compartilhar ou fazer upload de mídia.</string>
    
  5. Permissão de Microfone

     <key>NSMicrophoneUsageDescription</key>
     <string>Precisamos de acesso ao seu microfone para gravação de voz.</string>
    
  6. Permissão de Telefone

     <key>NSPhoneUsageDescription</key>
     <string>Precisamos de acesso aos serviços de telefone para habilitar chamadas.</string>
    
  7. Permissão para Fotos

     <key>NSPhotoLibraryAddUsageDescription</key>
     <string>Precisamos de permissão para adicionar fotos à sua biblioteca.</string>
    
  8. Permissão para Lembretes

     <key>NSRemindersUsageDescription</key>
     <string>Precisamos de acesso aos seus lembretes para gerenciamento de tarefas.</string>
    
  9. Permissão para Sensores

     <key>NSSensorsUsageDescription</key>
     <string>Precisamos de acesso aos seus sensores para monitoramento de fitness.</string>
    
  10. Permissão para SMS (Tratado automaticamente pelo iOS se serviços de SMS forem solicitados)

  11. Permissão para Reconhecimento de Voz

<key>NSSpeechRecognitionUsageDescription</key>
<string>We need access to speech recognition for voice commands.</string>
  1. Ignorar Otimizações de Bateria (Não aplicável no iOS)

  2. Permissão para Notificações

<key>NSUserNotificationUsageDescription</key>
<string>We need permission to send notifications.</string>
  1. Permissão para Acesso à Localização da Mídia (Tratado automaticamente no iOS)

  2. Permissão para Reconhecimento de Atividades

<key>NSMotionUsageDescription</key>
<string>We need access to motion data for fitness tracking.</string>
  1. Permissões de Bluetooth
<key>NSBluetoothPeripheralUsageDescription</key>
<string>We need access to Bluetooth for device connectivity.</string>
  1. Transparência no Rastreamento de Aplicativos
<key>NSUserTrackingUsageDescription</key>
<string>We need permission to track your activity across apps and websites for personalized ads.</string>

Para tornar seu aplicativo totalmente funcional e em conformidade com as mais recentes regulamentações de privacidade, é essencial gerenciar as permissões corretamente. Ao atualizar tanto o AndroidManifest.xml quanto o Info.plist, juntamente com a implementação da lógica de gerenciamento de permissões correta em seu aplicativo Flutter, você proporciona uma experiência fluida e transparente para os usuários ao solicitar acesso a recursos sensíveis.

Sempre garanta que você teste as permissões em ambas as plataformas e forneça explicações significativas aos usuários sobre o motivo pelo qual as permissões são necessárias para evitar rejeições durante as análises na loja de aplicativos.

Para uma pesquisa mais aprofundada, considere verificar a documentação oficial do manipulador de permissões para explorar outros tipos de permissões. Certifique-se também de atualizar seus arquivos específicos da plataforma (como AndroidManifest.xml e Info.plist) com as declarações necessárias para cada tipo de permissão.

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