Udostępnij za pośrednictwem


Geolokalizacja

Przeglądaj przykład. Przeglądanie przykładu

W tym artykule opisano sposób używania interfejsu użytkownika aplikacji wieloplatformowej platformy .NET (.NET MAUI). IGeolocation Ten interfejs udostępnia interfejsy API umożliwiające pobieranie bieżących współrzędnych geolokalizacji urządzenia.

Domyślna implementacja interfejsu IGeolocation jest dostępna za pośrednictwem właściwości Geolocation.Default. Zarówno interfejs IGeolocation, jak i klasa Geolocation znajdują się w przestrzeni nazw Microsoft.Maui.Devices.Sensors.

Rozpocznij

Aby uzyskać dostęp do funkcji geolokalizacji , wymagana jest następująca konfiguracja specyficzna dla platformy:

Należy określić uprawnienia do ogólnej lub dokładnej lokalizacji, lub oba, i skonfigurować je w projekcie systemu Android.

Ponadto jeśli aplikacja jest przeznaczona dla systemu Android 5.0 (poziom 21 interfejsu API) lub nowszy, musisz zadeklarować, że aplikacja korzysta z funkcji sprzętowych w pliku manifestu. Można to dodać w następujący sposób:

  • Dodaj uprawnienie oparte na zestawie:

    Otwórz plik Platforms/Android/MainApplication.cs i dodaj następujące atrybuty asemblacji po using dyrektyw:

    [assembly: UsesPermission(Android.Manifest.Permission.AccessCoarseLocation)]
    [assembly: UsesPermission(Android.Manifest.Permission.AccessFineLocation)]
    [assembly: UsesFeature("android.hardware.location", Required = false)]
    [assembly: UsesFeature("android.hardware.location.gps", Required = false)]
    [assembly: UsesFeature("android.hardware.location.network", Required = false)]
    

    Jeśli aplikacja jest przeznaczona dla systemu Android 10 — Q (poziom interfejsu API 29 lub nowszy) i żąda LocationAlways, musisz również dodać to żądanie uprawnień:

    [assembly: UsesPermission(Android.Manifest.Permission.AccessBackgroundLocation)]
    

    - lub -

  • Zaktualizuj manifest systemu Android:

    Otwórz plik Platforms/Android/AndroidManifest.xml i dodaj następujący kod w węźle manifest:

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.location" android:required="false" />
    <uses-feature android:name="android.hardware.location.gps" android:required="false" />
    <uses-feature android:name="android.hardware.location.network" android:required="false" />
    

    Jeśli aplikacja jest przeznaczona dla systemu Android 10 — Q (poziom interfejsu API 29 lub nowszy) i żąda LocationAlways, musisz również dodać to żądanie uprawnień:

    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    

    - lub -

  • Zaktualizuj manifest systemu Android w edytorze manifestu:

    W programie Visual Studio kliknij dwukrotnie plik Platforms/Android/AndroidManifest.xml, aby otworzyć edytor manifestu systemu Android. Następnie w obszarze Wymagane uprawnienia sprawdź uprawnienia wymienione powyżej. Spowoduje to automatyczne zaktualizowanie pliku AndroidManifest.xml.

Wskazówka

Zapoznaj się z dokumentacją systemu Android dotyczącą aktualizacji lokalizacji w tle, ponieważ należy wziąć pod uwagę wiele ograniczeń.

Uzyskaj ostatnią znaną lokalizację

Urządzenie mogło zbuforować najnowszą lokalizację urządzenia. GetLastKnownLocationAsync() Użyj metody , aby uzyskać dostęp do buforowanej lokalizacji, jeśli jest dostępna. Jest to często szybsze niż wykonywanie pełnego zapytania o lokalizację, ale może być mniej dokładne. Jeśli nie istnieje lokalizacja buforowana, ta metoda zwraca wartość null.

Uwaga / Notatka

W razie potrzeby interfejs API geolokalizacji prosi użytkownika o przyznanie uprawnień.

W poniższym przykładzie kodu pokazano sprawdzanie lokalizacji buforowanej:

public async Task<string> GetCachedLocation()
{
    try
    {
        Location location = await Geolocation.Default.GetLastKnownLocationAsync();

        if (location != null)
            return $"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}";
    }
    catch (FeatureNotSupportedException fnsEx)
    {
        // Handle not supported on device exception
    }
    catch (FeatureNotEnabledException fneEx)
    {
        // Handle not enabled on device exception
    }
    catch (PermissionException pEx)
    {
        // Handle permission exception
    }
    catch (Exception ex)
    {
        // Unable to get location
    }

    return "None";
}

