Geolokalizacja
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ęź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 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ć null
wartość , 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ć null
wartość , 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.