Udostępnij za pośrednictwem


Geolokalizacja

Browse sample. 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 Geolocation.Default właściwości . Zarówno interfejs, jak IGeolocation i Geolocation klasa są zawarte w Microsoft.Maui.Devices.Sensors przestrzeni nazw.

Rozpocznij

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

Należy określić coarse lub grzywny uprawnienia lokalizacji lub oba te uprawnienia i należy je skonfigurować 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 Platformy/Android/MainApplication.cs i dodaj następujące atrybuty zestawu po using dyrektywach:

    [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 Platformy/Android/AndroidManifest.xml i dodaj następujący kod w węźlemanifest:

    <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 Platformy/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 .

Napiwek

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

Pobieranie ostatniej znanej lokalizacji

Urządzenie mogło buforowane 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

W razie potrzeby interfejs API geolokalizacji monituje użytkownika o uprawnienia.

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 Altitude właściwość może mieć nullwartość , ma wartość 0 lub wartość dodatnią wskazującą mierniki nad poziomem morza. Inne wartości, które mogą nie być obecne, obejmują Speed właściwości i 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

W razie potrzeby interfejs API geolokalizacji monituje użytkownika o uprawnienia.

W poniższym przykładzie kodu pokazano, jak zażądać lokalizacji urządzenia podczas obsługi 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 Altitude właściwość może mieć nullwartość , ma wartość 0 lub wartość dodatnią wskazującą mierniki nad poziomem morza. Inne wartości, które mogą nie być obecne, obejmują Speed i Course.

Ostrzeżenie

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

Nasłuchiwanie zmian lokalizacji

Oprócz wykonywania zapytań dotyczących urządzenia dla bieżącej lokalizacji można nasłuchiwać zmian lokalizacji, gdy aplikacja znajduje się na pierwszym planie.

Aby sprawdzić, czy aplikacja obecnie nasłuchuje zmian lokalizacji, istnieje IsListeningForeground właściwość, którą można wykonać. 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 znajduje się na pierwszym planie. Obiekt GeolocationLocationChangedEventArgs , który towarzyszy temu zdarzeniu, ma Location właściwość typu Location, która reprezentuje wykrytą nową lokalizację.

Uwaga

W razie potrzeby interfejs API geolokalizacji monituje użytkownika o uprawnienia.

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 wystąpieniu ListeningFailed zdarzenia nasłuchiwanie dalszych zmian lokalizacji zatrzymuje się i nie są wywoływane żadne dalsze LocationChanged zdarzenia.

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

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

Dokładność

W poniższych sekcjach opisano odległość dokładności lokalizacji na platformę:

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ższe

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

Minimum

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

Maksimum

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ć pozorną lokalizację od dostawcy lub przez aplikację udostępniającą pozorne lokalizacje. Możesz to wykryć, używając elementu IsFromMockProvider w dowolnym Locationobiekcie :

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 Stany Zjednoczone miastami 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 CalculateDistance określić kilometry lub kilometry. Klasa UnitConverters definiuje KilometersToMiles MilesToKilometers również metody i do konwertowania między dwiema jednostkami.

Różnice między platformami

W tej sekcji opisano różnice specyficzne dla platformy dotyczące interfejsu 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.