Xamarin.Essentials: 지리적 위치
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이 반환됩니다.