사용자 위치 가져오기

참고 항목

MapControl 및 지도 서비스를 사용하려면 MapServiceToken이라는 지도 인증 키가 필요합니다. 맵 인증 키 가져오기 및 설정에 대한 자세한 내용은 맵 인증 키 요청을 참조하세요.

사용자의 위치를 찾아 위치 변화에 응답하세요. 사용자의 위치에 대한 액세스 권한은 설정 앱의 개인 정보 설정을 통해 관리합니다. 이 토픽에서는 사용자의 위치에 액세스할 수 있는 권한이 앱에 있는지 확인하는 방법도 보여줍니다.

앱에서 사용자의 위치에 액세스하는 방법에 대해 자세히 알아보려면 GitHub의 Windows-universal-samples 리포지토리에서 다음 샘플을 다운로드하세요.

위치 기능 활성화하기

  1. 솔루션 탐색기에서 package.appxmanifest를 두 번 클릭하고 기능 탭을 선택하세요.
  2. 기능 목록에서 위치 상자를 선택합니다. 이렇게 하면 패키지 매니페스트 파일에 location 디바이스 기능이 추가됩니다.
  <Capabilities>
    <!-- DeviceCapability elements must follow Capability elements (if present) -->
    <DeviceCapability Name="location"/>
  </Capabilities>

현재 위치 파악하기

이 섹션에서는 Windows.Devices.Geolocation 네임스페이스의 API를 사용해서 사용자의 지리적 위치를 검색하는 방법을 설명합니다.

1단계: 사용자의 위치에 대한 액세스 권한 요청하기

앱에 Coarse Location 기능(참고 참조)이 없는 경우 위치에 액세스하기 전에 RequestAccessAsync 메서드를 사용하여 위치에 대한 액세스를 요청해야 합니다. 사용자는 UI 스레드로부터 RequestAccessAsync 메서드를 호출해야 하며, 이때는 앱이 포그라운드에 있어야 합니다. 사용자가 앱에 권한을 부여할 때까지는 앱에서 사용자의 위치 정보에 액세스할 수 없습니다.*

using Windows.Devices.Geolocation;
...
var accessStatus = await Geolocator.RequestAccessAsync();

RequestAccessAsync 메서드를 사용하면 해당 위치에 액세스할 수 있는 권한이 있는지 묻는 메시지가 사용자에게 표시됩니다. 사용자는 앱당 한 번만 메시지를 받습니다. 최초로 권한을 부여하거나 거부하고 나면 이 메서드가 더 이상 사용자에게 권한 유무를 묻지 않습니다. 사용자가 메시지를 받은 후 위치 권한을 변경할 수 있도록, 이 토픽의 뒷부분에 설명된 대로 위치 설정의 링크를 제공하는 것이 좋습니다.

참고: Coarse Location 기능을 통해 앱은 사용자의 명시적 권한 없이도 의도적으로 난독 처리된(부정확한) 위치를 가져올 수 있습니다(시스템 수준의 위치 스위치는 계속 켜짐 상태여야 함). 앱에서 Coarse Location을 활용하는 방법은 Geolocator 클래스의 AllowFallbackToConsentlessPositions 메서드를 참조하세요.

2단계: 사용자의 위치 파악하기 및 위치 권한 변경 등록하기

GetGeopositionAsync 메서드는 현재 위치에 대한 일회성 판독을 실행합니다. switch 구문은 사용자의 위치에 대한 액세스가 허용된 경우에만 작동하도록 (이전 예제에서) accessStatus와 함께 사용됩니다. 이 코드는 사용자의 위치에 대한 액세스가 허용되는 경우 Geolocator 개체를 생성하고, 위치 권한의 변경 사항을 등록하고, 사용자의 위치를 요청합니다.

