Xamarin.Essentials: географическое расположение
Класс Geolocation предоставляет API для получения текущих геолокационных координат устройства.
Чтобы начать использовать этот API, ознакомьтесь с руководством по началу работы с Xamarin.Essentials, чтобы правильно настроить и установить библиотеку в проектах.
Чтобы проверить функциональность класса Geolocation, нужно создать описанную ниже конфигурацию для конкретной платформы:
Требуются разрешения Coarse и Fine Location, которые следует настроить в проекте Android. Кроме того, если приложение предназначено для платформы Android 5.0 (уровень API 21) или более поздней версии, в файле манифеста необходимо объявить, что приложение использует аппаратные возможности. Для этого можно применить любой из следующих методов:
Откройте файл AssemblyInfo.cs в папке Свойства и добавьте в него:
[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)]
Или обновите манифест Android:
Откройте файл AndroidManifest.xml в папке Properties и добавьте приведенный ниже код в узел 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" />
Или щелкните правой кнопкой мыши проект Android и откройте свойства проекта. В разделе Манифест Android найдите область Требуемые разрешения: и установите флажок для разрешений ACCESS_COARSE_LOCATION и ACCESS_FINE_LOCATION. Это действие автоматически обновляет файл AndroidManifest.xml.
Если приложение предназначено для Android 10 Q (API уровня 29 или более поздней версии) и запрашивает LocationAlways, необходимо также добавить следующее разрешение в AssemblyInfo.cs:
[assembly: UsesPermission(Manifest.Permission.AccessBackgroundLocation)]
Или непосредственно в AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
Рекомендуется читать документацию Android по фоновому расположению , так как необходимо учитывать множество ограничений.
Этот API использует разрешения среды выполнения для Android. Убедитесь, что набор Xamarin.Essentials полностью инициализирован и в вашем приложении настроена обработка разрешений.
В MainLauncher
проекта Android или в любом запущенном действии Activity
необходимо инициализировать Xamarin.Essentials в методе OnCreate
:
protected override void OnCreate(Bundle savedInstanceState)
{
//...
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState); // add this line to your code, it may also be called: bundle
//...
}
Для обработки на устройстве Android разрешений среды выполнения Xamarin.Essentials нужно получить любой OnRequestPermissionsResult
. Добавьте следующий код во все классы Activity
:
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
Добавьте ссылку на Xamarin.Essentials в своем классе:
using Xamarin.Essentials;
В API геолокации пользователю также будет предложено предоставить разрешения при необходимости.
Вы можете получить последнее известное расположение устройства, вызвав метод GetLastKnownLocationAsync
. Зачастую эта операция быстрее, чем выполнение всего запроса, но не так точна и может вернуть null
, если расположение для кэширования отсутствует.
try
{
var location = await Geolocation.GetLastKnownLocationAsync();
if (location != null)
{
Console.WriteLine($"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
}
Чтобы запросить текущие координаты расположения устройства, можно использовать GetLocationAsync
. Лучше всего передать полный GeolocationRequest
и CancellationToken
, так как получение расположения устройства может занять некоторое время.
CancellationTokenSource cts;
async Task GetCurrentLocation()
{
try
{
var request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));
cts = new CancellationTokenSource();
var location = await Geolocation.GetLocationAsync(request, cts.Token);
if (location != null)
{
Console.WriteLine($"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
}
}
protected override void OnDisappearing()
{
if (cts != null && !cts.IsCancellationRequested)
cts.Cancel();
base.OnDisappearing();
}
Не все значения могут быть доступны, так как каждое устройство запрашивает географическое расположение через разных поставщиков. Например, свойство Altitude
может быть равно null
, может иметь значение 0 или положительное значение, которое представляет собой высоту в метрах над уровнем моря. В число других значений, которые могут отсутствовать, входят Speed
и Course
.
В следующей таблице приведены сведения о точности для каждой платформы:
Платформа | Расстояние (в метрах) |
---|---|
Android | 500 |
iOS | 3000 |
UWP | 1000–5000 |
Платформа | Расстояние (в метрах) |
---|---|
Android | 500 |
iOS | 1000 |
UWP | 300–3000 |
Платформа | Расстояние (в метрах) |
---|---|
Android | 100–500 |
iOS | 100 |
UWP | 30–500 |
Платформа | Расстояние (в метрах) |
---|---|
Android | 0–100 |
iOS | 10 |
UWP | <= 10 |
Платформа | Расстояние (в метрах) |
---|---|
Android | 0–100 |
iOS | ~0 |
UWP | <= 10 |
Некоторые устройства могут возвращать расположение макетов от поставщика или приложения, которое предоставляет расположения макетов. Его можно определить с помощью IsFromMockProvider
на любом Location
.
var request = new GeolocationRequest(GeolocationAccuracy.Medium);
var location = await Geolocation.GetLocationAsync(request);
if (location != null)
{
if(location.IsFromMockProvider)
{
// location is from a mock provider
}
}
Классы Location
и LocationExtensions
определяют методы CalculateDistance
, которые дают возможность вычисления расстояния между двумя географическими расположениями. При расчете не учитываются дороги или другие пути. Это самое короткое расстояние между двумя точками на поверхности Земли, также известное как расстояние по дуге большого круга или, говоря простым языком, расстояние напрямик.
Приведем пример:
Location boston = new Location(42.358056, -71.063611);
Location sanFrancisco = new Location(37.783333, -122.416667);
double miles = Location.CalculateDistance(boston, sanFrancisco, DistanceUnits.Miles);
В конструкторе Location
аргументы широты и долготы указаны в следующем порядке. Положительные значения широты находятся к северу от экватора, а положительные значения долготы — к востоку от нулевого меридиана. Используйте последний аргумент CalculateDistance
, чтобы указать единицы измерения: мили или километры. Класс UnitConverters
также определяет методы KilometersToMiles
и MilesToKilometers
для преобразования между двумя единицами измерения.
Высота на каждой платформе вычисляется по-разному.
В Android высота, если она доступна, возвращается в виде высоты над нормальным эллипсоидом всемирной геодезической системы координат в метрах. Если в этом расположении нет высоты, возвращается 0,0.
- Geolocation source code (Исходный код для геолокации)
- Документация по API геолокации