W zależności od urządzenia nie wszystkie wartości lokalizacji mogą być dostępne. Na przykład właściwość Altitude może być null, mieć wartość 0 lub wartość dodatnią wskazującą metry nad poziomem morza. Inne wartości, które mogą nie być obecne, obejmują właściwość Speed oraz właściwość Course.

Pobieranie bieżącej lokalizacji

Sprawdzanie ostatniej znanej lokalizacji urządzenia może być szybsze, ale może być niedokładne. Użyj metody , GetLocationAsync aby wysłać zapytanie do urządzenia dla bieżącej lokalizacji. Można skonfigurować dokładność i limit czasu zapytania. Najlepszym rozwiązaniem jest przeciążenie metody korzystającej z GeolocationRequest parametrów i CancellationToken , ponieważ uzyskanie lokalizacji urządzenia może zająć trochę czasu.

Uwaga / Notatka

W razie potrzeby interfejs API geolokalizacji prosi użytkownika o zgodę.

W poniższym przykładzie kodu pokazano, jak zażądać lokalizacji urządzenia, zapewniając możliwość anulowania:

private CancellationTokenSource _cancelTokenSource;
private bool _isCheckingLocation;

public async Task GetCurrentLocation()
{
    try
    {
        _isCheckingLocation = true;

        GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));

        _cancelTokenSource = new CancellationTokenSource();

        Location location = await Geolocation.Default.GetLocationAsync(request, _cancelTokenSource.Token);

        if (location != null)
            Console.WriteLine($"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}");
    }
    // Catch one of the following exceptions:
    //   FeatureNotSupportedException
    //   FeatureNotEnabledException
    //   PermissionException
    catch (Exception ex)
    {
        // Unable to get location
    }
    finally
    {
        _isCheckingLocation = false;
    }
}

public void CancelRequest()
{
    if (_isCheckingLocation && _cancelTokenSource != null && _cancelTokenSource.IsCancellationRequested == false)
        _cancelTokenSource.Cancel();
}

Nie wszystkie wartości lokalizacji mogą być dostępne w zależności od urządzenia. Na przykład, właściwość Altitude może mieć wartość null, wartość 0 lub wartość dodatnią wskazującą metry nad poziomem morza. Inne wartości, które mogą nie być obecne, obejmują Speed i Course.

Ostrzeżenie

GetLocationAsync może zwrócić null w niektórych scenariuszach. Oznacza to, że platforma bazowa nie może uzyskać bieżącej lokalizacji.

Nasłuchiwanie zmian lokalizacji

Oprócz zapytania urządzenia o bieżącą lokalizację, można nasłuchiwać zmian lokalizacji, gdy aplikacja jest na pierwszym planie.

Aby sprawdzić, czy aplikacja obecnie nasłuchuje zmian lokalizacji, można zapytać o właściwość IsListeningForeground. Gdy wszystko będzie gotowe do rozpoczęcia nasłuchiwania zmian lokalizacji, należy wywołać metodę StartListeningForegroundAsync . Ta metoda rozpoczyna nasłuchiwanie aktualizacji lokalizacji i zgłasza LocationChanged zdarzenie, gdy lokalizacja ulegnie zmianie, pod warunkiem, że aplikacja jest na pierwszym planie. Obiekt GeolocationLocationChangedEventArgs , który towarzyszy temu zdarzeniu, ma Location właściwość typu Location, która reprezentuje wykrytą nową lokalizację.

Uwaga / Notatka

W razie potrzeby interfejs API geolokalizacji prosi użytkownika o zezwolenia.

W poniższym przykładzie kodu pokazano, jak nasłuchiwać zmiany lokalizacji i jak przetwarzać zmienioną lokalizację:

async void OnStartListening()
{
    try
    {
        Geolocation.LocationChanged += Geolocation_LocationChanged;
        var request = new GeolocationListeningRequest((GeolocationAccuracy)Accuracy);
        var success = await Geolocation.StartListeningForegroundAsync(request);

        string status = success
            ? "Started listening for foreground location updates"
            : "Couldn't start listening";
    }
    catch (Exception ex)
    {
        // Unable to start listening for location changes
    }
}

void Geolocation_LocationChanged(object sender, GeolocationLocationChangedEventArgs e)
{
    // Process e.Location to get the new location
}

