ユーザーの位置情報の取得Get the user's location

[Windows 10 の UWP アプリ向けに更新。[ Updated for UWP apps on Windows 10. Windows 8.x の記事については、アーカイブをご覧ください ]For Windows 8.x articles, see the archive ]

ユーザーの位置情報を検索し、位置の変更に対応します。Find the user's location and respond to changes in location. ユーザーの位置情報へのアクセスは、設定アプリのプライバシー設定で管理されています。Access to the user's location is managed by privacy settings in the Settings app. このトピックでは、アプリにユーザーの位置情報へのアクセス許可が与えられているかどうかを確認する方法についても説明します。This topic also shows how to check if your app has permission to access the user's location.

ヒント: アプリでユーザーの位置情報にアクセスする方法について詳しくは、GitHub の Windows-universal-samples リポジトリから次のサンプルをダウンロードしてください。Tip To learn more about accessing the user's location in your app, download the following sample from the Windows-universal-samples repo on GitHub.

位置情報機能を有効にするEnable the location capability

  1. ソリューション エクスプローラーで、package.appxmanifest をダブルクリックし、[機能] タブを選びます。In Solution Explorer, double-click package.appxmanifest and select the Capabilities tab.
  2. [機能] ボックスの一覧で、[位置情報] チェックボックスをオンにします。In the Capabilities list, check the box for Location. これにより、location デバイス機能がパッケージ マニフェスト ファイルに追加されます。This adds the location device capability to the package manifest file.
  <Capabilities>
    <!-- DeviceCapability elements must follow Capability elements (if present) -->
    <DeviceCapability Name="location"/>
  </Capabilities>

現在の位置情報を取得するGet the current location

このセクションでは、Windows.Devices.Geolocation 名前空間の API を使ってユーザーの地理的な位置を検出する方法について説明します。This section describes how to detect the user's geographic location using APIs in the Windows.Devices.Geolocation namespace.

手順 1. ユーザーの位置情報へのアクセス許可を求めるStep 1: Request access to the user's location

アプリに Consentless Location 機能 (「注意」を参照) がない場合は、ユーザーの位置情報へアクセスする前に、RequestAccessAsync メソッドを使用してユーザーの位置情報へのアクセス許可を求める必要があります。Unless your app has Consentless Location capability (see note), you must request access to the user's location by using the RequestAccessAsync method before attempting to access the location. RequestAccessAsync メソッドは UI スレッドから呼び出す必要があり、アプリがフォアグラウンドで実行されている必要があります。You must call the RequestAccessAsync method from the UI thread and your app must be in the foreground. アプリがユーザーの位置情報にアクセスするには、先にユーザーがその情報へのアクセス許可をアプリに与える必要があります。*Your app will not be able to access the user's location information until after the user grants permission to your app.*

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

RequestAccessAsync メソッドを使って、ユーザーに位置情報へのアクセス許可を求めます。The RequestAccessAsync method prompts the user for permission to access their location. ユーザーに対するこの要求はアプリごとに 1 回だけ行われます。The user is only prompted once (per app). アクセス許可の付与または拒否を行った後、このメソッドはユーザーにアクセス許可を求めなくなります。After the first time they grant or deny permission, this method no longer prompts the user for permission. ユーザーが位置情報へのアクセス許可を求められた後にそのアクセス許可を変更できるように、位置情報の設定へのリンクを用意することをお勧めします。これについては、このトピックの後半で紹介します。To help the user change location permissions after they've been prompted, we recommend that you provide a link to the location settings as demonstrated later in this topic.

注意: Consentless Location 機能により、アプリはユーザーによる明示的な許可を必要とせずに、意図的にあいまいにされた (不正確な) 位置情報を取得できます (ただしシステム全体の位置情報スイッチは on のままである必要があります)。Note: The Consentless Location feature allows your app to obtain an intentionally obfuscated (imprecise) location without getting the user's explicit permission (the system-wide location switch must still be on, however). アプリで Consentless Location を使用する方法について詳しくは、Geolocator クラスの AllowFallbackToConsentlessPositions メソッドをご覧ください。To learn how to utilize Consentless Location in your app, see the AllowFallbackToConsentlessPositions method in the Geolocator class.

手順 2. ユーザーの位置情報を取得し、位置情報のアクセス許可の変更を登録するStep 2: Get the user's location and register for changes in location permissions

GetGeopositionAsync メソッドは、現在の位置情報に対して 1 回限りの読み取りを実行します。The GetGeopositionAsync method performs a one-time reading of the current location. ここでは、switch ステートメントを (前の例で示した) accessStatus と共に使って、ユーザーの位置情報へのアクセス許可が与えられている場合にのみ動作するように指定します。Here, a switch statement is used with accessStatus (from the previous example) to act only when access to the user's location is allowed. ユーザーの位置情報へのアクセス許可が与えられた場合は、コードによって Geolocator オブジェクトが作成され、位置情報へのアクセス許可の変更が登録され、ユーザーの位置情報が要求されます。If access to the user's location is allowed, the code creates a Geolocator object, registers for changes in location permissions, and requests the user's location.

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. 位置情報へのアクセス許可の変更を処理するStep 3: Handle changes in location permissions