switch (accessStatus)
{
    case GeolocationAccessStatus.Allowed:
        _rootPage.NotifyUser("Waiting for update...", NotifyType.StatusMessage);

        // If DesiredAccuracy or DesiredAccuracyInMeters are not set (or value is 0), DesiredAccuracy.Default is used.
        Geolocator geolocator = new Geolocator { DesiredAccuracyInMeters = _desireAccuracyInMetersValue };

        // Subscribe to the StatusChanged event to get updates of location status changes.
        _geolocator.StatusChanged += OnStatusChanged;

        // Carry out the operation.
        Geoposition pos = await geolocator.GetGeopositionAsync();

        UpdateLocationData(pos);
        _rootPage.NotifyUser("Location updated.", NotifyType.StatusMessage);
        break;

    case GeolocationAccessStatus.Denied:
        _rootPage.NotifyUser("Access to location is denied.", NotifyType.ErrorMessage);
        LocationDisabledMessage.Visibility = Visibility.Visible;
        UpdateLocationData(null);
        break;

    case GeolocationAccessStatus.Unspecified:
        _rootPage.NotifyUser("Unspecified error.", NotifyType.ErrorMessage);
        UpdateLocationData(null);
        break;
}

3단계: 위치 권한의 변경 사항 처리하기

Geolocator 개체는 사용자의 위치 설정이 변경되었음을 나타내기 위해 StatusChanged 이벤트를 트리거합니다. 이 이벤트는 인수의 Status(상태) 속성(PositionStatus 형식에 속함)을 통해 해당 상태를 전달합니다. 이 메서드는 UI 스레드로부터 호출되지 않으며, 발송자 개체가 UI 변경 사항을 호출합니다.

using Windows.UI.Core;
...
async private void OnStatusChanged(Geolocator sender, StatusChangedEventArgs e)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        // Show the location setting message only if status is disabled.
        LocationDisabledMessage.Visibility = Visibility.Collapsed;

        switch (e.Status)
        {
            case PositionStatus.Ready:
                // Location platform is providing valid data.
                ScenarioOutput_Status.Text = "Ready";
                _rootPage.NotifyUser("Location platform is ready.", NotifyType.StatusMessage);
                break;

            case PositionStatus.Initializing:
                // Location platform is attempting to acquire a fix.
                ScenarioOutput_Status.Text = "Initializing";
                _rootPage.NotifyUser("Location platform is attempting to obtain a position.", NotifyType.StatusMessage);
                break;

            case PositionStatus.NoData:
                // Location platform could not obtain location data.
                ScenarioOutput_Status.Text = "No data";
                _rootPage.NotifyUser("Not able to determine the location.", NotifyType.ErrorMessage);
                break;

            case PositionStatus.Disabled:
                // The permission to access location data is denied by the user or other policies.
                ScenarioOutput_Status.Text = "Disabled";
                _rootPage.NotifyUser("Access to location is denied.", NotifyType.ErrorMessage);

                // Show message to the user to go to location settings.
                LocationDisabledMessage.Visibility = Visibility.Visible;

                // Clear any cached location data.
                UpdateLocationData(null);
                break;

            case PositionStatus.NotInitialized:
                // The location platform is not initialized. This indicates that the application
                // has not made a request for location data.
                ScenarioOutput_Status.Text = "Not initialized";
                _rootPage.NotifyUser("No request for location is made yet.", NotifyType.StatusMessage);
                break;

            case PositionStatus.NotAvailable:
                // The location platform is not available on this version of the OS.
                ScenarioOutput_Status.Text = "Not available";
                _rootPage.NotifyUser("Location is not available on this version of the OS.", NotifyType.ErrorMessage);
                break;

            default:
                ScenarioOutput_Status.Text = "Unknown";
                _rootPage.NotifyUser(string.Empty, NotifyType.StatusMessage);
                break;
        }
    });
}

위치 업데이트에 응답하기

이 섹션에서는 PositionChanged 이벤트를 사용하여 일정 기간 동안 사용자의 위치에 대해 업데이트를 받는 방법을 설명합니다. 사용자는 위치에 대한 액세스 권한을 언제든지 없앨 수 있습니다. 따라서 이전 섹션에 나온 대로 RequestAccessAsync를 호출하고 StatusChanged 이벤트를 사용하는 것이 중요합니다.

이 섹션에서는 사용자가 이미 위치 기능을 사용하도록 설정했으며 포그라운드 앱의 UI 스레드에서 RequestAccessAsync를 호출했다고 가정합니다.

1단계: 보고서 간격 정의하기 및 위치 업데이트 등록하기

이 예제에서 switch 구문은 사용자의 위치에 대한 액세스가 허용된 경우에만 작동하도록 accessStatus(이전 예제에 수록됨)와 함께 사용됩니다. 이 코드는 사용자의 위치에 대한 액세스가 허용되는 경우 Geolocator 개체를 생성하고, 추적 유형을 지정하고, 위치 업데이트를 등록합니다.

