Permissões no Xamarin.Android

Visão geral

Os aplicativos Android são executados em sua própria área restrita e, por motivos de segurança, não têm acesso a determinados recursos do sistema ou hardware no dispositivo. O usuário deve conceder permissão explicitamente ao aplicativo antes que ele possa usar esses recursos. Por exemplo, um aplicativo não pode acessar o GPS em um dispositivo sem permissão explícita do usuário. O Android lançará um Java.Lang.SecurityException se um aplicativo tentar acessar um recurso protegido sem permissão.

As permissões são declaradas no AndroidManifest.xml pelo desenvolvedor do aplicativo quando o aplicativo é desenvolvido. O Android tem dois fluxos de trabalho diferentes para obter o consentimento do usuário para essas permissões:

  • Para aplicativos direcionados ao Android 5.1 (nível de API 22) ou inferior, a solicitação de permissão ocorreu quando o aplicativo foi instalado. Se o usuário não concedesse as permissões, o aplicativo não seria instalado. Depois que o aplicativo é instalado, não há como revogar as permissões, exceto desinstalando o aplicativo.
  • A partir do Android 6.0 (nível de API 23), os usuários receberam mais controle sobre as permissões; eles podem conceder ou revogar permissões desde que o aplicativo esteja instalado no dispositivo. Esta captura de tela mostra as configurações de permissão para o aplicativo Contatos do Google. Ele lista as várias permissões e permite que o usuário habilite ou desabilite as permissões:

Tela Permissões de Exemplo

Os aplicativos Android devem marcar em tempo de execução para ver se eles têm permissão para acessar um recurso protegido. Se o aplicativo não tiver permissão, ele deverá fazer solicitações usando as novas APIs fornecidas pelo SDK do Android para que o usuário conceda as permissões. As permissões são divididas em duas categorias:

  • Permissões normais – são permissões que representam pouco risco à segurança ou privacidade do usuário. O Android 6.0 concederá automaticamente permissões normais no momento da instalação. Consulte a documentação do Android para obter uma lista completa de permissões normais.
  • Permissões perigosas – ao contrário das permissões normais, permissões perigosas são aquelas que protegem a segurança ou a privacidade do usuário. Elas devem ser concedidas explicitamente pelo usuário. Enviar ou receber uma mensagem SMS é um exemplo de uma ação que exige uma permissão perigosa.

Importante

A categoria à qual uma permissão pertence pode ser alterada ao longo do tempo. É possível que uma permissão categorizada como uma permissão "normal" possa ser elevada em níveis futuros de API para uma permissão perigosa.

Permissões perigosas são ainda mais subdivididas em grupos de permissões. Um grupo de permissões conterá permissões que estão logicamente relacionadas. Quando o usuário concede permissão a um membro de um grupo de permissões, o Android concede automaticamente permissão a todos os membros desse grupo. Por exemplo, o STORAGE grupo de permissões contém as WRITE_EXTERNAL_STORAGE permissões e READ_EXTERNAL_STORAGE . Se o usuário conceder permissão a READ_EXTERNAL_STORAGE, a WRITE_EXTERNAL_STORAGE permissão será concedida automaticamente ao mesmo tempo.

Antes de solicitar uma ou mais permissões, é uma prática recomendada fornecer uma lógica sobre por que o aplicativo requer a permissão antes de solicitar a permissão. Depois que o usuário entender a lógica, o aplicativo poderá solicitar permissão do usuário. Ao entender a lógica, o usuário poderá tomar uma decisão informada se quiser conceder a permissão e entender as repercussões se não o fizer.

Todo o fluxo de trabalho de verificação e solicitação de permissões é conhecido como permissões em tempo de execução marcar e pode ser resumido no diagrama a seguir:

Permissão em tempo de execução marcar fluxograma

A Biblioteca de Suporte do Android faz o backport de algumas das novas APIs para permissões para versões mais antigas do Android. Essas APIs com backported marcar automaticamente a versão do Android no dispositivo, portanto, não é necessário executar um nível de API marcar cada vez.

Este documento discutirá como adicionar permissões a um aplicativo Xamarin.Android e como os aplicativos direcionados ao Android 6.0 (nível de API 23) ou superior devem executar uma permissão de tempo de execução marcar.