Obsługę błędów można zaimplementować, rejestrując program obsługi zdarzeń dla ListeningFailed zdarzenia. Obiekt GeolocationListeningFailedEventArgs , który towarzyszy temu zdarzeniu, ma Error właściwość typu GeolocationError, która wskazuje, dlaczego nasłuchiwanie nie powiodło się. Po podniesieniu zdarzenia ListeningFailed zatrzymuje się nasłuchiwanie dalszych zmian lokalizacji i nie są wywoływane żadne dalsze zdarzenia LocationChanged.

Aby zatrzymać nasłuchiwanie zmian lokalizacji, wywołaj metodę StopListeningForeground :

void OnStopListening()
{
    try
    {
        Geolocation.LocationChanged -= Geolocation_LocationChanged;
        Geolocation.StopListeningForeground();
        string status = "Stopped listening for foreground location updates";
    }
    catch (Exception ex)
    {
        // Unable to stop listening for location changes
    }
}

Uwaga / Notatka

Metoda StopListeningForeground nie ma wpływu, gdy aplikacja nie nasłuchuje zmian lokalizacji.

Sprawdzanie, czy usługi lokalizacji są włączone

Klasa Geolocation ma właściwość tylko IsEnabled do odczytu, która może służyć do określenia, czy usługi lokalizacji zostały włączone na urządzeniu.

Dokładność

W poniższych sekcjach przedstawiono dokładność lokalizacji w zależności od platformy.

Ważne

System iOS ma pewne ograniczenia dotyczące dokładności. Aby uzyskać więcej informacji, zobacz sekcję Różnice między platformami .

Najniższy

Platforma Odległość (w metrach)
Android 500
Ios 3000
Windows 1000 - 5000

Niski

Platforma Odległość (w metrach)
Android 500
Ios 1000
Windows 300 - 3000

Średni (wartość domyślna)

Platforma Odległość (w metrach)
Android 100 - 500
Ios 100
Windows 30-500

Wysoki

Platforma Odległość (w metrach)
Android 0 - 100
Ios 10
Windows <= 10

Najlepsze

Platforma Odległość (w metrach)
Android 0 - 100
Ios ~0
Windows <= 10

Wykrywanie pozornych lokalizacji

Niektóre urządzenia mogą zwracać fikcyjną lokalizację od dostawcy lub przez aplikację udostępniającą fikcyjne lokalizacje. Możesz to wykryć, używając elementu IsFromMockProvider w dowolnym Location:

public async Task CheckMock()
{
    GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium);
    Location location = await Geolocation.Default.GetLocationAsync(request);

    if (location != null && location.IsFromMockProvider)
    {
        // location is from a mock provider
    }
}

Odległość między dwiema lokalizacjami

Metoda CalculateDistance oblicza odległość między dwiema lokalizacjami geograficznymi. Ta obliczona odległość nie bierze pod uwagę dróg ani innych ścieżek i jest tylko najkrótszą odległością między dwoma punktami na powierzchni Ziemi. To obliczenie jest określane jako obliczanie odległości z dużym okręgiem .

Poniższy kod oblicza odległość między miastami Stanów Zjednoczonych Ameryki Boston i San Francisco:

Location boston = new Location(42.358056, -71.063611);
Location sanFrancisco = new Location(37.783333, -122.416667);

double miles = Location.CalculateDistance(boston, sanFrancisco, DistanceUnits.Miles);

Konstruktor Location(Double, Double, Double) akceptuje odpowiednio argumenty szerokości geograficznej i długości geograficznej. Dodatnie wartości szerokości geograficznej są na północ od równika, a dodatnie wartości długości geograficznej są na wschód od Regionu Głównego. Użyj argumentu końcowego, aby w CalculateDistance określić mile lub kilometry. Klasa UnitConverters definiuje również metody KilometersToMiles oraz MilesToKilometers do konwertowania między dwiema jednostkami.

Różnice między platformami

W tej części opisano różnice specyficzne dla platformy związane z interfejsem API geolokalizacji.

Wysokość jest obliczana inaczej na każdej platformie.

W systemie Android wysokość, jeśli jest dostępna, jest zwracana w metrach powyżej wielokropka WGS 84 odwołania. Jeśli ta lokalizacja nie ma wysokości, 0.0 zostanie zwrócona.

Właściwość Location.ReducedAccuracy jest używana tylko przez system iOS i zwraca wartość false na wszystkich innych platformach.