Alterar configurações de localização

Caso seu app precise solicitar a localização ou receber atualizações de permissão, o dispositivo terá que ativar as configurações de sistema adequadas, como GPS ou busca por Wi-Fi. Em vez de ativar diretamente serviços como o GPS do dispositivo, seu app especifica o nível necessário de precisão/consumo de energia e o intervalo de atualização desejado, e o dispositivo faz automaticamente as mudanças necessárias nas configurações do sistema. Essas configurações são definidas pelo objeto de dados LocationRequest.

Esta lição mostra como usar o Cliente de configurações para conferir quais configurações estão ativadas e apresentar a caixa de diálogo "Configurações de localização" para que os usuários as atualizem com um único toque.

Configurar Serviços de localização

Para usar os Serviços de localização fornecidos pelo Google Play Services e o provedor de localização combinada, conecte seu app usando o Cliente de configurações, verifique as configurações de localização atuais e, se necessário, solicite ao usuário que ative as configurações necessárias.

Os apps cujos recursos usam Serviços de localização precisam solicitar permissões de localização, dependendo dos casos de uso desses recursos.

Configurar uma solicitação de localização

Para armazenar parâmetros para solicitações ao provedor de localização combinada, crie uma LocationRequest. Os parâmetros determinam o nível de precisão das solicitações de localização. Para ver detalhes de todas as opções de solicitação de local disponíveis, consulte a referência de classe LocationRequest. Esta lição define o intervalo de atualização, o intervalo de atualização mais rápido e a prioridade, conforme descrito abaixo:

Intervalo de atualização
setInterval(): esse método define a velocidade em milissegundos em que seu app prefere receber atualizações de localização. As atualizações de localização podem ser um pouco mais rápidas ou mais lentas que essa taxa para otimizar o uso da bateria, ou pode não haver atualizações (caso o dispositivo não tenha conectividade, por exemplo).
Intervalo de atualização mais rápido
setFastestInterval(): esse método define a velocidade mais rápida em milissegundos em que o app consegue receber as atualizações de localização. A menos que o app se beneficie ao receber atualizações mais rapidamente do que a taxa especificada em setInterval(), não é necessário chamar esse método.
Prioridade

setPriority(): esse método define a prioridade da solicitação, o que dá aos Serviços de localização do Google Play Services uma boa dica sobre as fontes de localização a serem usadas. Os valores a seguir são compatíveis:

  • PRIORITY_BALANCED_POWER_ACCURACY: use essa configuração para solicitar que a precisão da localização seja de um quarteirão, que é de aproximadamente 100 metros. Isso é considerado um nível aproximado de precisão e provavelmente consumirá menos energia. Com essa configuração, é provável que os Serviços de localização usem Wi-Fi e posicionamento da torre de celular. Entretanto, a escolha do provedor de localização depende de muitos outros fatores, como as fontes disponíveis.
  • PRIORITY_HIGH_ACCURACY: use essa configuração para solicitar a localização mais precisa possível. Com essa configuração, é mais provável que os Serviços de localização usem GPS para determinar a localização.
  • PRIORITY_LOW_POWER: use essa configuração para solicitar que a precisão da localização seja de nível de cidade, que é de aproximadamente 10 quilômetros. Isso é considerado um nível aproximado de precisão e provavelmente consumirá menos energia.
  • PRIORITY_NO_POWER: use essa configuração se precisar de um impacto insignificante no consumo de energia, mas quiser receber atualizações de localização quando elas estiverem disponíveis. Com essa configuração, seu app não aciona nenhuma atualização de local, mas recebe os locais acionados por outros apps.

Crie a solicitação de localização e defina os parâmetros conforme mostrado nesta amostra de código:

Kotlin

fun createLocationRequest() {
  val locationRequest = LocationRequest.Builder()
      .setIntervalMillis(10000)
      .setFastestIntervalMillis(5000)
      .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
      .build()
}

Java

protected void createLocationRequest() {
  LocationRequest locationRequest = LocationRequest.Builder()
      .setIntervalMillis(10000)
      .setFastestIntervalMillis(5000)
      .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
      .build();
}

