Serviços de localização no Android
Este guia apresenta o reconhecimento de localização em aplicativos Android e ilustra como obter a localização do usuário usando a API do Serviço de Localização do Android, bem como o provedor de localização fundido disponível com a API dos Serviços de Localização do Google.
O Android fornece acesso a várias tecnologias de localização, como localização de torre de celular, Wi-Fi e GPS. Os detalhes de cada tecnologia de localização são abstraídos por meio de provedores de localização, permitindo que os aplicativos obtenham locais da mesma maneira, independentemente do provedor usado. Este guia apresenta o provedor de localização fundida, uma parte do Google Play Services, que determina de forma inteligente a melhor maneira de obter a localização dos dispositivos com base em quais provedores estão disponíveis e como o dispositivo está sendo usado. API do Serviço de Localização do Android e mostra como se comunicar com o Serviço de Localização do Sistema usando um LocationManager
arquivo . A segunda parte do guia explora a API dos Serviços de Localização do Android usando o LocationManager
.
Como regra geral, os aplicativos devem preferir usar o provedor de localização fundida, retornando a API de Serviço de Localização do Android mais antiga apenas quando necessário.
Fundamentos de localização
No Android, independentemente da API escolhida para trabalhar com dados de localização, vários conceitos permanecem os mesmos. Esta seção apresenta Provedores de Localização e permissões relacionadas à localização.
Provedores de localização
Diversas tecnologias são utilizadas internamente para identificar a localização do usuário. O hardware usado depende do tipo de provedor de localização selecionado para o trabalho de coleta de dados. O Android usa três provedores de localização:
GPS Provider - GPS dá a localização mais precisa, usa a maior potência, e funciona melhor ao ar livre. Este provedor usa uma combinação de GPS e GPS assistido (aGPS), que retorna dados de GPS coletados por torres de celular.
Provedor de rede – Fornece uma combinação de dados Wi-Fi e celular, incluindo dados aGPS coletados por torres de celular. Ele usa menos energia do que o provedor GPS, mas retorna dados de localização de precisão variável.
Provedor passivo – Uma opção de "piggyback" usando provedores solicitados por outros aplicativos ou serviços para gerar dados de localização em um aplicativo. Esta é uma opção menos confiável, mas que economiza energia, ideal para aplicativos que não exigem atualizações constantes de localização para funcionar.
Os provedores de localização nem sempre estão disponíveis. Por exemplo, podemos querer usar o GPS para nosso aplicativo, mas o GPS pode estar desativado em Configurações ou o dispositivo pode não ter GPS. Se um provedor específico não estiver disponível, a escolha desse provedor poderá retornar null
.
Permissões de localização
Um aplicativo com reconhecimento de localização precisa acessar os sensores de hardware de um dispositivo para receber dados de GPS, Wi-Fi e celular. O acesso é controlado por meio de permissões apropriadas no Manifesto Android do aplicativo. Há duas permissões disponíveis – dependendo dos requisitos do seu aplicativo e da sua escolha de API, você desejará permitir uma:
ACCESS_FINE_LOCATION
– Permite o acesso de um aplicativo ao GPS. Necessário para as opções Provedor GPS e Provedor Passivo (Provedor Passivo precisa de permissão para acessar dados GPS coletados por outro aplicativo ou Serviço). Permissão opcional para o Provedor de Rede.ACCESS_COARSE_LOCATION
– Permite o acesso de um aplicativo à localização de celular e Wi-Fi. Necessário para o Provedor de Rede seACCESS_FINE_LOCATION
não estiver definido.
Para aplicativos destinados à API versão 21 (Android 5.0 Lollipop) ou superior, você pode habilitar ACCESS_FINE_LOCATION
e ainda executar em dispositivos que não têm hardware GPS. Se seu aplicativo exigir hardware GPS, você deverá adicionar explicitamente um android.hardware.location.gps
uses-feature
elemento ao Manifesto do Android. Para obter mais informações, consulte a referência do elemento de recurso de uso do Android.
Para definir as permissões, expanda a pasta Propriedades no Painel de Soluções e clique duas vezes em AndroidManifest.xml. As permissões serão listadas em Permissões necessárias:
A configuração de qualquer uma dessas permissões informa ao Android que seu aplicativo precisa de permissão do usuário para acessar os provedores de localização. Os dispositivos que executam o nível de API 22 (Android 5.1) ou inferior solicitarão que o usuário conceda essas permissões sempre que o aplicativo for instalado. Em dispositivos que executam o nível de API 23 (Android 6.0) ou superior, o aplicativo deve executar uma verificação de permissão de tempo de execução antes de fazer uma solicitação ao provedor de localização.
Observação
Nota: A configuração ACCESS_FINE_LOCATION
implica o acesso a dados de localização grosseiros e finos. Você nunca deve ter que definir ambas as permissões, apenas a permissão mínima que seu aplicativo requer para funcionar.
Este trecho é um exemplo de como verificar se um aplicativo tem permissão para a ACCESS_FINE_LOCATION
permissão:
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.AccessFineLocation) == Permission.Granted)
{
StartRequestingLocationUpdates();
isRequestingLocationUpdates = true;
}
else
{
// The app does not have permission ACCESS_FINE_LOCATION
}
Os aplicativos devem ser tolerantes com o cenário em que o usuário não concederá permissão (ou revogou a permissão) e ter uma maneira de lidar normalmente com essa situação. Consulte o Guia de permissões para obter mais detalhes sobre como implementar verificações de permissão em tempo de execução no Xamarin.Android.
Usando o provedor de localização fundida
O provedor de localização fundido é a maneira preferida para os aplicativos Android receberem atualizações de localização do dispositivo, pois selecionará eficientemente o provedor de localização durante o tempo de execução para fornecer as melhores informações de localização de forma eficiente em termos de bateria. Por exemplo, um usuário andando ao ar livre obtém a melhor leitura de localização com GPS. Se o usuário andar dentro de casa, onde o GPS funciona mal (se é que funciona), o provedor de localização fundida pode mudar automaticamente para Wi-Fi, que funciona melhor em ambientes fechados.
A API do provedor de localização fundida fornece uma variedade de outras ferramentas para capacitar aplicativos com reconhecimento de localização, incluindo cerca geográfica e monitoramento de atividades. Nesta seção, vamos nos concentrar nos conceitos básicos de configuração do LocationClient
, estabelecer provedores e obter a localização do usuário.
O provedor de localização fundida faz parte do Google Play Services. O pacote do Google Play Services deve ser instalado e configurado corretamente no aplicativo para que a API do provedor de localização fundida funcione, e o dispositivo deve ter o APK do Google Play Services instalado.
Antes que um aplicativo Xamarin.Android possa usar o provedor de localização fundida, ele deve adicionar o pacote Xamarin.GooglePlayServices.Location ao projeto. Além disso, as instruções a seguir using
devem ser adicionadas a quaisquer arquivos de origem que façam referência às classes descritas abaixo:
using Android.Gms.Common;
using Android.Gms.Location;
Verificar se o Google Play Services está instalado
Um Xamarin.Android falhará se tentar usar o provedor de localização fundido quando o Google Play Services não estiver instalado (ou desatualizado), ocorrerá uma exceção de tempo de execução. Se o Google Play Services não estiver instalado, o aplicativo deverá retornar ao Serviço de localização do Android discutido acima. Se o Google Play Services estiver desatualizado, o aplicativo poderá exibir uma mensagem ao usuário solicitando que ele atualize a versão instalada do Google Play Services.
Este trecho é um exemplo de como uma atividade do Android pode verificar programaticamente se o Google Play Services está instalado:
bool IsGooglePlayServicesInstalled()
{
var queryResult = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
if (queryResult == ConnectionResult.Success)
{
Log.Info("MainActivity", "Google Play Services is installed on this device.");
return true;
}
if (GoogleApiAvailability.Instance.IsUserResolvableError(queryResult))
{
// Check if there is a way the user can resolve the issue
var errorString = GoogleApiAvailability.Instance.GetErrorString(queryResult);
Log.Error("MainActivity", "There is a problem with Google Play Services on this device: {0} - {1}",
queryResult, errorString);
// Alternately, display the error to the user.
}
return false;
}
FusedLocationProviderClient
Para interagir com o provedor de localização fundida, um aplicativo Xamarin.Android deve ter uma instância do FusedLocationProviderClient
. Essa classe expõe os métodos necessários para assinar atualizações de local e recuperar o último local conhecido do dispositivo.
O OnCreate
método de uma Atividade é um local adequado para obter uma referência ao FusedLocationProviderClient
, conforme demonstrado no seguinte trecho de código:
public class MainActivity: AppCompatActivity
{
FusedLocationProviderClient fusedLocationProviderClient;
protected override void OnCreate(Bundle bundle)
{
fusedLocationProviderClient = LocationServices.GetFusedLocationProviderClient(this);
}
}
Obtendo o último local conhecido
O FusedLocationProviderClient.GetLastLocationAsync()
método fornece uma maneira simples e sem bloqueio para um aplicativo Xamarin.Android obter rapidamente a última localização conhecida do dispositivo com sobrecarga de codificação mínima.
Este trecho mostra como usar o GetLastLocationAsync
método para recuperar o local do dispositivo:
async Task GetLastLocationFromDevice()
{
// This method assumes that the necessary run-time permission checks have succeeded.
getLastLocationButton.SetText(Resource.String.getting_last_location);
Android.Locations.Location location = await fusedLocationProviderClient.GetLastLocationAsync();
if (location == null)
{
// Seldom happens, but should code that handles this scenario
}
else
{
// Do something with the location
Log.Debug("Sample", "The latitude is " + location.Latitude);
}
}
Subscrever atualizações de localização
Um aplicativo Xamarin.Android também pode assinar atualizações de localização do provedor de localização fundido usando o FusedLocationProviderClient.RequestLocationUpdatesAsync
método, conforme mostrado neste trecho de código:
await fusedLocationProviderClient.RequestLocationUpdatesAsync(locationRequest, locationCallback);
Esse método usa dois parâmetros:
Android.Gms.Location.LocationRequest
– UmLocationRequest
objeto é como um aplicativo Xamarin.Android passa os parâmetros sobre como o provedor de localização fundido deve funcionar. AsLocationRequest
informações de retenção, como a frequência com que as solicitações devem ser feitas ou a importância de uma atualização de localização precisa. Por exemplo, uma solicitação de localização importante fará com que o dispositivo use o GPS e, consequentemente, mais energia ao determinar a localização. Este trecho de código mostra como criar umLocationRequest
para um local com alta precisão, verificando aproximadamente a cada cinco minutos uma atualização de local (mas não antes de dois minutos entre as solicitações). O provedor de localização fundida usará umLocationRequest
como orientação para qual provedor de local usar ao tentar determinar a localização do dispositivo:LocationRequest locationRequest = new LocationRequest() .SetPriority(LocationRequest.PriorityHighAccuracy) .SetInterval(60 * 1000 * 5) .SetFastestInterval(60 * 1000 * 2);
Android.Gms.Location.LocationCallback
– Para receber atualizações de localização, um aplicativo Xamarin.Android deve subclassificar aLocationProvider
classe abstrata. Essa classe expôs dois métodos que podem ser invocados pelo provedor de localização fundido para atualizar o aplicativo com informações de localização. Isso será discutido com mais detalhes a seguir.
Para notificar um aplicativo Xamarin.Android de uma atualização de local, o provedor de localização fundido invocará o LocationCallBack.OnLocationResult(LocationResult result)
. O Android.Gms.Location.LocationResult
parâmetro conterá as informações de local de atualização.
Quando o provedor de localização fundida detecta uma alteração na disponibilidade dos dados de localização, ele chamará o LocationProvider.OnLocationAvailability(LocationAvailability locationAvailability)
método. Se a LocationAvailability.IsLocationAvailable
propriedade retornar true
, pode-se presumir que os resultados de localização do dispositivo relatados por OnLocationResult
são tão precisos e atualizados quanto exigido pelo LocationRequest
. Se IsLocationAvailable
for false, nenhum resultado de localização será retornado por OnLocationResult
.
Este trecho de código é uma implementação de exemplo do LocationCallback
objeto:
public class FusedLocationProviderCallback : LocationCallback
{
readonly MainActivity activity;
public FusedLocationProviderCallback(MainActivity activity)
{
this.activity = activity;
}
public override void OnLocationAvailability(LocationAvailability locationAvailability)
{
Log.Debug("FusedLocationProviderSample", "IsLocationAvailable: {0}",locationAvailability.IsLocationAvailable);
}
public override void OnLocationResult(LocationResult result)
{
if (result.Locations.Any())
{
var location = result.Locations.First();
Log.Debug("Sample", "The latitude is :" + location.Latitude);
}
else
{
// No locations to work with.
}
}
}
Usando a API do Serviço de Localização do Android
O Serviço de Localização do Android é uma API mais antiga para usar informações de localização no Android. Os dados de localização são coletados por sensores de hardware e coletados por um serviço do sistema, que é acessado no aplicativo com uma LocationManager
classe e um ILocationListener
arquivo .
O Serviço de localização é mais adequado para aplicativos que devem ser executados em dispositivos que não têm o Google Play Services instalado.
O Serviço de Localização é um tipo especial de Serviço gerenciado pelo Sistema. Um Serviço do Sistema interage com o hardware do dispositivo e está sempre em execução. Para acessar as atualizações de localização em nosso aplicativo, assinaremos as atualizações de localização do Serviço de Localização do sistema usando uma LocationManager
e uma RequestLocationUpdates
chamada.
Para obter a localização do usuário usando o Serviço de Localização do Android envolve várias etapas:
- Obtenha uma referência para o
LocationManager
serviço. - Implemente a
ILocationListener
interface e manipule eventos quando o local for alterado. - Use o para solicitar atualizações de
LocationManager
local para um provedor especificado. OILocationListener
da etapa anterior será usado para receber retornos de chamada doLocationManager
. - Pare as atualizações de local quando o aplicativo não for mais apropriado para receber atualizações.
Gerente de Localização
Podemos acessar o serviço de localização do sistema com uma instância da LocationManager
classe. LocationManager
é uma classe especial que nos permite interagir com o serviço de localização do sistema e chamar métodos nele. Um aplicativo pode obter uma referência ao LocationManager
chamando GetSystemService
e passando em um tipo de serviço, conforme mostrado abaixo:
LocationManager locationManager = (LocationManager) GetSystemService(Context.LocationService);
OnCreate
é um bom lugar para obter uma referência para o LocationManager
.
É uma boa ideia manter o LocationManager
como uma variável de classe, para que possamos chamá-lo em vários pontos do ciclo de vida da atividade.
Solicitar atualizações de localização do LocationManager
Uma vez que o aplicativo tem uma referência ao LocationManager
, ele precisa dizer que LocationManager
tipo de informações de localização que são necessárias e com que frequência essas informações devem ser atualizadas. Faça isso chamando RequestLocationUpdates
o LocationManager
objeto e passando alguns critérios para atualizações e um retorno de chamada que receberá as atualizações de local. Esse retorno de chamada é um tipo que deve implementar a ILocationListener
interface (descrita com mais detalhes mais adiante neste guia).
O RequestLocationUpdates
método informa ao Serviço de localização do sistema que seu aplicativo gostaria de começar a receber atualizações de local. Esse método permite que você especifique o provedor, bem como limites de tempo e distância para controlar a frequência de atualização. Por exemplo, o método abaixo solicita atualizações de localização do provedor de localização GPS a cada 2000 milissegundos e somente quando o local muda mais de 1 metro:
// For this example, this method is part of a class that implements ILocationListener, described below
locationManager.RequestLocationUpdates(LocationManager.GpsProvider, 2000, 1, this);
Um aplicativo deve solicitar atualizações de local somente com a frequência necessária para que o aplicativo tenha um bom desempenho. Isso preserva a vida útil da bateria e cria uma melhor experiência para o usuário.
Respondendo a atualizações do LocationManager
Depois que um aplicativo solicita atualizações do LocationManager
, ele pode receber informações do Serviço implementando a ILocationListener
interface. Essa interface fornece quatro métodos para escutar o Serviço de localização e o provedor de localização, OnLocationChanged
. O Sistema chamará OnLocationChanged
quando a localização do usuário for alterada o suficiente para se qualificar como uma alteração de local de acordo com os Critérios definidos ao solicitar atualizações de localização.
O código a ILocationListener
seguir mostra os métodos na interface:
public class MainActivity : AppCompatActivity, ILocationListener
{
TextView latitude;
TextView longitude;
public void OnLocationChanged (Location location)
{
// called when the location has been updated.
}
public OnProviderDisabled(string locationProvider)
{
// called when the user disables the provider
}
public OnProviderEnabled(string locationProvider)
{
// called when the user enables the provider
}
public OnStatusChanged(string locationProvider, Availability status, Bundle extras)
{
// called when the status of the provider changes (there are a variety of reasons for this)
}
}
Cancelando a assinatura de atualizações do LocationManager
Para conservar os recursos do sistema, um aplicativo deve cancelar a assinatura de atualizações de local o mais rápido possível. O RemoveUpdates
método diz ao para parar de LocationManager
enviar atualizações para o nosso aplicativo. Como exemplo, uma Atividade pode chamar RemoveUpdates
o OnPause
método para que possamos economizar energia se um aplicativo não precisar de atualizações de localização enquanto sua Atividade não estiver na tela:
protected override void OnPause ()
{
base.OnPause ();
locationManager.RemoveUpdates (this);
}
Se o aplicativo precisar obter atualizações de localização em segundo plano, você desejará criar um Serviço personalizado que assine o Serviço de Localização do sistema. Consulte o guia Backgrounding with Android Services para obter mais informações.
Determinando o melhor provedor de localização para o LocationManager
O aplicativo acima define o GPS como o provedor de localização. No entanto, o GPS pode não estar disponível em todos os casos, como se o dispositivo estiver dentro de casa ou não tiver um receptor GPS. Se esse for o caso, o resultado será um null
retorno para o Provedor.
Para fazer com que seu aplicativo funcione quando o GPS não estiver disponível, use o GetBestProvider
método para solicitar o melhor provedor de localização disponível (suportado pelo dispositivo e habilitado pelo usuário) na inicialização do aplicativo. Em vez de passar um provedor específico, você pode dizer GetBestProvider
os requisitos para o provedor - como precisão e potência - com um Criteria
objeto. GetBestProvider
retorna o melhor provedor para os Critérios fornecidos.
O código a seguir mostra como obter o melhor provedor disponível e usá-lo ao solicitar atualizações de local:
Criteria locationCriteria = new Criteria();
locationCriteria.Accuracy = Accuracy.Coarse;
locationCriteria.PowerRequirement = Power.Medium;
locationProvider = locationManager.GetBestProvider(locationCriteria, true);
if(locationProvider != null)
{
locationManager.RequestLocationUpdates (locationProvider, 2000, 1, this);
}
else
{
Log.Info(tag, "No location providers available");
}
Observação
Se o usuário tiver desabilitado todos os provedores de localização, GetBestProvider
retornará null
. Para ver como esse código funciona em um dispositivo real, ative o GPS, o Wi-Fi e as redes celulares no Modo de localização > das Configurações > do Google, conforme mostrado nesta captura de tela:
A captura de tela abaixo demonstra o aplicativo de localização em execução usando GetBestProvider
:
Lembre-se de que GetBestProvider
isso não altera o provedor dinamicamente. Em vez disso, ele determina o melhor provedor disponível uma vez durante o ciclo de vida da atividade. Se o status do provedor for alterado depois de definido, o aplicativo exigirá código adicional nos ILocationListener
métodos – OnProviderEnabled
, OnProviderDisabled
e OnStatusChanged
– para lidar com todas as possibilidades relacionadas à troca de provedor.
Resumo
Este guia abordou a obtenção da localização do usuário usando o Serviço de localização do Android e o provedor de localização fundido da API dos Serviços de localização do Google.