Usługi lokalizacji w systemie Android
W tym przewodniku przedstawiono rozpoznawanie lokalizacji w aplikacjach systemu Android i pokazano, jak uzyskać lokalizację użytkownika przy użyciu interfejsu API usługi lokalizacji systemu Android, a także dostawcę lokalizacji połączonej dostępnego za pomocą interfejsu API usług Lokalizacyjne Google.
System Android zapewnia dostęp do różnych technologii lokalizacji, takich jak lokalizacja wieży komórkowej, Wi-Fi i GPS. Szczegóły każdej technologii lokalizacji są abstrakcje za pośrednictwem dostawców lokalizacji, co umożliwia aplikacjom uzyskiwanie lokalizacji w taki sam sposób, niezależnie od używanego dostawcy. W tym przewodniku przedstawiono połączonego dostawcę lokalizacji, część usług Google Play, która inteligentnie określa najlepszy sposób uzyskiwania lokalizacji urządzeń na podstawie dostępnych dostawców i sposobu użycia urządzenia. Interfejs API usługi lokalizacji systemu Android i pokazuje, jak komunikować się z usługą lokalizacji systemu przy użyciu elementu LocationManager
. Druga część przewodnika zawiera omówienie interfejsu API usług lokalizacji systemu Android przy użyciu polecenia LocationManager
.
Ogólnie rzecz biorąc, aplikacje powinny preferować korzystanie z połączonego dostawcy lokalizacji, wracając do starszego interfejsu API usługi lokalizacji systemu Android tylko wtedy, gdy jest to konieczne.
Podstawy lokalizacji
W systemie Android, bez względu na to, jaki interfejs API wybierzesz do pracy z danymi lokalizacji, kilka pojęć pozostaje takie same. W tej sekcji przedstawiono dostawców lokalizacji i uprawnienia związane z lokalizacją.
Dostawcy lokalizacji
Kilka technologii jest używanych wewnętrznie do określania lokalizacji użytkownika. Używany sprzęt zależy od typu dostawcy lokalizacji wybranego do zadania zbierania danych. System Android używa trzech dostawców lokalizacji:
DOSTAWCA GPS - GPS daje najdokładniejsze miejsce, wykorzystuje najwięcej mocy i działa najlepiej na zewnątrz. Ten dostawca używa kombinacji GPS i wspomaganego GPS (aGPS), który zwraca dane GPS zebrane przez wieże komórkowe.
Dostawca sieci — zapewnia kombinację danych sieci Wi-Fi i komórkowych, w tym danych aGPS zebranych przez wieże komórek. Używa mniejszej mocy niż dostawca GPS, ale zwraca dane lokalizacji o różnej dokładności.
Dostawca pasywny — opcja "piggyback" przy użyciu dostawców żądanych przez inne aplikacje lub usługi do generowania danych lokalizacji w aplikacji. Jest to mniej niezawodna, ale oszczędzająca energię opcja idealna dla aplikacji, które nie wymagają stałych aktualizacji lokalizacji do pracy.
Dostawcy lokalizacji nie zawsze są dostępni. Na przykład możemy chcieć użyć GPS dla naszej aplikacji, ale GPS może być wyłączony w Ustawienia lub urządzenie w ogóle nie ma GPS. Jeśli określony dostawca jest niedostępny, wybranie tego dostawcy może zwrócić wartość null
.
Uprawnienia lokalizacji
Aplikacja z obsługą lokalizacji wymaga dostępu do czujników sprzętowych urządzenia w celu odbierania danych GPS, Wi-Fi i komórkowych. Dostęp jest kontrolowany za pomocą odpowiednich uprawnień w manifeście systemu Android aplikacji. Dostępne są dwa uprawnienia — w zależności od wymagań aplikacji i wybranego interfejsu API należy zezwolić na jedno:
ACCESS_FINE_LOCATION
– Umożliwia aplikacji dostęp do GPS. Wymagane dla opcji dostawcy GPS i pasywnego dostawcy (Pasywny dostawca musi mieć uprawnienia dostępu do danych GPS zebranych przez inną aplikację lub usługę). Opcjonalne uprawnienie dla dostawcy sieci.ACCESS_COARSE_LOCATION
— umożliwia aplikacji dostęp do lokalizacji sieci komórkowej i sieci Wi-Fi. Wymagane dla dostawcy sieci, jeśliACCESS_FINE_LOCATION
nie jest ustawiony.
W przypadku aplikacji przeznaczonych dla interfejsu API w wersji 21 (Android 5.0 Lollipop) lub nowszej można włączyć ACCESS_FINE_LOCATION
i nadal działać na urządzeniach, które nie mają sprzętu GPS. Jeśli aplikacja wymaga sprzętu GPS, należy jawnie dodać android.hardware.location.gps
uses-feature
element do manifestu systemu Android. Aby uzyskać więcej informacji, zobacz informacje o elemencie uses-feature systemu Android.
Aby ustawić uprawnienia, rozwiń folder Właściwości w okienku rozwiązania i kliknij dwukrotnie AndroidManifest.xml. Uprawnienia zostaną wyświetlone w obszarze Wymagane uprawnienia:
Ustawienie jednego z tych uprawnień informuje system Android, że aplikacja potrzebuje uprawnień od użytkownika w celu uzyskania dostępu do dostawców lokalizacji. Urządzenia z poziomem 22 interfejsu API (Android 5.1) lub niższymi będą prosić użytkownika o przyznanie tych uprawnień za każdym razem, gdy aplikacja jest zainstalowana. Na urządzeniach z poziomem interfejsu API 23 (Android 6.0) lub nowszym aplikacja powinna wykonać kontrolę uprawnień w czasie wykonywania przed złożeniem żądania dostawcy lokalizacji.
Uwaga
Uwaga: ustawienie ACCESS_FINE_LOCATION
oznacza dostęp zarówno do grubych, jak i precyzyjnych danych lokalizacji. Nigdy nie należy ustawiać obu uprawnień— tylko minimalne uprawnienia wymagane przez aplikację.
Ten fragment kodu to przykład sprawdzania, czy aplikacja ma uprawnienia do ACCESS_FINE_LOCATION
uprawnień:
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.AccessFineLocation) == Permission.Granted)
{
StartRequestingLocationUpdates();
isRequestingLocationUpdates = true;
}
else
{
// The app does not have permission ACCESS_FINE_LOCATION
}
Aplikacje muszą być odporne na scenariusz, w którym użytkownik nie udzieli uprawnień (lub odwołał uprawnienie) i może bezpiecznie poradzić sobie z tym sytuacją. Aby uzyskać więcej informacji na temat implementowania kontroli uprawnień w czasie wykonywania na platformie Xamarin.Android, zobacz Przewodnik uprawnień.
Korzystanie z połączonego dostawcy lokalizacji
Dostawca lokalizacji połączonej jest preferowanym sposobem odbierania aktualizacji lokalizacji z urządzenia przez aplikacje systemu Android, ponieważ efektywnie wybierze dostawcę lokalizacji w czasie wykonywania, aby zapewnić najlepsze informacje o lokalizacji w sposób wydajny w baterii. Na przykład użytkownik idący na zewnątrz uzyskuje najlepszą lokalizację odczytu z GPS. Jeśli użytkownik następnie idzie w pomieszczeniu, gdzie GPS działa słabo (jeśli w ogóle), bezpieczni dostawcy lokalizacji może automatycznie przełączyć się do Wi-Fi, który działa lepiej w pomieszczeniach.
Interfejs API dostawcy lokalizacji połączonej udostępnia wiele innych narzędzi umożliwiających rozpoznawanie lokalizacji aplikacji, w tym geofencing i monitorowanie aktywności. W tej sekcji skupimy się na podstawach konfigurowania LocationClient
, ustanawiania dostawców i uzyskiwania lokalizacji użytkownika.
Połączony dostawca lokalizacji jest częścią usług Google Play. Pakiet usług Google Play musi być zainstalowany i prawidłowo skonfigurowany w aplikacji, aby interfejs API połączonego dostawcy lokalizacji działał, a urządzenie musi mieć zainstalowany pakiet APK usług Google Play.
Aby aplikacja platformy Xamarin.Android mogła korzystać z połączonego dostawcy lokalizacji, musi dodać pakiet Xamarin.GooglePlayServices.Location do projektu. Ponadto do wszystkich plików źródłowych odwołujących się do klas opisanych poniżej należy dodać następujące using
instrukcje:
using Android.Gms.Common;
using Android.Gms.Location;
Sprawdzanie, czy usługi Google Play są zainstalowane
Platforma Xamarin.Android ulegnie awarii, jeśli spróbuje użyć połączonego dostawcy lokalizacji, gdy usługi Google Play nie są zainstalowane (lub nieaktualne), wystąpi wyjątek środowiska uruchomieniowego. Jeśli usługi Google Play nie są zainstalowane, aplikacja powinna wrócić do usługi lokalizacji systemu Android omówionej powyżej. Jeśli usługi Google Play są nieaktualne, aplikacja może wyświetlić użytkownikowi komunikat z prośbą o zaktualizowanie zainstalowanej wersji usług Google Play.
Ten fragment kodu jest przykładem sposobu programowego sprawdzania, czy usługi Google Play są zainstalowane przez działanie systemu Android:
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
Aby móc korzystać z połączonego dostawcy lokalizacji, aplikacja platformy Xamarin.Android musi mieć wystąpienie klasy FusedLocationProviderClient
. Ta klasa uwidacznia niezbędne metody subskrybowania aktualizacji lokalizacji i pobierania ostatniej znanej lokalizacji urządzenia.
OnCreate
Metoda działania jest odpowiednim miejscem do uzyskania odwołania do FusedLocationProviderClient
elementu , jak pokazano w poniższym fragmencie kodu:
public class MainActivity: AppCompatActivity
{
FusedLocationProviderClient fusedLocationProviderClient;
protected override void OnCreate(Bundle bundle)
{
fusedLocationProviderClient = LocationServices.GetFusedLocationProviderClient(this);
}
}
Pobieranie ostatniej znanej lokalizacji
Metoda FusedLocationProviderClient.GetLastLocationAsync()
zapewnia prosty, nieblokujący sposób na szybkie uzyskanie ostatniej znanej lokalizacji urządzenia z minimalnym obciążeniem kodowania dla aplikacji platformy Xamarin.Android.
Ten fragment kodu przedstawia sposób użycia GetLastLocationAsync
metody w celu pobrania lokalizacji urządzenia:
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);
}
}
Subskrybowanie aktualizacji lokalizacji
Aplikacja platformy Xamarin.Android może również subskrybować aktualizacje lokalizacji od dostawcy lokalizacji połączonej FusedLocationProviderClient.RequestLocationUpdatesAsync
przy użyciu metody , jak pokazano w tym fragmencie kodu:
await fusedLocationProviderClient.RequestLocationUpdatesAsync(locationRequest, locationCallback);
Ta metoda przyjmuje dwa parametry:
Android.Gms.Location.LocationRequest
LocationRequest
— Obiekt to sposób, w jaki aplikacja platformy Xamarin.Android przekazuje parametry dotyczące sposobu działania połączonego dostawcy lokalizacji. ZawieraLocationRequest
informacje, takie jak częstotliwość żądań lub jak ważna powinna być dokładna aktualizacja lokalizacji. Na przykład ważne żądanie lokalizacji spowoduje, że urządzenie będzie korzystać z GPS, a w konsekwencji większej mocy podczas określania lokalizacji. Ten fragment kodu pokazuje, jak utworzyć obiektLocationRequest
dla lokalizacji o wysokiej dokładności, sprawdzając co około pięć minut aktualizacji lokalizacji (ale nie wcześniej niż dwie minuty między żądaniami). Dostawca lokalizacji połączonejLocationRequest
będzie używać jako wskazówek dla dostawcy lokalizacji, który ma być używany podczas próby określenia lokalizacji urządzenia:LocationRequest locationRequest = new LocationRequest() .SetPriority(LocationRequest.PriorityHighAccuracy) .SetInterval(60 * 1000 * 5) .SetFastestInterval(60 * 1000 * 2);
Android.Gms.Location.LocationCallback
— Aby otrzymywać aktualizacje lokalizacji, aplikacja platformy Xamarin.Android musi podklasować klasę abstrakcyjnąLocationProvider
. Ta klasa uwidoczniła dwie metody, które mogą być wywoływane przez dostawcę lokalizacji połączonej w celu zaktualizowania aplikacji przy użyciu informacji o lokalizacji. Zostanie to omówione bardziej szczegółowo poniżej.
Aby powiadomić aplikację platformy Xamarin.Android o aktualizacji lokalizacji, dostawca lokalizacji połączonej wywoła metodę LocationCallBack.OnLocationResult(LocationResult result)
. Parametr Android.Gms.Location.LocationResult
będzie zawierać informacje o lokalizacji aktualizacji.
Gdy dostawca lokalizacji połączonej wykryje zmianę dostępności danych lokalizacji, wywoła metodę LocationProvider.OnLocationAvailability(LocationAvailability locationAvailability)
. LocationAvailability.IsLocationAvailable
Jeśli właściwość zwraca true
wartość , można założyć, że wyniki lokalizacji urządzenia zgłoszone przez OnLocationResult
usługę są tak dokładne, jak i aktualne zgodnie z wymaganiami .LocationRequest
Jeśli IsLocationAvailable
ma wartość false, wyniki lokalizacji nie zostaną zwrócone przez OnLocationResult
.
Ten fragment kodu to przykładowa implementacja LocationCallback
obiektu:
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.
}
}
}
Korzystanie z interfejsu API usługi lokalizacji systemu Android
Usługa lokalizacji systemu Android to starszy interfejs API do korzystania z informacji o lokalizacji w systemie Android. Dane lokalizacji są zbierane przez czujniki sprzętowe i zbierane przez usługę systemową, do której uzyskuje się dostęp w aplikacji z klasą LocationManager
i klasą ILocationListener
.
Usługa Location Service najlepiej nadaje się do aplikacji, które muszą działać na urządzeniach, na których nie zainstalowano usług Google Play.
Usługa lokalizacji jest specjalnym typem usługi zarządzanej przez system. Usługa systemowa współdziała ze sprzętem urządzenia i zawsze działa. Aby wykorzystać aktualizacje lokalizacji w naszej aplikacji, zasubskrybujemy aktualizacje lokalizacji z usługi lokalizacji systemowej przy użyciu LocationManager
wywołania RequestLocationUpdates
i .
Aby uzyskać lokalizację użytkownika przy użyciu usługi Lokalizacji systemu Android, należy wykonać kilka kroków:
- Uzyskaj odwołanie do
LocationManager
usługi. - Zaimplementuj
ILocationListener
interfejs i obsłuż zdarzenia po zmianie lokalizacji. - Użyj polecenia ,
LocationManager
aby zażądać aktualizacji lokalizacji dla określonego dostawcy. ElementILocationListener
z poprzedniego kroku będzie używany do odbierania wywołań zwrotnych z elementuLocationManager
. - Zatrzymaj aktualizacje lokalizacji, gdy aplikacja nie jest już odpowiednia do odbierania aktualizacji.
Menedżer lokalizacji
Możemy uzyskać dostęp do usługi lokalizacji systemu przy użyciu wystąpienia LocationManager
klasy . LocationManager
to specjalna klasa, która umożliwia interakcję z usługą lokalizacji systemu i wywoływanie metod. Aplikacja może uzyskać odwołanie do elementu LocationManager
, wywołując GetSystemService
i przekazując typ usługi, jak pokazano poniżej:
LocationManager locationManager = (LocationManager) GetSystemService(Context.LocationService);
OnCreate
to dobre miejsce, aby uzyskać odwołanie do .LocationManager
Warto zachować LocationManager
zmienną jako zmienną klasy, aby można było ją wywołać w różnych punktach cyklu życia działania.
Żądanie aktualizacji lokalizacji z menedżera lokalizacji
Gdy aplikacja ma odwołanie do LocationManager
elementu , musi poinformować LocationManager
, jakiego typu informacje o lokalizacji są wymagane i jak często te informacje mają być aktualizowane. W tym celu należy wywołać RequestLocationUpdates
LocationManager
obiekt i przekazać pewne kryteria aktualizacji oraz wywołanie zwrotne, które otrzymają aktualizacje lokalizacji. To wywołanie zwrotne jest typem, który musi zaimplementować ILocationListener
interfejs (opisany bardziej szczegółowo w dalszej części tego przewodnika).
Metoda RequestLocationUpdates
informuje usługę lokalizacji systemowej, że aplikacja chce rozpocząć odbieranie aktualizacji lokalizacji. Ta metoda umożliwia określenie dostawcy, a także progów czasu i odległości w celu kontrolowania częstotliwości aktualizacji. Na przykład poniższa metoda żąda aktualizacji lokalizacji od dostawcy lokalizacji GPS co 2000 milisekund i tylko wtedy, gdy lokalizacja zmienia się ponad 1 metr:
// For this example, this method is part of a class that implements ILocationListener, described below
locationManager.RequestLocationUpdates(LocationManager.GpsProvider, 2000, 1, this);
Aplikacja powinna żądać aktualizacji lokalizacji tylko tak często, jak to konieczne, aby aplikacja mogła działać prawidłowo. Pozwala to zachować żywotność baterii i utworzyć lepsze środowisko dla użytkownika.
Odpowiadanie na aktualizacje z menedżera lokalizacji
Gdy aplikacja zażąda aktualizacji z LocationManager
usługi , może odbierać informacje z usługi przez zaimplementowanie interfejsu ILocationListener
. Ten interfejs udostępnia cztery metody nasłuchiwania usługi lokalizacji i dostawcy lokalizacji, OnLocationChanged
. System wywoła OnLocationChanged
, gdy lokalizacja użytkownika zmieni się na tyle, aby zakwalifikować się do zmiany lokalizacji zgodnie z kryteriami ustawionymi podczas żądania aktualizacji lokalizacji.
Poniższy kod przedstawia metody w interfejsie ILocationListener
:
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)
}
}
Anulowanie subskrybowania aktualizacji elementu LocationManager
Aby oszczędzać zasoby systemowe, aplikacja powinna anulować subskrypcję aktualizacji lokalizacji tak szybko, jak to możliwe. Metoda RemoveUpdates
nakazuje LocationManager
zatrzymać wysyłanie aktualizacji do naszej aplikacji. Na przykład działanie może wywołać RemoveUpdates
metodę , OnPause
abyśmy mogli oszczędzać moc, jeśli aplikacja nie potrzebuje aktualizacji lokalizacji, gdy jego działanie nie znajduje się na ekranie:
protected override void OnPause ()
{
base.OnPause ();
locationManager.RemoveUpdates (this);
}
Jeśli aplikacja musi pobierać aktualizacje lokalizacji w tle, należy utworzyć usługę niestandardową, która subskrybuje systemową usługę lokalizacji. Aby uzyskać więcej informacji, zapoznaj się z przewodnikiem Backgrounding with Android Services (Obsługa w tle za pomocą usług systemu Android).
Określanie najlepszego dostawcy lokalizacji dla menedżera lokalizacji
Powyższa aplikacja ustawia GPS jako dostawcę lokalizacji. Gps może być jednak niedostępny we wszystkich przypadkach, na przykład jeśli urządzenie jest w pomieszczeniu lub nie ma odbiornika GPS. W takim przypadku wynik jest zwracany przez dostawcę null
.
Aby aplikacja działała, gdy gps jest niedostępny, użyj GetBestProvider
metody , aby poprosić o najlepszą dostępną (obsługiwaną przez urządzenie i włączoną przez użytkownika) dostawcę lokalizacji podczas uruchamiania aplikacji. Zamiast przekazywać określonego dostawcę, możesz określić GetBestProvider
wymagania dostawcy — takie jak dokładność i moc — za pomocą Criteria
obiektu. GetBestProvider
zwraca najlepszego dostawcę dla danego kryterium.
Poniższy kod pokazuje, jak uzyskać najlepszego dostępnego dostawcę i używać go podczas żądania aktualizacji lokalizacji:
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");
}
Uwaga
Jeśli użytkownik wyłączył wszystkich dostawców lokalizacji, GetBestProvider
zwróci wartość null
. Aby zobaczyć, jak działa ten kod na rzeczywistym urządzeniu, upewnij się, że włączono gps, Wi-Fi i sieci komórkowej w obszarze Google Ustawienia > Tryb lokalizacji>, jak pokazano na poniższym zrzucie ekranu:
Poniższy zrzut ekranu przedstawia aplikację lokalizacji uruchomioną przy użyciu polecenia GetBestProvider
:
Należy pamiętać, że GetBestProvider
dostawca nie zmienia się dynamicznie. Zamiast tego określa najlepszego dostępnego dostawcę raz w cyklu życia działania. Jeśli stan dostawcy zmieni się po jego ustawieniu, aplikacja będzie wymagać dodatkowego ILocationListener
kodu w metodach — OnProviderEnabled
, OnProviderDisabled
i OnStatusChanged
— do obsługi każdej możliwości związanej z przełącznikiem dostawcy.
Podsumowanie
W tym przewodniku opisano uzyskiwanie lokalizacji użytkownika przy użyciu usługi Lokalizacji systemu Android i połączonego dostawcy lokalizacji z interfejsu API usług lokalizacji Google.