Xamarin.Essentials: Permisos
La clase Permissions proporciona la capacidad de comprobar y solicitar permisos en tiempo de ejecución.
Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que la biblioteca está correctamente instalada y configurada en los proyectos.
Esta API usa permisos en tiempo de ejecución en Android. Asegúrese de que Xamarin.Essentials se haya inicializado por completo y de que el control de permisos esté configurado en la aplicación.
En el elemento MainLauncher
del proyecto de Android o cualquier Activity
que se inicie, Xamarin.Essentials se debe inicializar en el método OnCreate
:
protected override void OnCreate(Bundle savedInstanceState)
{
//...
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState); // add this line to your code, it may also be called: bundle
//...
}
Para controlar los permisos en tiempo de ejecución de Android, Xamarin.Essentials debe recibir cualquier OnRequestPermissionsResult
. Agregue el código siguiente a todas las clases Activity
:
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
Uso de permisos
Agregue una referencia a Xamarin.Essentials en la clase:
using Xamarin.Essentials;
Comprobación de permisos
Para comprobar el estado actual de un permiso, use el método CheckStatusAsync
junto con el permiso específico para el que obtener el estado.
var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
Se produce una excepción PermissionException
si no se declara el permiso necesario.
Es mejor comprobar el estado del permiso antes de solicitarlo. Cada sistema operativo devuelve un estado predeterminado diferente si nunca se ha solicitado el usuario. iOS devuelve Unknown
, mientras que otros devuelven Denied
. Si el estado es Granted
, no es necesario realizar otras llamadas. En iOS, si el estado es Denied
, debe pedir al usuario que cambie el permiso en la configuración, y en Android puede llamar a ShouldShowRationale
para detectar si el usuario ya denegó el permiso en el pasado.
Solicitar permisos
Para solicitar un permiso a los usuarios, use el método RequestAsync
junto con el permiso específico que se va a solicitar. Si el usuario ha concedido previamente el permiso y no lo ha revocado, este método devuelve Granted
inmediatamente y no muestra ningún cuadro de diálogo.
var status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
Se produce una excepción PermissionException
si no se declara el permiso necesario.
Tenga en cuenta que, en algunas plataformas, una solicitud de permiso solo se puede activar una vez. El desarrollador debe controlar otros mensajes para comprobar si un permiso tiene el estado Denied
y pedir al usuario que lo active manualmente.
Estado del permiso
Al usar los elementos CheckStatusAsync
o RequestAsync
, se devuelve un estado PermissionStatus
que se puede usar para determinar los pasos siguientes:
- Desconocido: el permiso tiene un estado desconocido.
- Denegado: el usuario denegó la solicitud del permiso.
- Deshabilitado: la característica está deshabilitada en el dispositivo.
- Concedido: el usuario concedió el permiso o se ha concedido automáticamente.
- Restringido: en un estado restringido.
Explicación de por qué se necesita el permiso
Es un procedimiento recomendado explicar el motivo por el que la aplicación necesita un permiso específico. En iOS debe especificar una cadena que se muestre al usuario. Android no tiene esta capacidad y, además, el estado de permiso tiene como valor predeterminado Deshabilitado. Esto limita la capacidad de saber si el usuario ha denegado el permiso o si es la primera vez que se le solicita. El método ShouldShowRationale
se puede usar para determinar si se debe mostrar una interfaz de usuario educativa. Si el método devuelve true
, esto se debe a que el usuario ha denegado o deshabilitado el permiso en el pasado. Otras plataformas siempre devolverán false
cuando se llame a este método.
Permisos disponibles
Xamarin.Essentials intenta abstraer tantos permisos como sea posible. Pero cada sistema operativo tiene un conjunto diferente de permisos en tiempo de ejecución. Además, hay diferencias a la hora de proporcionar una única API para algunos permisos. Esta es una guía para los permisos disponibles actualmente:
Guía de iconos:
- - Compatible
- - No compatible o requerido
Permiso | Android | iOS | UWP | watchOS | tvOS | Tizen |
---|---|---|---|---|---|---|
CalendarRead | ||||||
CalendarWrite | ||||||
Cámara | ||||||
ContactsRead | ||||||
ContactsWrite | ||||||
Linterna | ||||||
LocationWhenInUse | ||||||
LocationAlways | ||||||
Medios | ||||||
Micrófono | ||||||
Teléfono | ||||||
Fotos | ||||||
Recordatorios | ||||||
Sensores | ||||||
SMS | ||||||
Voz | ||||||
StorageRead | ||||||
StorageWrite |
Si un permiso está marcado como siempre devolverá Granted
cuando se compruebe o solicite.
Uso general
El código siguiente presenta el patrón de uso general para determinar si un permiso se ha concedido, o para solicitarlo, en el caso de que todavía no se haya hecho. Este código usa características que están disponibles con la versión 1.6.0 de Xamarin.Essentials y las posteriores.
public async Task<PermissionStatus> CheckAndRequestLocationPermission()
{
var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
if (status == PermissionStatus.Granted)
return status;
if (status == PermissionStatus.Denied && DeviceInfo.Platform == DevicePlatform.iOS)
{
// Prompt the user to turn on in settings
// On iOS once a permission has been denied it may not be requested again from the application
return status;
}
if (Permissions.ShouldShowRationale<Permissions.LocationWhenInUse>())
{
// Prompt the user with additional information as to why the permission is needed
}
status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
return status;
}
Cada tipo de permiso puede tener una instancia de este creada, para que se pueda llamar directamente a los métodos.
public async Task GetLocationAsync()
{
var status = await CheckAndRequestPermissionAsync(new Permissions.LocationWhenInUse());
if (status != PermissionStatus.Granted)
{
// Notify user permission was denied
return;
}
var location = await Geolocation.GetLocationAsync();
}
public async Task<PermissionStatus> CheckAndRequestPermissionAsync<T>(T permission)
where T : BasePermission
{
var status = await permission.CheckStatusAsync();
if (status != PermissionStatus.Granted)
{
status = await permission.RequestAsync();
}
return status;
}
Extensión de permisos
La API Permissions se creó para aportar flexibilidad y extensibilidad a las aplicaciones que requieren validación o permisos adicionales que no están incluidos en Xamarin.Essentials. Cree una clase que herede de BasePermission
e implemente los métodos abstractos necesarios.
public class MyPermission : BasePermission
{
// This method checks if current status of the permission
public override Task<PermissionStatus> CheckStatusAsync()
{
throw new System.NotImplementedException();
}
// This method is optional and a PermissionException is often thrown if a permission is not declared
public override void EnsureDeclared()
{
throw new System.NotImplementedException();
}
// Requests the user to accept or deny a permission
public override Task<PermissionStatus> RequestAsync()
{
throw new System.NotImplementedException();
}
}
Al implementar un permiso en una plataforma específica, se puede heredar de la clase BasePlatformPermission
. Esto proporciona métodos auxiliares de la plataforma adicionales para comprobar automáticamente las declaraciones. Esto puede ayudar a la hora de crear permisos personalizados para realizar agrupaciones. Por ejemplo, puede solicitar acceso Leer y Escribir en el almacenamiento en Android con el siguiente permiso personalizado.
public class ReadWriteStoragePermission : Xamarin.Essentials.Permissions.BasePlatformPermission
{
public override (string androidPermission, bool isRuntime)[] RequiredPermissions => new List<(string androidPermission, bool isRuntime)>
{
(Android.Manifest.Permission.ReadExternalStorage, true),
(Android.Manifest.Permission.WriteExternalStorage, true)
}.ToArray();
}
Después, puede llamar al nuevo permiso desde el proyecto de Android.
await Permissions.RequestAsync<ReadWriteStoragePermission>();
Si quiere llamar a esta API desde el código compartido, puede crear una interfaz y usar un servicio de dependencia para efectuar el registro y obtener la implementación.
public interface IReadWritePermission
{
Task<PermissionStatus> CheckStatusAsync();
Task<PermissionStatus> RequestAsync();
}
Después, implemente la interfaz en el proyecto de la plataforma:
public class ReadWriteStoragePermission : Xamarin.Essentials.Permissions.BasePlatformPermission, IReadWritePermission
{
public override (string androidPermission, bool isRuntime)[] RequiredPermissions => new List<(string androidPermission, bool isRuntime)>
{
(Android.Manifest.Permission.ReadExternalStorage, true),
(Android.Manifest.Permission.WriteExternalStorage, true)
}.ToArray();
}
Luego, puede registrar la implementación específica:
DependencyService.Register<IReadWritePermission, ReadWriteStoragePermission>();
A continuación, desde el proyecto compartido, puede resolverla y usarla:
var readWritePermission = DependencyService.Get<IReadWritePermission>();
var status = await readWritePermission.CheckStatusAsync();
if (status != PermissionStatus.Granted)
{
status = await readWritePermission.RequestAsync();
}
Detalles de implementación de la plataforma
Los permisos deben tener los atributos coincidentes establecidos en el archivo de manifiesto de Android. El estado de permiso tiene como valor predeterminado Denegado.
Obtenga más información en el documento Permisos en Xamarin.Android.