Geolocator 개체는 위치 변경(거리 기반 추적) 또는 시간 변경(주기 기반 추적)에 따라 PositionChanged 이벤트를 트리거할 수 있습니다.

두 속성 중 어떤 것도 설정하지 않으면 위치가 1초마다(ReportInterval = 1000와(과) 상등) 반환됩니다. 여기서는 2초(ReportInterval = 2000) 보고서 간격을 사용합니다.

using Windows.Devices.Geolocation;
...
var accessStatus = await Geolocator.RequestAccessAsync();

switch (accessStatus)
{
    case GeolocationAccessStatus.Allowed:
        // Create Geolocator and define perodic-based tracking (2 second interval).
        _geolocator = new Geolocator { ReportInterval = 2000 };

        // Subscribe to the PositionChanged event to get location updates.
        _geolocator.PositionChanged += OnPositionChanged;

        // Subscribe to StatusChanged event to get updates of location status changes.
        _geolocator.StatusChanged += OnStatusChanged;

        _rootPage.NotifyUser("Waiting for update...", NotifyType.StatusMessage);
        LocationDisabledMessage.Visibility = Visibility.Collapsed;
        StartTrackingButton.IsEnabled = false;
        StopTrackingButton.IsEnabled = true;
        break;

    case GeolocationAccessStatus.Denied:
        _rootPage.NotifyUser("Access to location is denied.", NotifyType.ErrorMessage);
        LocationDisabledMessage.Visibility = Visibility.Visible;
        break;

    case GeolocationAccessStatus.Unspecified:
        _rootPage.NotifyUser("Unspecificed error!", NotifyType.ErrorMessage);
        LocationDisabledMessage.Visibility = Visibility.Collapsed;
        break;
}

2단계: 위치 업데이트 처리하기

Geolocator 개체는 사용자가 구성한 방법에 따라 사용자의 위치가 변경되었거나 시간이 지났음을 나타내기 위해 PositionChanged 이벤트를 트리거합니다. 이 이벤트는 인수의 Position(위치) 속성(Geoposition 형식에 속함)을 통해 해당 위치를 전달합니다. 이 예제에서 해당 메서드는 UI 스레드로부터 호출되지 않으며, Dispatcher(발송자) 개체가 UI 변경 사항을 호출합니다.

using Windows.UI.Core;
...
async private void OnPositionChanged(Geolocator sender, PositionChangedEventArgs e)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        _rootPage.NotifyUser("Location updated.", NotifyType.StatusMessage);
        UpdateLocationData(e.Position);
    });
}

위치 개인 정보 설정 변경하기

위치 개인 정보 보호 설정에서 앱으로 사용자의 위치에 액세스하도록 허용하지 않는 경우, 설정 앱의 위치 개인 정보 보호 설정으로 연결되는 간편 링크를 제공하는 것이 좋습니다. 이 예제에서는 하이퍼링크 컨트롤을 사용하여 ms-settings:privacy-location URI로 이동합니다.

<!--Set Visibility to Visible when access to location is denied -->  
<TextBlock x:Name="LocationDisabledMessage" FontStyle="Italic"
                 Visibility="Collapsed" Margin="0,15,0,0" TextWrapping="Wrap" >
          <Run Text="This app is not able to access Location. Go to " />
              <Hyperlink NavigateUri="ms-settings:privacy-location">
                  <Run Text="Settings" />
              </Hyperlink>
          <Run Text=" to check the location privacy settings."/>
</TextBlock>

아니면 앱으로 LaunchUriAsync 메서드를 호출하여 코드에서 설정 앱을 시작해도 됩니다. 자세한 내용은 Windows 설정 앱 시작하기를 참조하세요.

using Windows.System;
...
bool result = await Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-location"));

앱 문제 해결

앱이 사용자의 위치에 액세스하려면 먼저 디바이스에서 Location(위치)을 사용하도록 설정해야 합니다. 설정 앱에서 다음 위치 개인 정보 보호 설정이 켜져 있는지 확인하세요.

  • 이 디바이스의 위치켜져 있습니다(Windows 10 Mobile에는 적용되지 않음).
  • 위치 서비스 설정인 위치켜져 있습니다.
  • 사용자의 위치를 사용할 수 있는 앱 선택 하위에서 앱이 켜짐으로 설정됩니다.