Solicitar acesso à localização no momento da execução

Quando um recurso do seu app precisa de acesso à localização, aguarde até que o usuário interaja com o recurso antes de solicitar a permissão. Esse fluxo de trabalho segue a prática recomendada de solicitar permissões de execução no contexto, conforme descrito no guia que explica como solicitar permissões do app.

A Figura 1 mostra um exemplo de como executar esse processo. O app contém um recurso "compartilhar localização" que requer acesso à localização em primeiro plano. No entanto, a permissão de localização só é solicitada quando o usuário seleciona o botão Compartilhar localização.

Depois que o usuário seleciona o botão "Compartilhar localização", a
    caixa de diálogo do sistema que pede permissão de localização é exibida
Figura 1. Recurso de compartilhamento de localização que precisa de acesso à localização em primeiro plano. O recurso será ativado se o usuário selecionar Permitir durante o uso do app.

O usuário pode conceder acesso apenas ao local aproximado

No Android 12 (nível 31 da API) ou versões mais recentes, os usuários podem solicitar que o app recupere apenas informações de local aproximado, mesmo quando o app solicitar a permissão de execução ACCESS_FINE_LOCATION.

Para processar esse possível comportamento do usuário, não solicite apenas a permissão ACCESS_FINE_LOCATION sozinha. Em vez disso, solicite a permissão ACCESS_FINE_LOCATION e a ACCESS_COARSE_LOCATION em uma única solicitação de ambiente de execução. Se você tentar solicitar apenas ACCESS_FINE_LOCATION, o sistema vai ignorar a solicitação em algumas versões do Android 12. Se o app for destinado ao Android 12 ou versões mais recentes, o sistema vai registrar a seguinte mensagem de erro no Logcat:

ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION.

Quando o app solicitar ACCESS_FINE_LOCATION e ACCESS_COARSE_LOCATION, a caixa de diálogo de permissões do sistema incluirá as novas opções a seguir para o usuário:

  • Precisa: permite que o app receba informações de localização precisas.
  • Aproximado: permite que o app receba apenas informações de local aproximado.

A Figura 3 mostra que a caixa de diálogo contém uma dica visual para as duas opções, o que ajuda o usuário a escolher. Após o usuário decidir sobre o tipo da localização, ele tocará em um dos três botões para selecionar a duração da concessão de permissão.

No Android 12, os usuários podem acessar as configurações do sistema para definir a precisão de localização preferencial de qualquer app, independentemente da versão do SDK de destino. Isso ocorre mesmo quando o app é instalado em um dispositivo com o Android 11 ou versões anteriores e, em seguida, o usuário faz upgrade do dispositivo para o Android 12 ou versões mais recentes.

A caixa de diálogo se refere apenas à localização aproximada e
         contém três botões, um acima do outro
Figura 2. Caixa de diálogo de permissões do sistema exibida quando o app solicita apenas ACCESS_COARSE_LOCATION.
A caixa de diálogo tem dois conjuntos de opções, uma acima da outra
Figura 3. Caixa de diálogo de permissões do sistema que aparece quando o app solicita ACCESS_FINE_LOCATION e ACCESS_COARSE_LOCATION em uma única solicitação de ambiente de execução.

A escolha do usuário afeta as concessões de permissão

A tabela a seguir mostra as permissões que o sistema concede ao app, com base nas opções que o usuário escolhe na caixa de diálogo das permissões de execução:

Exata Aproximada
Durante o uso do app ACCESS_FINE_LOCATION e
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
Apenas esta vez ACCESS_FINE_LOCATION e
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
Negar Sem permissão de localização Sem permissão de localização

Para determinar quais permissões o sistema concedeu ao app, confira o valor de retorno da solicitação de permissões. Você pode usar as bibliotecas do Jetpack em códigos parecidos com o do exemplo a seguir ou usar bibliotecas da plataforma, em que você gerencia o código de solicitação de permissão por conta própria.

Kotlin

@RequiresApi(Build.VERSION_CODES.N)
fun requestPermissions() {
    val locationPermissionRequest = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        when {
            permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
                // Precise location access granted.
            }
            permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
                // Only approximate location access granted.
            }
            else -> {
                // No location access granted.
            }
        }
    }

    // Before you perform the actual permission request, check whether your app
    // already has the permissions, and whether your app needs to show a permission
    // rationale dialog. For more details, see Request permissions:
    // https://developer.android.com/training/permissions/requesting#request-permission
    locationPermissionRequest.launch(
        arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
        )
    )
}

