次の方法で共有


位置情報

Browse sample. サンプルを参照する

この記事では、.NET マルチプラットフォーム アプリ UI (.NET MAUI) IGeolocation インターフェイスを使用する方法について説明します。 このインターフェイスは、デバイスの現在の位置情報座標を取得する API を提供します。

IGeolocation インターフェイスの既定の実装は、Geolocation.Default プロパティを通じて利用できます。 IGeolocation インターフェイスと Geolocation クラスはどちらも Microsoft.Maui.Devices.Sensors 名前空間に含まれています。

作業の開始

Geolocation の機能にアクセスするには、次のプラットフォーム固有の設定が必要です。

粗いまたは細かい位置情報のアクセス許可、またはその両方を指定し、Android プロジェクトで構成する必要があります。

さらに、アプリの対象が Android 5.0 (API レベル 21) 以降である場合は、アプリがマニフェスト ファイルのハードウェア機能を使用することを宣言する必要があります。 これは次の方法で追加できます。

  • アセンブリベースのアクセス許可を追加します。

    Platforms/Android/MainApplication.cs ファイルを開き、using ディレクティブの後に次のアセンブリ属性を追加します。

    [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 10 - Q (API レベル 29 以上) を対象としており、LocationAlways を要求している場合は、次のアクセス許可も追加する必要があります。

    [assembly: UsesPermission(Manifest.Permission.AccessBackgroundLocation)]
    

    または

  • Android マニフェストを更新します。

    Platforms/Android/AndroidManifest.xml ファイルを開き、manifest ノードに次を追加します。

    <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 10 - Q (API レベル 29 以上) を対象としており、LocationAlways を要求している場合は、次のアクセス許可も追加する必要があります。

    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    

    または

  • マニフェスト エディターで Android マニフェストを更新します。

    Visual Studio で、Platforms/Android/AndroidManifest.xml ファイルをダブルクリックして、Android マニフェスト エディターを開きます。 次に、[必要なアクセス許可] で、上記に一覧表示されたアクセス許可をチェックします。 これにより、AndroidManifest.xml ファイルが自動的に更新されます。

ヒント

考慮すべき制限が多数あるため、バックグラウンドでの位置情報の更新に関する Android ドキュメントを読むことをお勧めします。

最新の位置情報を取得する

デバイスは、デバイスの最新の場所をキャッシュしている可能性があります。 可能な場合は、GetLastKnownLocationAsync() メソッドを使用して、キャッシュされた場所にアクセスします。 多くの場合、この方が完全なクエリを実行するよりも迅速ですが、精度が低下することがあります。 キャッシュされた場所が存在しない場合、このメソッドは null を返します。

Note

Geolocation API は、必要に応じてユーザーにアクセス許可を求めることがあります。

次のコード例は、キャッシュされた場所を確認する方法を示しています。

public async Task<string> GetCachedLocation()
{
    try
    {
        Location location = await Geolocation.Default.GetLastKnownLocationAsync();

        if (location != null)
            return $"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
    }

    return "None";
}

デバイスによっては、すべての場所の値が使用できるわけではありません。 たとえば、Altitude プロパティは null、0、または海抜高度をメートルで表す正の値を持っている可能性があります。 存在しない可能性のあるその他の値として、Speed プロパティと Course プロパティがあります。

現在の位置情報を取得する

デバイスの最後に確認された位置を確認する方が早い場合もありますが、不正確になる可能性があります。 GetLocationAsync メソッドを使用して、デバイスに現在の位置を照会します。 クエリの精度とタイムアウトを構成できます。 デバイスの位置を取得するのに時間がかかる可能性があるため、GeolocationRequestCancellationToken パラメーターを使用するメソッドのオーバーロードをお勧めします。

Note

Geolocation API は、必要に応じてユーザーにアクセス許可を求めることがあります。

次のコード例は、キャンセルをサポートしながらデバイスの位置情報を要求する方法を示しています。

private CancellationTokenSource _cancelTokenSource;
private bool _isCheckingLocation;

public async Task GetCurrentLocation()
{
    try
    {
        _isCheckingLocation = true;

        GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));

        _cancelTokenSource = new CancellationTokenSource();

        Location location = await Geolocation.Default.GetLocationAsync(request, _cancelTokenSource.Token);

        if (location != null)
            Console.WriteLine($"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}");
    }
    // Catch one of the following exceptions:
    //   FeatureNotSupportedException
    //   FeatureNotEnabledException
    //   PermissionException
    catch (Exception ex)
    {
        // Unable to get location
    }
    finally
    {
        _isCheckingLocation = false;
    }
}

public void CancelRequest()
{
    if (_isCheckingLocation && _cancelTokenSource != null && _cancelTokenSource.IsCancellationRequested == false)
        _cancelTokenSource.Cancel();
}

デバイスによっては、すべての位置情報を利用できるわけではありません。 たとえば、Altitude プロパティは null、0、または海抜高度をメートルで表す正の値を持っている可能性があります。 存在しない可能性のあるその他の値として、Speed および Course があります。

警告