Observação

É possível que as permissões para hardware possam afetar a forma como o aplicativo é filtrado pelo Google Play. Por exemplo, se o aplicativo exigir permissão para a câmera, o Google Play não mostrará o aplicativo na Google Play Store em um dispositivo que não tenha uma câmera instalada.

Requisitos

É altamente recomendável que os projetos Xamarin.Android incluam o pacote NuGet Xamarin.Android.Support.Compat . Esse pacote retornará APIs específicas de permissão para versões mais antigas do Android, fornecendo uma interface comum sem a necessidade de marcar constantemente a versão do Android em que o aplicativo está sendo executado.

Solicitando permissões do sistema

A primeira etapa para trabalhar com permissões do Android é declarar as permissões no arquivo de manifesto do Android. Isso deve ser feito independentemente do nível de API que o aplicativo está direcionando.

Aplicativos direcionados ao Android 6.0 ou superior não podem assumir que, como o usuário concedeu permissão em algum momento no passado, a permissão será válida na próxima vez. Um aplicativo direcionado ao Android 6.0 deve sempre executar uma permissão de runtime marcar. Aplicativos direcionados ao Android 5.1 ou inferior não precisam executar uma permissão de tempo de execução marcar.

Observação

Os aplicativos só devem solicitar as permissões necessárias.

Declarando permissões no manifesto

As permissões são adicionadas ao AndroidManifest.xml com o uses-permission elemento . Por exemplo, se um aplicativo for localizar a posição do dispositivo, ele exigirá permissões finas e de localização do curso. Os dois elementos a seguir são adicionados ao manifesto:

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

É possível declarar as permissões usando o suporte à ferramenta integrado ao Visual Studio:

  1. Clique duas vezes em Propriedades no Gerenciador de Soluções e selecione a guia Manifesto do Android no janela Propriedades:

    Permissões necessárias na guia Manifesto do Android

  2. Se o aplicativo ainda não tiver um AndroidManifest.xml, clique em Nenhum AndroidManifest.xml encontrado. Clique para adicionar um , conforme mostrado abaixo:

    Nenhuma mensagem de AndroidManifest.xml

  3. Selecione as permissões que seu aplicativo precisa na lista Permissões necessárias e salve:

    Exemplo de permissões CAMERA selecionadas

O Xamarin.Android adicionará automaticamente algumas permissões em tempo de compilação para compilações de depuração. Isso facilitará a depuração do aplicativo. Em particular, duas permissões notáveis são INTERNET e READ_EXTERNAL_STORAGE. Essas permissões definidas automaticamente não parecerão estar habilitadas na lista Permissões necessárias . No entanto, os builds de versão usam apenas as permissões definidas explicitamente na lista Permissões necessárias .

Para aplicativos direcionados ao Android 5.1 (nível de API 22) ou inferior, não há nada mais que precise ser feito. Os aplicativos que serão executados no Android 6.0 (API 23 nível 23) ou superior devem prosseguir para a próxima seção sobre como executar verificações de permissão de tempo de execução.

Verificações de permissão de runtime no Android 6.0

O ContextCompat.CheckSelfPermission método (disponível com a Biblioteca de Suporte do Android) é usado para marcar se uma permissão específica tiver sido concedida. Esse método retornará uma Android.Content.PM.Permission enumeração que tem um dos dois valores:

  • Permission.Granted – A permissão especificada foi concedida.
  • Permission.Denied – A permissão especificada não foi concedida.

Este snippet de código é um exemplo de como marcar para a permissão Câmera em uma Atividade:

if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) == (int)Permission.Granted) 
{
    // We have permission, go ahead and use the camera.
} 
else 
{
    // Camera permission is not granted. If necessary display rationale & request.
}

É uma prática recomendada informar o usuário sobre por que uma permissão é necessária para um aplicativo para que uma decisão informada possa ser tomada para conceder a permissão. Um exemplo disso seria um aplicativo que tira fotos e marca geografiamente. Está claro para o usuário que a permissão da câmera é necessária, mas pode não ficar claro por que o aplicativo também precisa da localização do dispositivo. A lógica deve exibir uma mensagem para ajudar o usuário a entender por que a permissão de localização é desejável e que a permissão da câmera é necessária.

