Solicitando permisos en Android y IOS con Flutter

Tanto en Android como en IOS antes de poder acceder a cierto hardware del dispositivo tenemos que solicitar al usuario que nos conceda privilegios para poder obtener datos de ellos.

Esto ocurre, por ejemplo, si deseamos acceder a la localización o queremos acceder a la agenda de contactos o para poder acceder a la galería multimedia, etc…

Son permisos que el usuario nos debe de conceder y que en cualquier momento nos puede revocar, por tanto siempre que deseemos utilizar estos servicios tendremos que averiguar si disponemos de los permisos necesarios en ese momento.

Por supuesto, cada sistema operativo operativo trata esta concesión de permisos de una forma diferente y desde Flutter, por suerte, disponemos de un paquete que nos gestiona la petición de permisos para ambas plataformas de una forma única y homogénea, hablamos de Flutter Permission Handler, el cual vamos a ver a continuación como funciona.

Instalando el paquete en nuestro proyecto de Flutter

Su instalación es igual que el resto de librerías o paquetes que existen para Flutter. Abrimos el archivo pubspecs.yaml e incluimos la siguiente línea:

permission_handler: ^5.0.1

Una vez tenemos instalado el paquete, debemos editar el archivo Podfile que está dentro de la carpeta IOS.

Este archivo tenemos que modificarlo añadiendo lo siguiente dentro del bloque que inicia por post_install do |installer|

Y nos tiene que quedar de la siguiente forma:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      ... # Here are some configurations automatically generated by flutter

      # You can remove unused permissions here
      # for more infomation: https://github.com/BaseflowIT/flutter-permission-handler/blob/develop/permission_handler/ios/Classes/PermissionHandlerEnums.h
      # e.g. when you don't need camera permission, just add 'PERMISSION_CAMERA=0'
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',

        ## dart: PermissionGroup.calendar
        # 'PERMISSION_EVENTS=0',

        ## dart: PermissionGroup.reminders
        # 'PERMISSION_REMINDERS=0',

        ## dart: PermissionGroup.contacts
        # 'PERMISSION_CONTACTS=0',

        ## dart: PermissionGroup.camera
        # 'PERMISSION_CAMERA=0',

        ## dart: PermissionGroup.microphone
        # 'PERMISSION_MICROPHONE=0',

        ## dart: PermissionGroup.speech
        # 'PERMISSION_SPEECH_RECOGNIZER=0',

        ## dart: PermissionGroup.photos
        # 'PERMISSION_PHOTOS=0',

        ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
        # 'PERMISSION_LOCATION=0',

        ## dart: PermissionGroup.notification
        # 'PERMISSION_NOTIFICATIONS=0',

        ## dart: PermissionGroup.mediaLibrary
        # 'PERMISSION_MEDIA_LIBRARY=0',

        ## dart: PermissionGroup.sensors
        # 'PERMISSION_SENSORS=0'
      ]

    end
  end
end

Lo último que nos queda por hacer en este archivo es borrar la # del permiso que no deseamos utilizar en nuestra aplicación. Es decir, si no queremos acceder a los sensores y no vamos a pedir este permiso, tenemos que borrar la almohadilla de la última línea:

## dart: PermissionGroup.sensors
 'PERMISSION_SENSORS=0'

En IOS, los permisos que vayamos a utilizar hay que declararlos en un archivo que se llama Info.plist y que está dentro de la carpeta IOS >> Runner.

En este archivo debemos añadir una key/value con el nombre del permiso que vamos a necesitar y un texto que se mostrará al usuario explicando para deseamos utilizar ese permiso.

Así por ejemplo si deseamos utilizar la cámara, tenemos que añadir esto:

< key>NSCameraUsageDescription< /key >
< string >Necesitamos acceso a tu cámara para tomar fotos.< /string >

Un listado con todos los permisos posibles y su clave la podéis encontrar en la documentación oficial de Apple.

Para Android, los permisos se solicitan añadiéndolos en el archivo AndroidManifest.xml que está dentro del directorio de ficheros del proyecto Android.

En él debemos añadir únicamente los permisos que vayamos a solicitar tal que así:

< uses-permission android:name="android.permission.CAMERA" />

Como solicitar un permiso en Android y IOS

