Udostępnij za pośrednictwem


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śli ACCESS_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.gpsuses-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:

Zrzut ekranu przedstawiający ustawienia wymaganych uprawnień manifestu systemu Android

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 FusedLocationProviderClientelementu , 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.LocationRequestLocationRequest— Obiekt to sposób, w jaki aplikacja platformy Xamarin.Android przekazuje parametry dotyczące sposobu działania połączonego dostawcy lokalizacji. Zawiera LocationRequest 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ć obiekt LocationRequest 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łączonej LocationRequest 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 truewartość , 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:

  1. Uzyskaj odwołanie do LocationManager usługi.
  2. Zaimplementuj ILocationListener interfejs i obsłuż zdarzenia po zmianie lokalizacji.
  3. Użyj polecenia , LocationManager aby zażądać aktualizacji lokalizacji dla określonego dostawcy. Element ILocationListener z poprzedniego kroku będzie używany do odbierania wywołań zwrotnych z elementu LocationManager.
  4. 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);

OnCreateto 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 LocationManagerelementu , 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ć RequestLocationUpdatesLocationManager 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 LocationManagerusł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:

Ustawienia ekran trybu lokalizacji na telefonie z systemem Android

Poniższy zrzut ekranu przedstawia aplikację lokalizacji uruchomioną przy użyciu polecenia GetBestProvider:

Aplikacja GetBestProvider wyświetlającą szerokość geograficzną, długość geograficzną i dostawcę

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, OnProviderDisabledi 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.