Permissões
Este artigo descreve como você pode usar a classe Permissions da interface do usuário do aplicativo .NET multiplataforma (.NET MAUI). Essa classe permite que você verifique e solicite permissões em tempo de execução. O tipo Permissions
está disponível no namespace Microsoft.Maui.ApplicationModel
.
Permissões disponíveis
O .NET MAUI tenta abstrair o máximo de permissões possível. No entanto, cada sistema operacional tem um conjunto diferente de permissões. Embora a API permita o acesso a uma permissão comum, pode haver diferenças entre os sistemas operacionais relacionados a essa permissão. A tabela a seguir descreve as permissões disponíveis:
A tabela a seguir usa ✔️ para indicar que a permissão tem suporte e ❌ para indicar que a permissão não tem suporte ou não é necessária:
Permissão | Android | iOS | Windows | tvOS |
---|---|---|---|---|
Bateria | ✔️ | ❌ | ❌ | ❌ |
Bluetooth | ✔️ | ❌ | ❌ | ❌ |
CalendarRead | ✔️ | ✔️ | ❌ | ❌ |
CalendarWrite | ✔️ | ✔️ | ❌ | ❌ |
Câmera | ✔️ | ✔️ | ❌ | ❌ |
ContactsRead | ✔️ | ✔️ | ❌ | ❌ |
ContactsWrite | ✔️ | ✔️ | ❌ | ❌ |
Lanterna | ✔️ | ❌ | ❌ | ❌ |
LocationWhenInUse | ✔️ | ✔️ | ❌ | ✔️ |
LocationAlways | ✔️ | ✔️ | ❌ | ❌ |
Media | ❌ | ✔️ | ❌ | ❌ |
Microfone | ✔️ | ✔️ | ❌ | ❌ |
NearbyWifiDevices | ✔️ | ❌ | ❌ | ❌ |
NetworkState | ✔️ | ❌ | ❌ | ❌ |
Telefone | ✔️ | ✔️ | ❌ | ❌ |
Photos | ❌ | ✔️ | ❌ | ✔️ |
PhotosAddOnly | ❌ | ✔️ | ❌ | ✔️ |
Notificações Post | ✔️ | ❌ | ❌ | ❌ |
Lembretes | ❌ | ✔️ | ❌ | ❌ |
Sensores | ✔️ | ✔️ | ❌ | ❌ |
Sms | ✔️ | ✔️ | ❌ | ❌ |
Fala | ✔️ | ✔️ | ❌ | ❌ |
StorageRead | ✔️ | ❌ | ❌ | ❌ |
StorageWrite | ✔️ | ❌ | ❌ | ❌ |
Vibrar | ✔️ | ❌ | ❌ | ❌ |
Importante
As permissões StorageRead e StorageWrite sempre retornarão Granted na API do Android 33+. Isso ocorre porque o Android READ_EXTERNAL_STORAGE
subjacente e WRITE_EXTERNAL_STORAGE
as permissões não estão mais disponíveis na API 33.
Se uma permissão estiver marcada como ❌, ela sempre retornará Granted quando marcada ou solicitada.
Verificar permissões
Para verificar o status atual de uma permissão, use o método Permissions.CheckStatusAsync com a permissão específica para obter o status. O exemplo a seguir verifica o status da permissão LocationWhenInUse
:
PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
Um PermissionException será gerado se a permissão necessária não for declarada.
É melhor verificar o status da permissão antes de solicitá-la. Cada sistema operacional retornará um estado padrão diferente, se o usuário nunca tiver sido solicitado. O iOS retorna Unknown, enquanto outros retornam Denied. Se o status for Granted, não será necessário fazer outras chamadas. No iOS, se o status for Denied, você deverá solicitar que o usuário altere a permissão nas configurações. No Android, você pode chamar ShouldShowRationale para detectar se o usuário já negou a permissão no passado.
Status da permissão
Ao usar CheckStatusAsync ou RequestAsync, um PermissionStatus é retornado que pode ser usado para determinar as próximas etapas:
Unknown
A permissão está em um estado desconhecido ou, no iOS, o usuário nunca foi solicitado.Denied
O usuário negou a solicitação de permissão.Disabled
O recurso está desabilitado no dispositivo.Granted
O usuário concedeu permissão ou ela é concedida automaticamente.Restricted
Em um estado restrito.Limited
Em um estado limitado. Somente o iOS retorna esse status.
Solicitar permissões
Para solicitar uma permissão dos usuários, use o método RequestAsync com a permissão específica. Se o usuário concedeu permissão anteriormente e não a revogou, esse método retornará Granted sem mostrar uma caixa de diálogo para o usuário. As permissões não devem ser solicitadas da sua classe MauiProgram
ou App
e só devem ser solicitadas quando a primeira página do aplicativo for exibida.
O exemplo a seguir solicita a permissão LocationWhenInUse
:
PermissionStatus status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
Um PermissionException será gerado se a permissão necessária não for declarada.
Importante
Em algumas plataformas, uma solicitação de permissão só pode ser ativada uma única vez. Outras solicitações devem ser tratadas pelo desenvolvedor para verificar se uma permissão está no estado Denied e, em seguida, pedir ao usuário para ativá-la manualmente.
Explicar por que a permissão é necessária
É uma prática recomendada explicar ao usuário por que seu aplicativo precisa de uma permissão específica. No iOS, você deve especificar uma cadeia de caracteres que será exibida ao usuário. O Android não tem essa capacidade e também define o status de permissão como Disabled por padrão. Isso limita a capacidade de saber se o usuário negou a permissão ou se é a primeira vez que a permissão está sendo solicitada. O método ShouldShowRationale pode ser usado para determinar se uma interface do usuário informativa deve ser exibida. Se o método retornar true
, isso ocorre porque o usuário negou ou desabilitou a permissão no passado. Outras plataformas sempre retornam false
ao chamar esse método.
Exemplo
O código a seguir apresenta o padrão de uso geral para determinar se uma permissão foi concedida e, em seguida, solicitá-la caso não tenha sido.
public async Task<PermissionStatus> CheckAndRequestLocationPermission()
{
PermissionStatus 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;
}
Estender permissões
A API de Permissões foi criada para ser flexível e extensível para aplicativos que exigem mais validação ou permissões que não estão incluídas no .NET MAUI. Crie uma classe que herda de Permissions.BasePermission e implemente os métodos abstratos necessários. O código de exemplo a seguir demonstra os membros abstratos básicos, mas sem implementação:
public class MyPermission : Permissions.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();
}
// Indicates that the requestor should prompt the user as to why the app requires the permission, because the
// user has previously denied this permission.
public override bool ShouldShowRationale()
{
throw new NotImplementedException();
}
}
Ao implementar uma permissão de uma plataforma específica, a classe Permissions.BasePlatformPermission pode ser herdada. Essa classe fornece métodos auxiliares adicionais de plataforma para verificar automaticamente as declarações de permissão. Isso ajuda ao criar permissões personalizadas que fazem agrupamentos, por exemplo, solicitando acesso tanto para leitura quanto para gravação ao armazenamento no Android. O exemplo de código a seguir demonstra a solicitação de acesso de leitura e gravação ao armazenamento:
public class ReadWriteStoragePerms : Permissions.BasePlatformPermission
{
public override (string androidPermission, bool isRuntime)[] RequiredPermissions =>
new List<(string androidPermission, bool isRuntime)>
{
(global::Android.Manifest.Permission.ReadExternalStorage, true),
(global::Android.Manifest.Permission.WriteExternalStorage, true)
}.ToArray();
}
Em seguida, verifique a permissão da mesma forma que qualquer outro tipo de permissão fornecido pelo .NET MAUI:
PermissionStatus status = await Permissions.RequestAsync<ReadWriteStoragePerms>();
Se você quiser chamar essa API do código multiplataforma, poderá criar uma interface e registrar a permissão personalizada como uma dependência no contêiner de serviço do aplicativo. O exemplo a seguir mostra a interface IReadWritePermission
:
public interface IReadWritePermission
{
Task<PermissionStatus> CheckStatusAsync();
Task<PermissionStatus> RequestAsync();
}
Em seguida, implemente a interface em sua permissão personalizada:
public class ReadWriteStoragePermission : 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();
}
Na classe MauiProgram
, você deve registrar a interface e seu tipo concreto, e o tipo que consumirá a permissão personalizada, no contêiner de serviço do aplicativo:
builder.Services.AddTransient<MyViewModel>();
builder.Services.AddSingleton<IReadWritePermission, ReadWriteStoragePermission>();
A implementação de permissão personalizada pode então ser resolvida e invocada de um de seus tipos, como um viewmodel:
public class MyViewModel
{
IReadWritePermission _readWritePermission;
public MyViewModel(IReadWritePermission readWritePermission)
{
_readWritePermission = readWritePermission;
}
public async Task CheckPermissionAsync()
{
var status = await _readWritePermission.CheckStatusAsync();
if (status != PermissionStatus.Granted)
{
status = await _readWritePermission.RequestAsync();
}
}
}
Diferenças de plataforma
Esta seção descreve as diferenças específicas de cada plataforma com a API de permissões.
As permissões devem ter os atributos correspondentes definidos no arquivo de Manifesto do Android. O status de permissão é definido por padrão como Denied.