Geolocator オブジェクトは StatusChanged イベントをトリガーして、ユーザーの位置情報設定が変化したことを示します。The Geolocator object triggers the StatusChanged event to indicate that the user's location settings changed. このイベントは、引数の Status プロパティ (PositionStatus 型) を使って、対応する状態を渡します。That event passes the corresponding status via the argument's Status property (of type PositionStatus). このメソッドは UI スレッドから呼び出されず、Dispatcher オブジェクトが UI の変更を呼び出します。Note that this method is not called from the UI thread and the Dispatcher object invokes the UI changes.

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;
        }
    });
}

位置情報の更新への対応Respond to location updates

このセクションでは、PositionChanged イベントを使って、特定の期間におけるユーザーの位置の更新情報を受け取る方法について説明します。This section describes how to use the PositionChanged event to receive updates of the user's location over a period of time. ユーザーはいつでも位置情報へのアクセス許可を取り消すことができるため、前のセクションで説明したように、RequestAccessAsync を呼び出して StatusChanged イベントを使うことが重要になります。Because the user could revoke access to location at any time, it's important call RequestAccessAsync and use the StatusChanged event as shown in the previous section.

このセクションでは、既に位置情報機能を有効にし、フォアグラウンド アプリの UI スレッドから RequestAccessAsync を呼び出していることを前提としています。This section assumes that you've already enabled the location capability and called RequestAccessAsync from the UI thread of your foreground app.

手順 1. レポート間隔を定義し、位置情報の更新を登録するStep 1: Define the report interval and register for location updates

この例では、switch ステートメントを (前の例で示した) accessStatus と共に使って、ユーザーの位置情報へのアクセス許可が与えられている場合にのみ動作するように指定します。In this example, a switch statement is used with accessStatus (from the previous example) to act only when access to the user's location is allowed. ユーザーの位置情報へのアクセス許可が与えられた場合は、コードによって Geolocator オブジェクトが作成され、追跡の種類の指定と位置情報の更新の登録が行われます。If access to the user's location is allowed, the code creates a Geolocator object, specifies the tracking type, and registers for location updates.

Geolocator オブジェクトは、位置の変化 (距離に基づく追跡) または時間の変化 (期間に基づく追跡) に基づいて PositionChanged イベントをトリガーできます。The Geolocator object can trigger the PositionChanged event based on a change in position (distance-based tracking) or a change in time (periodic-based tracking).

  • 距離に基づく追跡の場合は、MovementThreshold プロパティを設定します。For distance-based tracking, set the MovementThreshold property.
  • 期間に基づく追跡の場合は、ReportInterval プロパティを設定します。For periodic-based tracking, set the ReportInterval property.

どちらのプロパティも設定されていない場合は、位置が 1 秒ごとが返されます (ReportInterval = 1000 と同じです)。If neither property is set, a position is returned every 1 second (equivalent to ReportInterval = 1000). ここでは、2 秒 (ReportInterval = 2000) のレポート間隔を使います。Here, a 2 second (ReportInterval = 2000) report interval is used.

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. 位置情報の更新を処理するStep 2: Handle location updates

Geolocator オブジェクトは PositionChanged イベントをトリガーし、構成方法に応じて、ユーザーの位置が変化したことまたは時間が経過したことを示します。The Geolocator object triggers the PositionChanged event to indicate that the user's location changed or time has passed, depending on how you've configured it. このイベントは、引数の Position プロパティ (Geoposition) を使って、対応する位置を渡します。That event passes the corresponding location via the argument's Position property (of type Geoposition). この例では、メソッドは UI スレッドから呼び出されず、Dispatcher オブジェクトが UI の変更を呼び出します。In this example, the method is not called from the UI thread and the Dispatcher object invokes the UI changes.

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);
    });
}

位置情報のプライバシー設定を変更するChange the location privacy settings

位置情報のプライバシー設定でアプリにユーザーの位置情報へのアクセス許可を与えていない場合は、設定アプリの [位置情報のプライバシー設定] へのリンクを用意することをお勧めします。If the location privacy settings don't allow your app to access the user's location, we recommend that you provide a convenient link to the location privacy settings in the Settings app. この例では、ハイパーリンク コントロールを使って、ms-settings:privacy-location という URI に移動します。In this example, a Hyperlink control is used navigate to the 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 メソッドを呼び出し、コードで設定アプリを起動することもできます。Alternatively, your app can call the LaunchUriAsync method to launch the Settings app from code. 詳しくは、「Windows 設定アプリの起動」をご覧ください。For more info, see Launch the Windows Settings app.

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

アプリのトラブルシューティングを行うTroubleshoot your app

アプリがユーザーの位置情報にアクセスする前に、デバイスで [位置情報] を有効にする必要があります。Before your app can access the user's location, Location must be enabled on the device. 設定アプリで、次の位置情報に関するプライバシー設定がオンになっていることを確認します。In the Settings app, check that the following location privacy settings are turned on:

  • [このデバイスの位置情報]オン になっている (Windows 10 Mobile には適用されません)Location for this device... is turned on (not applicable in Windows 10 Mobile)
  • 位置情報サービス設定の [位置情報]オン になっているThe location services setting, Location, is turned on
  • [位置情報を使うことができるアプリを選ぶ] で、アプリが オン になっているUnder Choose apps that can use your location, your app is set to on