Содержание
В предыдущей части мы использовали объекты класса 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 содержит методы для расчёта расстояния между двумя точками.