Xamarin.Essentials:Geolocation

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_LOCATIONACCESS_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 또는 시작된 ActivityOnCreate 메서드에서 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를 사용할 수 있습니다. 디바이스 위치를 가져오는 데 약간 시간이 걸릴 수 있으므로 전체 GeolocationRequestCancellationToken으로 전달하는 것이 가장 좋습니다.

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이거나, 값이 양수(해수면 위 미터 단위)일 수 있습니다. 존재하지 않을 수 있는 다른 값으로는 SpeedCourse가 있습니다.

지리적 위치 정확도

다음 표에서는 플랫폼별 정확도를 개략적으로 설명합니다.

가장 낮음

플랫폼 거리(미터)
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
    }
}

두 위치 간 거리

LocationLocationExtensions 클래스는 두 지리적 위치 간 거리를 계산할 수 있는 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 클래스는 두 단위 간에 변환하기 위한 KilometersToMilesMilesToKilometers 메서드를 정의합니다.

플랫폼의 차이점

고도는 플랫폼마다 다르게 계산됩니다.

Android에서 사용 가능한 경우 고도는 WGS 84 참조 타원면 위에 미터 단위로 반환됩니다. 이 위치에 고도가 없는 경우에는 0.0이 반환됩니다.

API

Channel 9YouTube에서 더 많은 Xamarin 비디오를 확인하세요.