Geolocation 클래스는 디바이스의 현재 지리적 위치 좌표를 검색하기 위한 API를 제공합니다.
시작하기
이 API를 사용하기 전에 라이브러리가 제대로 설치되고 프로젝트에 설정되어 있는지 확인하기 위해 Xamarin.Essentials에 대한 시작 가이드를 읽어보세요.
지리적 위치 기능에 액세스하려면 다음 플랫폼 관련 설정이 필요합니다.
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 파일을 열고 매니페스트 노드 내부에 다음을 추가합니다.
<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가 완전히 초기화되고 앱에서 사용 권한 처리가 설정되어 있는지 확인하세요.
Android 프로젝트의 MainLauncher 또는 시작된 Activity의 OnCreate 메서드에서 Xamarin.Essentials를 초기화해야 합니다.
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 |
Mock 위치 검색
일부 디바이스는 공급자에서 또는 모의 위치를 제공하는 애플리케이션에 의해 모의 위치를 반환할 수 있습니다. Location에서 IsFromMockProvider를 사용하여 이를 탐지할 수 있습니다.
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 메서드를 정의합니다. 이 계산된 거리는 도로 또는 다른 경로를 고려하지 않으며, ‘대권 거리(great-circle distance)’라고도 하는 지표면에 따라 두 지점 간의 가장 짧은 거리 또는 구어로 “일직선” 거리일 뿐입니다.
예를 들어 다음과 같습니다.
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에서 사용 가능한 경우 고도는 WGS 84 참조 타원면 위에 미터 단위로 반환됩니다. 이 위치에 고도가 없는 경우에는 0.0이 반환됩니다.