A prioridade de PRIORITY_HIGH_ACCURACY, combinada com a configuração de permissão ACCESS_FINE_LOCATION definida no manifesto do app e um intervalo de atualização rápido de 5.000 milissegundos (5 segundos), faz com que o provedor de localização combinada retorne atualizações com precisão de poucos metros. Essa abordagem é adequada para apps de mapeamento que exibem o local em tempo real.

Dica de desempenho: caso seu app acesse a rede ou realize outro trabalho de longa duração após receber uma atualização de local, ajuste o intervalo mais rápido para um valor mais lento. Esse ajuste impede que seu app receba atualizações que não podem ser usadas. Quando o trabalho de longa duração for concluído, defina o intervalo mais rápido novamente com um valor rápido.

Receber as configurações de localização atuais

Depois de se conectar ao Google Play Services e à API Location Services, você poderá ver as configurações de localização atuais do dispositivo do usuário. Para fazer isso, crie um LocationSettingsRequest.Builder e adicione uma ou mais solicitações de localização. O snippet de código a seguir mostra como adicionar a solicitação de localização que foi criada na etapa anterior:

Kotlin

val builder = LocationSettingsRequest.Builder()
        .addLocationRequest(locationRequest)

Java

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
     .addLocationRequest(locationRequest);

Em seguida, verifique se as configurações de localização atuais são satisfeitas:

Kotlin

val builder = LocationSettingsRequest.Builder()

// ...

val client: SettingsClient = LocationServices.getSettingsClient(this)
val task: Task<LocationSettingsResponse> = client.checkLocationSettings(builder.build())

Java

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();

// ...

SettingsClient client = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());

Quando a Task for concluída, seu app poderá verificar as configurações de localização pelo código de status do objeto LocationSettingsResponse. Para saber ainda mais detalhes sobre o estado atual das configurações de localização relevantes, seu app pode chamar o método getLocationSettingsStates() do objeto LocationSettingsResponse.

Solicitar que o usuário altere as configurações de localização

Para determinar se as configurações de localização são adequadas para a solicitação de local, adicione um OnFailureListener ao objeto Task que valide essas configurações. Em seguida, verifique se o objeto Exception passado para o método onFailure() é uma instância da classe ResolvableApiException, o que indica que as configurações precisam ser mudadas. Depois, exiba uma caixa de diálogo que solicite ao usuário permissão para modificar as configurações de localização chamando startResolutionForResult().

O snippet de código a seguir mostra como determinar se as configurações de localização do usuário permitem que os serviços de localização criem uma LocationRequest, além de mostrar como solicitar permissão ao usuário para mudar as configurações de localização, se necessário:

Kotlin

task.addOnSuccessListener { locationSettingsResponse ->
    // All location settings are satisfied. The client can initialize
    // location requests here.
    // ...
}

task.addOnFailureListener { exception ->
    if (exception is ResolvableApiException){
        // Location settings are not satisfied, but this can be fixed
        // by showing the user a dialog.
        try {
            // Show the dialog by calling startResolutionForResult(),
            // and check the result in onActivityResult().
            exception.startResolutionForResult(this@MainActivity,
                    REQUEST_CHECK_SETTINGS)
        } catch (sendEx: IntentSender.SendIntentException) {
            // Ignore the error.
        }
    }
}

Java

task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
    @Override
    public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
        // All location settings are satisfied. The client can initialize
        // location requests here.
        // ...
    }
});

task.addOnFailureListener(this, new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        if (e instanceof ResolvableApiException) {
            // Location settings are not satisfied, but this can be fixed
            // by showing the user a dialog.
            try {
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                ResolvableApiException resolvable = (ResolvableApiException) e;
                resolvable.startResolutionForResult(MainActivity.this,
                        REQUEST_CHECK_SETTINGS);
            } catch (IntentSender.SendIntentException sendEx) {
                // Ignore the error.
            }
        }
    }
});

A próxima lição, Como receber atualizações de localização, mostra como receber as atualizações periodicamente.