Java

private void requestPermissions() {

    ActivityResultLauncher<String[]> locationPermissionRequest =
            registerForActivityResult(new ActivityResultContracts
                            .RequestMultiplePermissions(), result -> {

                Boolean fineLocationGranted = null;
                Boolean coarseLocationGranted = null;

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    fineLocationGranted = result.getOrDefault(
                            Manifest.permission.ACCESS_FINE_LOCATION, false);
                    coarseLocationGranted = result.getOrDefault(
                            Manifest.permission.ACCESS_COARSE_LOCATION,false);
                }

                if (fineLocationGranted != null && fineLocationGranted) {
                    // Precise location access granted.
                } else if (coarseLocationGranted != null && coarseLocationGranted) {
                    // Only approximate location access granted.
                } else {
                    // No location access granted.
                }
            }
        );

    // ...

    // Before you perform the actual permission request, check whether your app
    // already has the permissions, and whether your app needs to show a permission
    // rationale dialog. For more details, see Request permissions.
    locationPermissionRequest.launch(new String[] {
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
    });
}

Solicitar um upgrade para um local exato

Você pode solicitar que o usuário faça upgrade do acesso do app do local aproximado para o local exato. Antes de pedir ao usuário para atualizar o acesso do app para o local exato, considere se o caso de uso do app realmente exige esse nível de precisão. Se o app precisar parear um dispositivo com outros próximos por Bluetooth ou Wi-Fi, use o pareamento de dispositivo complementar ou as permissões de Bluetooth, em vez de solicitar a permissão ACCESS_FINE_LOCATION.

Para solicitar que o usuário faça upgrade do acesso de localização do app de aproximada para exata, faça o seguinte:

  1. Se necessário, explique por que o app precisa da permissão.
  2. Solicite as permissões ACCESS_FINE_LOCATION e ACCESS_COARSE_LOCATION juntas novamente. Como o usuário já autorizou o sistema a conceder uma localização aproximada ao app, a caixa de diálogo do sistema será diferente desta vez, como mostrado nas Figuras 4 e 5:
A caixa de diálogo contém as opções &quot;Mudar para local
         exato&quot;, &quot;Apenas esta vez&quot; e &quot;Negar&quot;.
Figura 4. Anteriormente, o usuário selecionou Aproximada e Durante o uso do app (na caixa de diálogo da Figura 3).
A caixa de diálogo contém as opções &quot;Apenas esta vez&quot; e
         &quot;Negar&quot;.
Figura 5. Anteriormente, o usuário selecionou Aproximada e Apenas esta vez (na caixa de diálogo da Figura 3).

Solicitar apenas a localização em primeiro plano inicialmente

Mesmo que vários recursos do seu app precisem de acesso à localização, é provável que apenas alguns deles precisem de acesso à localização em segundo plano. Portanto, é recomendado que o app faça solicitações incrementais de permissão de localização, pedindo o acesso à localização em primeiro plano e, depois, em segundo plano. Com as solicitações incrementais, você oferece aos usuários mais controle e transparência, porque eles podem entender melhor quais recursos do app precisam de acesso à localização em segundo plano.

A Figura 6 mostra um exemplo de app desenvolvido para processar solicitações incrementais. Os recursos "mostrar localização atual" e "recomendar lugares por perto" exigem acesso à localização em primeiro plano. No entanto, somente o recurso "recomendar lugares por perto" requer acesso à localização em segundo plano.

O botão que ativa o acesso à localização em primeiro plano fica a meia tela de distância do botão que permite a localização em segundo plano
Figura 6. Os dois recursos exigem acesso à localização, mas apenas o "recomendar lugares por perto" requer acesso à localização em segundo plano.

O processo para fazer solicitações incrementais é o seguinte:

  1. Primeiro, seu app precisa indicar aos usuários os recursos que exigem acesso à localização em primeiro plano, como o recurso "compartilhar localização" da Figura 1 ou "mostrar localização atual" da Figura 2.

    É recomendável desativar o acesso do usuário a recursos que exijam acesso à localização em segundo plano até que o app receba acesso à localização em primeiro plano.

  2. Posteriormente, quando o usuário explorar recursos que exijam acesso à localização em segundo plano, você poderá solicitar acesso a esse tipo de localização.

Outros recursos

Para ter mais informações sobre permissões de localização no Android, consulte o seguinte material:

Codelabs

Vídeos

Amostras

  • App de exemplo para demonstrar o uso de permissões de localização.