O ActivityCompat.ShouldShowRequestPermissionRationale método é usado para determinar se a lógica deve ser mostrada ao usuário. Esse método retornará true se a lógica de uma determinada permissão for exibida. Esta captura de tela mostra um exemplo de uma Barra de Lanches exibida por um aplicativo que explica por que o aplicativo precisa saber o local do dispositivo:

Racionalidade para localização

Se o usuário conceder a permissão, o ActivityCompat.RequestPermissions(Activity activity, string[] permissions, int requestCode) método deverá ser chamado. Esse método requer os seguintes parâmetros:

  • atividade – essa é a atividade que está solicitando as permissões e deve ser informada pelo Android sobre os resultados.
  • permissões – uma lista das permissões que estão sendo solicitadas.
  • requestCode – um valor inteiro usado para corresponder os resultados da solicitação de permissão a uma RequestPermissions chamada. Esse valor deve ser maior que zero.

Esse snippet de código é um exemplo dos dois métodos que foram discutidos. Primeiro, um marcar é feito para determinar se a lógica de permissão deve ser mostrada. Se a lógica for mostrada, uma Barra de Lanches será exibida com a lógica . Se o usuário clicar em OK na Barra de Lanches, o aplicativo solicitará as permissões. Se o usuário não aceitar a lógica, o aplicativo não deverá prosseguir para solicitar permissões. Se a lógica não for mostrada, a Atividade solicitará a permissão:

if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessFineLocation)) 
{
    // Provide an additional rationale to the user if the permission was not granted
    // and the user would benefit from additional context for the use of the permission.
    // For example if the user has previously denied the permission.
    Log.Info(TAG, "Displaying camera permission rationale to provide additional context.");

    var requiredPermissions = new String[] { Manifest.Permission.AccessFineLocation };
    Snackbar.Make(layout, 
                   Resource.String.permission_location_rationale,
                   Snackbar.LengthIndefinite)
            .SetAction(Resource.String.ok, 
                       new Action<View>(delegate(View obj) {
                           ActivityCompat.RequestPermissions(this, requiredPermissions, REQUEST_LOCATION);
                       }    
            )
    ).Show();
}
else 
{
    ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.Camera }, REQUEST_LOCATION);
}

RequestPermission pode ser chamado mesmo se o usuário já tiver concedido permissão. Chamadas subsequentes não são necessárias, mas fornecem ao usuário a oportunidade de confirmar (ou revogar) a permissão. Quando RequestPermission é chamado, o controle é entregue ao sistema operacional, que exibirá uma interface do usuário para aceitar as permissões:

Caixa de diálogo De permsão

Depois que o usuário for concluído, o Android retornará os resultados para a Atividade por meio de um método de retorno de chamada, OnRequestPermissionResult. Esse método faz parte da interface ActivityCompat.IOnRequestPermissionsResultCallback que deve ser implementada pela Atividade. Essa interface tem um único método, OnRequestPermissionsResult, que será invocado pelo Android para informar a Atividade das escolhas do usuário. Se o usuário concedeu a permissão, o aplicativo poderá prosseguir e usar o recurso protegido. Um exemplo de como implementar OnRequestPermissionResult é mostrado abaixo:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
    if (requestCode == REQUEST_LOCATION) 
    {
        // Received permission result for camera permission.
        Log.Info(TAG, "Received response for Location permission request.");

        // Check if the only required permission has been granted
        if ((grantResults.Length == 1) && (grantResults[0] == Permission.Granted)) {
            // Location permission has been granted, okay to retrieve the location of the device.
            Log.Info(TAG, "Location permission has now been granted.");
            Snackbar.Make(layout, Resource.String.permission_available_camera, Snackbar.LengthShort).Show();            
        } 
        else 
        {
            Log.Info(TAG, "Location permission was NOT granted.");
            Snackbar.Make(layout, Resource.String.permissions_not_granted, Snackbar.LengthShort).Show();
        }
    } 
    else 
    {
        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

Resumo

Este guia discutiu como adicionar e marcar para permissões em um dispositivo Android. As diferenças em como as permissões funcionam entre aplicativos Android antigos (nível < de API 23) e novos aplicativos Android (nível > de API 22). Ele discutiu como executar verificações de permissão em tempo de execução no Android 6.0.