Содержание
В предыдущей части мы использовали объекты класса Location
исключительно для вывода данных о широте и долготе местоположения устройства. Вместе с тем, класс Location
предоставляет и другие полезные свойства и методы, которые мы изучим в этой части.
Класс Location
Свойства класса
Класс Location
содержит информацию о местоположении, а также предоставляет ряд методов для расчёта расстояний между двумя точками. У класса определены следующие свойства:
Свойство | Тип | Описание |
Accuracy |
double? |
Горизонтальная точность определения местоположения в метрах |
Altitude |
double? |
Высота расположения |
AltitudeReferenceSystem |
AltitudeReferenceSystem |
Система в которой определялось значение Altitude. Может принимать следующие значения:
|
Course |
double? |
Азимут местоположения (градусы относительно истинного севера на момент определения местоположения) |
IsFromMockProvider |
bool |
Указывает, является ли это расположение источником из макетированного датчика и, следовательно, может не быть реальным расположением устройства |
Latitude |
double |
Широта |
Longitude |
double |
Долгота |
ReducedAccuracy |
bool |
Указывает имеет ли это расположение сниженную точность чтения (используется только в iOS) |
Speed |
double? |
Скорость в метрах в секунду на момент определения местоположения |
Timestamp |
DateTimeOffset |
Метка времени в формате UTC |
VerticalAccuracy |
double? |
Вертикальная точность определения местоположения в метрах |
Как можно видеть по типам данных, которые используются в свойствах, не все значения свойств могут возвращаться. Например, горизонтальная и вертикальная точность, высота и скорость могут отсутствовать в возвращаемых значениях.
Что касается определения высоты (Altitude
), то в Android это значение всегда возвращается в системе WGS-84 (свойство AltitudeReferenceSystem
равно Ellipsoid
).
Методы класса
Что касается методов класса Location
, то здесь стоит отметить метод CalculateDistance()
, который имеет несколько перегрузок и позволяет рассчитываться расстояние между двумя местоположениями. Одна из версий этого метода выглядит следующим образом:
public static double CalculateDistance(Location locationStart, Location locationEnd, DistanceUnits units);
здесь locationStart
— начальное местоположение, locationEnd
— конечное местоположение, DistanceUnits
— единицы измерения, может принимать следующие значения:
Kilometers
— расстояние возвращается в километрахMiles
— расстояние возвращается в милях
Попробуем воспользоваться этим методом в нашем приложении, которое мы разработали в предыдущей части.
Определение расстояний с помощью класса Location
На данный момент наше приложение умеет прослушивать событие смены местоположения. Сам обработчик события выглядит следующим образом:
private void OnLocationChanged(object? sender, GeolocationLocationChangedEventArgs args) { Locations.Add(args.Location); }
А весь исходный код класса MainPage
следующий:
using System.Collections.ObjectModel; namespace MauiLocation { public partial class MainPage : ContentPage { private CancellationTokenSource _cancelTokenSource; private bool _isCheckingLocation; public ObservableCollection<Location> Locations { get; private set; } = []; public string LastError { get; private set; } = string.Empty; public MainPage() { InitializeComponent(); } private void OnLocationChanged(object? sender, GeolocationLocationChangedEventArgs args) { Locations.Add(args.Location); } public void OnListeningFiled(object? sender, GeolocationListeningFailedEventArgs args) { switch (args.Error) { case GeolocationError.Unauthorized: { LastError = "Разрешение на получение данных о местоположении устройства было отозвано"; break; } case GeolocationError.PositionUnavailable: { LastError = "Не удалось получить данные о местоположении"; break; } } } private async void OnListeningClicked(object sender, EventArgs e) { if (Geolocation.Default.IsListeningForeground) { Geolocation.Default.LocationChanged -= OnLocationChanged; Geolocation.Default.ListeningFailed -= OnListeningFiled; Geolocation.Default.StopListeningForeground(); } else { Geolocation.Default.LocationChanged += OnLocationChanged; Geolocation.Default.ListeningFailed += OnListeningFiled; GeolocationListeningRequest request = new GeolocationListeningRequest(); request.DesiredAccuracy = GeolocationAccuracy.Best; request.MinimumTime = TimeSpan.FromSeconds(1); if (await Geolocation.Default.StartListeningForegroundAsync(request) == false) LastError = "Не смогли запустить прослушивание"; } } private async void OnCounterClicked(object sender, EventArgs e) { _isCheckingLocation = true; Indicator.IsRunning = _isCheckingLocation; GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(20)); _cancelTokenSource = new CancellationTokenSource(); Location? location = await Geolocation.Default.GetLocationAsync(request, _cancelTokenSource.Token); if (location != null) { LatitudeLabel.Text = location.Latitude.ToString(); LongitudeLabel.Text = location.Longitude.ToString(); } _isCheckingLocation = false; Indicator.IsRunning = _isCheckingLocation; } public void CancelRequestClicked(object sender, EventArgs e) { if (_isCheckingLocation && _cancelTokenSource != null && _cancelTokenSource.IsCancellationRequested == false) _cancelTokenSource.Cancel(); } } }
Изменим обработчик события смены местоположения следующим образом:
public partial class MainPage : ContentPage, INotifyPropertyChanged { ... public double Distance { get; set; } ... private void OnLocationChanged(object? sender, GeolocationLocationChangedEventArgs args) { if (Locations.Count > 0) { var startLocation = Locations.Last(); Distance = Location.CalculateDistance(startLocation, args.Location, DistanceUnits.Kilometers); DistanceLabel.Text = Distance.ToString(); } Locations.Add(args.Location); } ... }
Здесь мы, используя метод CalculateDistance()
, рассчитываем расстояние между текущей и предыдущей точкой расположения устройства.
Исходный код страницы MainPage сделаем таким:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:locations="clr-namespace:Microsoft.Maui.Devices.Sensors;assembly=Microsoft.Maui.Essentials" x:Class="MauiLocation.MainPage" xmlns:m="clr-namespace:MauiLocation" x:DataType="m:MainPage"> <ScrollView> <VerticalStackLayout Padding="30,0" Spacing="25"> <ActivityIndicator ZIndex="1" IsRunning="False" x:Name="Indicator"/> <Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Label Text="Широта" Grid.Column="0" Grid.Row="0"/> <Label Text="00,000000" x:Name="LatitudeLabel" Grid.Column="1" Grid.Row="0"/> <Label Text="Долгота" Grid.Column="0" Grid.Row="1"/> <Label Text="00,000000" x:Name="LongitudeLabel" Grid.Column="1" Grid.Row="1"/> <Label Text="Расстояние, км" Grid.Column="0" Grid.Row="2"/> <Label Text="0" x:Name="DistanceLabel" Grid.Column="1" Grid.Row="2"/> </Grid> <Button x:Name="CounterBtn" Text="Click me" Clicked="OnCounterClicked" HorizontalOptions="Fill" /> <Button Text="Отменить запрос" Clicked="CancelRequestClicked" HorizontalOptions="Fill" /> <Button Text="Начать прослушивание" Clicked="OnListeningClicked"/> <CollectionView ItemsSource="{Binding Locations, Source={RelativeSource AncestorType={x:Type m:MainPage}}, Mode=TwoWay}"> <CollectionView.ItemTemplate> <DataTemplate x:DataType="locations:Location"> <HorizontalStackLayout> <Label Text="{Binding Latitude, StringFormat='Широта {0}; '}"/> <Label Text="{Binding Longitude, StringFormat='Долгота {0} '}"/> </HorizontalStackLayout> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> <Label Text="{Binding LastError}"/> </VerticalStackLayout> </ScrollView> </ContentPage>
Теперь запустим приложение, включим прослушивание событий и по перемещаем устройство. В результате, вы должны увидеть на экране примерно следующую информацию:
Итого
Класс Location
содержит информацию о местоположении устройства, включая данные о высоте точки расположения, азимуте и, если доступно, то скорости, с которой перемещалось устройство в момент получения данных о местоположении. Также, Location
содержит методы для расчёта расстояния между двумя точками.