En nuestro ejemplo vamos a solicitar tres permisos tanto en Android como en IOS. Estos permisos serán: el acceso a la cámara, el acceso a los contactos y el acceso a la localización.

En Android, lo primero será añadir los permisos que vamos a utilizar en el AndroidManifest.xml:

< !-- Permisos para localización -->
< uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
< uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
< !-- Permisos para  camara -->
< uses-permission android:name="android.permission.CAMERA"/>
< !-- Permisos para contactos -->
< uses-permission android:name="android.permission.READ_CONTACTS"/>
< uses-permission android:name="android.permission.WRITE_CONTACTS"/>
< uses-permission android:name="android.permission.GET_ACCOUNTS"/>

En IOS tendremos que añadir en el archivo Info.plist :

< key > NSContactsUsageDescription < /key >
< string > Necesitamos acceso a tus contactos. < /string >
< key > NSLocationWhenInUseUsageDescription < /key >
< string > Necesitamos acceso a tu localización. < /string >
< key > NSLocationAlwaysUsageDescription < /key >
< string > Necesitamos acceso a tu localización siempre para saber cuando estás cerca de tu tienda favorita. < /string >
< key > NSCameraUsageDescription < /key >
< string > Necesitamos acceso a tu cámara para tomar fotos.<  /string >

Además, y tal como hemos comentado al principio, tenemos que borrar la almohadilla dentro del archivo Pods de aquellos permisos que no vallamos a utilizar, en nuestro caso será:

config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
  '$(inherited)',

  ## dart: PermissionGroup.calendar
   'PERMISSION_EVENTS=0',

  ## dart: PermissionGroup.reminders
   'PERMISSION_REMINDERS=0',

  ## dart: PermissionGroup.contacts
  # 'PERMISSION_CONTACTS=0',

  ## dart: PermissionGroup.camera
  # 'PERMISSION_CAMERA=0',

  ## dart: PermissionGroup.microphone
   'PERMISSION_MICROPHONE=0',

  ## dart: PermissionGroup.speech
   'PERMISSION_SPEECH_RECOGNIZER=0',

  ## dart: PermissionGroup.photos
   'PERMISSION_PHOTOS=0',

  ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
  # 'PERMISSION_LOCATION=0',

  ## dart: PermissionGroup.notification
   'PERMISSION_NOTIFICATIONS=0',

  ## dart: PermissionGroup.mediaLibrary
   'PERMISSION_MEDIA_LIBRARY=0',

  ## dart: PermissionGroup.sensors
   'PERMISSION_SENSORS=0'
]

Ahora nos queda mediante código solicitar propiamente el permiso al usuario, y si este no nos lo ha concedido con anterioridad, le aparecerá una alerta indicándole que necesitamos dicho permiso para que nos lo conceda.

Esto lo hacemos de esta forma:

if (await Permission.contacts.request().isGranted) {
  // Permiso concedido
}

Con esta línea de código estamos verificando que el permiso esté concedido, y si no lo está, se mostrará la alerta antes mencionada.

Si lo que deseamos es verificar únicamente si el permiso está concedido entonces podemos utilizar la siguiente sentencia:

var status = await Permission.camera.status;

Y el status puede ser: undetermined, granted, denied, restricted or permanentlyDenied

Si el usuario nos ha denegado un permiso, no podremos utilizar la información que nos habilita dicho permiso, pero podemos recordarle al usuario que dicho permiso es necesario para que la aplicación funcione o para que pueda mostrar determinado dato. Incluso podemos abrir la página de settings del terminal para que usuario vuelva a darnos el permiso si por lo que sea nos lo ha revocado.

Esto lo podríamos hacer de esta forma:

if (await Permission.speech.isPermanentlyDenied) {
  openAppSettings();
}

Dependiendo de la versión del sistema operativo, modelo del terminal, puede que no sea posible abrir esta ventana de settings y esta petición nos arrojará una excepción que tendremos que controlar.

También podemos solicitar el acceso a varios permisos al mismo tiempo. Para esto podemos hacer lo siguiente:

Map statuses = await [
  Permission.location,
  Permission.storage,
].request();

print(statuses[Permission.location]);

Todo el código lo tenéis disponible en Github.

Comparte si lo consideras interesante
  •  
  •  
  •  
  •  
  •  
  •  
  •  

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.