一部のシナリオでは、GetLocationAsyncnull を返すことがあります。 これは、基になるプラットフォームが現在の場所を取得できないことを示します。

場所の変更をリッスンする

現在の場所についてデバイスに対してクエリを実行するだけでなく、アプリがフォアグラウンドにある間に場所の変更をリッスンできます。

アプリが現在、位置の変更をリッスンしているかどうかを確認するには、クエリを実行できる IsListeningForeground プロパティがあります。 位置変更のリッスンを開始する準備ができたら、StartListeningForegroundAsync メソッドを呼び出す必要があります。 このメソッドは、位置情報の更新のリッスンを開始し、アプリがフォアグラウンドにある場合に位置情報が変更されると LocationChanged イベントを発生させます。 このイベントに付随する GeolocationLocationChangedEventArgs オブジェクトには、検出された新しい場所を表す Location 型の Location プロパティがあります。

Note

Geolocation API は、必要に応じてユーザーにアクセス許可を求めることがあります。

次のコード例は、場所の変更をリッスンする方法と、変更された場所を処理する方法を示しています。

async void OnStartListening()
{
    try
    {
        Geolocation.LocationChanged += Geolocation_LocationChanged;
        var request = new GeolocationListeningRequest((GeolocationAccuracy)Accuracy);
        var success = await Geolocation.StartListeningForegroundAsync(request);

        string status = success
            ? "Started listening for foreground location updates"
            : "Couldn't start listening";
    }
    catch (Exception ex)
    {
        // Unable to start listening for location changes
    }
}

void Geolocation_LocationChanged(object sender, GeolocationLocationChangedEventArgs e)
{
    // Process e.Location to get the new location
}

エラー処理は、ListeningFailed イベントのイベント ハンドラーを登録することで実装できます。 このイベントに付随する GeolocationListeningFailedEventArgs オブジェクトには、リッスンが失敗した理由を示す GeolocationError 型の Error プロパティがあります。 ListeningFailed イベントが発生すると、それ以上の位置変更のリッスンが停止し、それ以上 LocationChanged イベントは発生しなくなります。

位置変更のリッスンを停止するには、StopListeningForeground メソッドを呼び出します。

void OnStopListening()
{
    try
    {
        Geolocation.LocationChanged -= Geolocation_LocationChanged;
        Geolocation.StopListeningForeground();
        string status = "Stopped listening for foreground location updates";
    }
    catch (Exception ex)
    {
        // Unable to stop listening for location changes
    }
}

Note

StopListeningForeground メソッドは、アプリが位置情報の変更をリッスンしていない場合には効果がありません。

正確さ

次のセクションでは、プラットフォームごとの位置精度の距離について概説します。

重要

iOS には、精度に関するいくつかの制限があります。 詳細については、「プラットフォームによる違い」をご覧ください。

最低

プラットフォーム 距離 (メートル単位)
Android 500
iOS 3000
Windows 1000 ~ 5000

Low

プラットフォーム 距離 (メートル単位)
Android 500
iOS 1000
Windows 300 ~ 3000

中 (既定値)

プラットフォーム 距離 (メートル単位)
Android 100 ~ 500
iOS 100
Windows 30 ~ 500

High

プラットフォーム 距離 (メートル単位)
Android 0 ~ 100
iOS 10
Windows <= 10

最高

プラットフォーム 距離 (メートル単位)
Android 0 ~ 100
iOS ~0
Windows <= 10

擬似ロケーションの検出

一部のデバイスは、プロバイダーからの擬似ロケーションを返します。擬似ロケーションを提供するアプリケーションによって擬似ロケーションを返すこともあります。 任意の LocationIsFromMockProvider を使用するとこれを検出できます。

public async Task CheckMock()
{
    GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium);
    Location location = await Geolocation.Default.GetLocationAsync(request);

    if (location != null && location.IsFromMockProvider)
    {
        // location is from a mock provider
    }
}

2 つのロケーション間の距離

CalculateDistance メソッドは、2 つの地理的な場所間の距離を計算します。 この計算距離は道路またはその他の経路を考慮していなく、あくまでも地球の表面に沿った 2 点間の最短距離です。 この計算は、大圏距離計算として知られています。

次のコードは、アメリカ合衆国の都市、ボストンとサンフランシスコの間の距離を計算します。

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(Double, Double, Double) コンストラクターは、緯度と経度の引数をそれぞれ受け入れます。 正の緯度値は北半球を示し、正の緯度値は東半球を示します。 マイルまたはキロメートルを指定するには、CalculateDistance に対する最後の引数を使用します。 UnitConverters クラスでは、2 つの単位の間で変換を行う KilometersToMiles および MilesToKilometers メソッドも定義されています。

プラットフォームによる違い

このセクションでは、位置情報 API とのプラットフォーム固有の違いについて説明します。

高度は、プラットフォームごとに異なる方法で計算されます。

Android で、高度が表示されている場合は、WGS 84 準拠楕円体のメートル単位で返されます。 この位置に高度がない場合は、0.0 を返します。

Location.ReducedAccuracy プロパティは iOS でのみ使用され、他のすべてのプラットフォームでは false を返します。