現在地の検索

マッピングアプリケーションを使用する主な理由の 1 つは、自分がどこにいるかを確認することです。 LocationEngine HERE SDK が提供するは、 iOS プラットフォーム の位置を使用する包括的な位置特定ソリューションを実装し、 GPS やその他のグローバル衛星ナビゲーションシステム( GNSS )受信機などの複数の位置情報ソースと連携します。

iOSデバイスがGNSS精度を達成する能力は、そのハードウェアに依存します。 すべてのiOSデバイスがこのフィーチャーをサポートするハードウェアを備えているわけではありません。 サブメーターの精度は現在iOSではサポートされていないため、別のレシーバーが必要です。

簡単に確認できます

HERE SDK の位置情報フィーチャーを統合するには、少なくとも次の手順を実行する必要があります。

  1. 必要 な iOS 権限を.plist ファイルに追加し、ユーザーに権限を要求します。
  2. LocationEngineを作成し、少なくとも 1 つのLocationDelegateを設定します。
  3. LocationEngineを1回開始し、必要な精度レベルを設定します。
  4. Location の更新を受信し、アプリで処理します。

必要な権限を追加

アプリでのLocationEngine の使用を開始する前に、アプリ Info.plist のファイルに必要な権限を追加する必要があります。

<key>UIRequiredDeviceCapabilities</key>
<array>
   <string>location-services</string>
   <string>gps</string>
</array>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
   <string>This app needs to access your current location to display it on the map.</string>
<key>NSLocationWhenInUseUsageDescription</key>
   <string>This app needs to access your current location to display it on the map.</string>
<key>NSMotionUsageDescription</key>
   <string>Motion detection is needed to determine more accurate locations, when no GPS signal is found or used.</string>

バックグラウンド で位置情報の更新を要求する場合にのみ、権限のNSLocationAlwaysAndWhenInUseUsageDescription が必要になります。 詳細については、「バックグラウンド更新の有効化」を参照してください。

GPS などのネイティブの位置情報サービスを使用するアプリは、ユーザーの許可を要求します。 すべてのデバイスが同じ機能を提供しているわけではありません。また、特定のハードウェアの制約があるため、結果が異なる可能性があります。 を使用する前 LocationEngineに、ネイティブの位置情報サービスが有効になっているかどうかを確認することをお勧めします。 ほとんど の iOS デバイスでは、ユーザーは [ 設定 ] > [ プライバシー ] > [ 位置情報サービス ] の順に移動して位置情報サービスがオンになっていることを確認できます。

最近の iPad デバイスでも 、UIRequiredDeviceCapabilitiesに必要なgpsの機能が不足 している可能性があります。 Info.plist ファイルに存在する場合、アプリ はこのようなデバイスにインストールされません。 この機能を削除すると、アプリ がインストールされますが 、デバイスから受け取る更新 Locationの精度は半径が大きくなり、結果として非常に不正確になります。 GPS センサーがない場合、デバイスはネットワークの配置などにフォールバックすることがあります。

以下のコード スニペットを使用して、アプリケーションを確認 CLAuthorizationStatus し、ユーザーの承認を要求できます。 Apple の 詳細については、 iOS のドキュメントを参照 CLAuthorizationStatusしてください。

import CoreLocation

// ...

private func startLocating() {
    if locationEngine.start(locationAccuracy: .bestAvailable) == .missingPermissions {
        // App is missing location permission, let's request it.
        requestLocationAuthorization()
    }
}

// ...

public func requestLocationAuthorization() {
    // Get current location authorization status.
    let locationAuthorizationStatus = CLLocationManager.authorizationStatus()

    // Check authorization.
    switch locationAuthorizationStatus {
    case .restricted:
        // Access to location services restricted in the system settings.
        let alert = UIAlertController(title: "Location Services are restricted", message: "Please remove Location Services restriction in your device Settings", preferredStyle: .alert)
        let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
        alert.addAction(okAction)
        present(alert, animated: true, completion: nil)
        return

    case .denied:
        // Location access denied for the application.
        let alert = UIAlertController(title: "Location access is denied", message: "Please allow location access for the application in your device Settings", preferredStyle: .alert)
        let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
        alert.addAction(okAction)
        present(alert, animated: true, completion: nil)
        return

    case .authorizedWhenInUse, .authorizedAlways:
        // Authorization ok.
        break

    case .notDetermined:
        locationManager.requestWhenInUseAuthorization()
        break

    default:
        break
    }
}

LocationEngine を作成します

LocationEngine の新規作成は簡単です。

// Create instance of location engine.
do {
    try locationEngine = LocationEngine()
} catch let engineInstantiationError {
    fatalError("Failed to initialize LocationEngine. Cause: \(engineInstantiationError)")
}

最後に確認した場所を取得

エンジンが初期化されると、少なくとも 1 回前にエンジンが始動し、少なくとも 1 つの位置を受信している限り、最後に確認された位置を取得できます。そうでない場合、nil が返されます。 この情報は残ります。したがって、最後に確認された場所もアプリケーションセッション間で利用できます。

if let myLastLocation = locationEngine.lastKnownLocation {
    // Log the last known location coordinates.
    print("Last known location: '%f', '%f'", myLastLocation.coordinates.latitude, myLastLocation.coordinates.longitude)
}

LocationEngine 最後の既知の場所を取得するために、を開始する必要はありません。また、リスナーを設定する必要もありません。 が LocationEngine 前のセッションで 1 回正常に開始され、有効な位置イベントが少なくとも 1 回受信されただけで十分です。 Location オブジェクトには timestamp 、その場所がいつ受信されたかを示すが含まれています。

位置情報イベントの通知を受信

次に、 LocationEngine を開始する前に、 LocationStatusDelegate プロトコルに準拠してエンジンのステータスの変更が通知されるようにし、それをロケーションエンジンの addLocationStatusDelegate() メソッドに登録することをお勧めします。 さまざまなステータスの詳細については、 API リファレンス を確認してください。

class PositioningExample: LocationStatusDelegate {

    func onStatusChanged(locationEngineStatus: LocationEngineStatus) {
        print("LocationEngineStatus: : \(locationEngineStatus)")
    }

    func onFeaturesNotAvailable(features: [LocationFeature]) {
        for feature in features {
            print("Feature not available: '%s'", String(describing: feature))
        }
    }

// ...

    locationEngine.addLocationStatusDelegate(locationStatusDelegate: self)

// ...

}

開始が成功すると、LocationStatusDelegateは常にステータスLocationEngineStatus.engineStartedを受信し、停止が成功すると、常にステータスLocationEngineStatus.engineStoppedを受信します。

また、代理人 onFeaturesNotAvailable() のコールバック を通じて LocationFeature 、利用できないものがある場合は通知されます。 必要なフィーチャーが利用できない場合は、HERE の担当者にご連絡ください。 注 : LocationFeature 列挙型 (enum) は現在保留中のフィーチャーです。

エンジンを始動する前に最後に考慮すべきことは、 LocationDelegate プロトコルに準拠していることです。このプロトコルは、新しい Location が検出されたときに通知を送信する onLocationUpdated() コールバックを提供します。 これは、前述のLocationStatusDelegateと同様の方法で行うことができ ます。

class PositioningExample: LocationDelegate {

    func onLocationUpdated(location: Location) {
        print("Location updated: \(location.coordinates)")
    }

// ...

    locationEngine.addLocationDelegate(locationDelegate: self)

// ...

}

コールバック onLocationUpdated() はメインスレッドで受信されます。他のすべてのコールバックと同じです。

現在の地理座標およびタイムスタンプを除き、その他 Location のすべてのフィールドはオプションです。 たとえば、受信 したオブジェクトLocation には、ベアリング角度および現在の速度に関する情報が含まれている場合がありますが、この情報は利用できることは保証されていません。 使用できない値は、として返さ nilれます。 ポジショニングに使用されるソースの種類( エンジンの始動に使用されるLocationAccuracyによって定義されます。以下の「 Start and Stop Receiving Locations 」セクションを参照してください)と、デバイスの機能が利用可能なフィールドに影響を与えます。

それぞれのaddLocationStatusDelegate()メソッドおよびaddLocationDelegateメソッドを呼び出して、必要なだけLocationStatusDelegateおよびLocationDelegateを追加できます。

位置情報受信の開始および停止

次のコード スニペットのように、事前定義された LocationAccuracy モードのいずれかを渡して、 LocationEnginestart() メソッドを呼び出す準備ができました。

class PositioningExample: LocationStatusDelegate, LocationDelegate {

// ...

    private func startLocating() {
        locationEngine.addLocationStatusDelegate(locationStatusDelegate: self)
        locationEngine.addLocationDelegate(locationDelegate: self)
        if locationEngine.start(locationAccuracy: .bestAvailable) == .missingPermissions {
            requestLocationAuthorization()
        }
    }

// ...

}

start() このメソッドはすでに次の値を返しています LocationStatus: LocationStatusDelegate 上の行でを設定しましたが、ステータスをただちに使用して、アプリケーションに位置情報の権限が付与されているかどうかを確認します。 権限が付与されていない場合、 OS はユーザーに権限を要求します。

LocationEngine iOS プラットフォーム の位置情報を使用して位置情報の更新を生成します。 LocationAccuracy が iOS 自体の CLLocationAccuracy にマップする方法については、以下の表を参照してください。利用可能なすべてのモードの詳細については、API リファレンスを参照してください。

LocationAccuracy 次の表に、CLLocationAccuracyからへのマッピングを示します。

位置精度 CLLocationAccuracy
最高の可用性 kCLLocationAccuracyBest
ナビゲーション kCLLocationAccuracyBestForNavigation
TensOfMeters kCLLocationAccuracyNearestTenMeters
100 分の 1 メートル法 kCLLocationAccuracyHundredMeters
キロメートル kCLLocationAccuracyThreeKilometers

LocationEngine が開始された後 stop() は、ユーザーがコールするまで開始状態のままになります。 LocationEngineStatus.alreadyStarted 最初にstop()をコールせずにもう一度コールしようとすると、メッセージが表示されます。 このメソッドisStarted() を使用して、エンジンが始動しているかどうかを確認できます。 同様に、 LocationEngine を開始し、最初のものを停止せずに別のものを開始しようとすると、 LocationEngineStatus.alreadyStarted エラーが発生します。 一度に始動できるエンジンは 1 つだけです。

位置情報の更新をこれ以上受信したくない場合 stop() は、メソッドを呼び出してエンジンを停止できます。 不要になった受講者は、必ず削除してください。

class PositioningExample: LocationStatusDelegate, LocationDelegate {

// ...

    public func stopLocating() {
        locationEngine.removeLocationDelegate(locationDelegate: self)
        locationEngine.removeLocationStatusDelegate(locationStatusDelegate: self)
        locationEngine.stop()
    }

// ...

}

一般 に、アプリが廃棄された場合は、LocationEngine を停止することをお勧めします。

停止中の更新を一時停止

デフォルト LocationEngine では、ロケーションデータが変更されない場合、は自動的にロケーションの更新を一時停止します。 これを使用すると、デバイスが静止している場合など、バッテリーの寿命を延ばすことができます。 このフィーチャーは、 LocationEngine.setPauseLocationUpdatesAutomatically()を呼び出して制御できます。

バックグラウンド更新の有効化

アプリケーションがバックグラウンドで実行されているときに位置情報の更新を引き続き受信する場合は、アプリのファイルInfo.plist に次のキーを追加して、この機能を有効にする必要があります。

<key>UIBackgroundModes</key>
    <array>
        <string>location</string>
        <string>processing</string>
    </array>

iOS バージョン 13.0 以降では、「処理」モードが必要です。 追加する場合は、次のものも必要です。

<key>BGTaskSchedulerPermittedIdentifiers</key>
    <array>
        <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    </array>

詳細については、 Apple の iOS のドキュメントを参照してください。

さらに、ユーザーに自動化のリクエストが必要です。 上記のセクションで共有したコード スニペットでは、必要な権限を追加 することもできます。

自動化がクリアされると、すべての設定が完了します。 LocationEngine.setBackgroundLocationAllowed() メソッドを使用すると、バックグラウンドで位置情報の更新を有効または無効にできます。 LocationEngine.setBackgroundLocationIndicatorVisible()メソッドを使用して、アプリケーションのバックグラウンド位置情報インジケータの表示範囲を設定することもできます。

最後に、 LocationEngine.setPauseLocationUpdatesAutomatically() メソッドに false 渡すことで、デバイスが停止しているときに位置情報の更新が一時停止しないようにできます。

setBackgroundLocationAllowed()setBackgroundLocationIndicatorVisible()は、アプリケーションでバックグラウンド位置情報フィーチャーが有効になっていない場合には、LocationEngineStatus.notAllowed が戻ります。 それ以外の場合は 、LocationEngineStatus.ok が返されます。

付属の Positioning Example アプリでは、既定ではバックグラウンド更新が有効になっていません

位置情報から精度情報にアクセス

Locationオブジェクト内に存在する horizontalAccuracyInMetersフィールドは、「不確実性の半径」とも呼ばれ、68% の確率で真の地理座標が存在する可能性が高いエリアの推定値を提供します。これは、現在の位置の周囲にハローインジケータを描画するために使用されます。 下の図は、内側の緑色の円location.coordinatesに 、周囲の円を半径の精度の円horizontalAccuracyInMetersとして示し ています。 正確な地理座標は、精度円の内側(68%)または外側(32%)にあります。

図: 水平方向の不確実性と垂直方向の不確実性の半径。

同様に、高度の場合、 verticalAccuracyInMeters 値が10メートルの場合、実際の高度は 、 68%の確率で、高度-10mから高度+10mの範囲内にあると予想されます。 bearingAccuracyInDegrees およびspeedAccuracyInMetersPerSecondなどの他の精度値も同じ規則に従います。不確実性が小さいほど精度が向上します。

この値coordinates.altitudeは平均海面レベル(MSL)に関連して与えられます。

68% を超える確率で達成 (CEP68)

68% の確率 (CEP68) では不十分な場合、 99% の精度を達成できますか ? はい、次のとおりです。 与えられた円形誤差確率 (CEP) は自由度が 2 つのカイ (χ)2乗分布に続くため、次の式に基づいて望ましい確率を簡単に計算できます。

確率 不確実性の半径
50% CEP50 = 0.78 x CEP68
60% CEP60 = 0.90 x CEP68
70% CEP70 = 1.03 x CEP68
80% CEP80 = 1.19 x CEP68
90% CEP90 = 1.42 x CEP68
95% CEP95 = 1.62 x CEP68
99% CEP99 = 2.01 x CEP68

上の表を使用して、マップ上のハローインジケータのさまざまな確率レベルを表示できます。 たとえば、水平方向の精度が 20 メートルの場合、半径のほぼ 2 倍の確率で 99 %を達成できます。 精度値は常に CEP68 として指定されます。つまり、次のことを意味します。

CEP99 = 2.01 x CEP68 = 2.01 x 20m = 40.2m

発見された場所の周囲に 40.2 メートルの半径を描画できるようになり ました。確率は 99% で、実際の場所はその円の内側にあります。 一方、半径 0 メートルの確率は 0% です。

チュートリアル : 現在地をマップに表示

LocationIndicatorは 、マップ上のデバイスの現在位置を表すために使用されます。 インジケータが現在の位置の値で更新される前に、デフォルト Location が設定されます。デフォルトは、最後に確認された場所、または最初の位置更新が到着する前にユーザが表示する必要がある場所です。 デフォルトでは、水平精度は半径horizontalAccuracyInMetersMapCircle で表示されます。

//Default start-up location.
private static let defaultGeoCoordinates = GeoCoordinates(latitude: 52.520798, longitude: 13.409408)

// LocationIndicator object to represent device's current location.
private var locationIndicator: LocationIndicator!

// ...

private func addMyLocationToMap(myLocation: Location) {
    // Setup location indicator.
    locationIndicator = LocationIndicator()
    // Enable a halo to indicate the horizontal accuracy.
    locationIndicator.isAccuracyVisualized = true
    locationIndicator.locationIndicatorStyle = .pedestrian;
    locationIndicator.updateLocation(myLocation)
    mapView.addLifecycleDelegate(locationIndicator)
    // Point camera to current location.
    let distanceInMeters = MapMeasure(kind: .distance,
                                      value: PositioningExample.defaultCameraDistance)
    mapCamera.lookAt(point: myLocation.coordinates,
                     zoom: distanceInMeters)                 
}

private func updateMyLocationOnMap(myLocation: Location) {
    // Update location indicator.
    locationIndicator.updateLocation(myLocation)
    // Point camera to current location.
    mapCamera.lookAt(point: myLocation.coordinates)
}

// ...

if let lastLocation = locationEngine.lastKnownLocation {
    addMyLocationToMap(myLocation: lastLocation)
} else {
    var defaultLocation = Location(coordinates: PositioningExample.defaultGeoCoordinates)
    defaultLocation.time = Date()
    addMyLocationToMap(myLocation: defaultLocation)
}

// ...

func onLocationUpdated(_ location: Location) {
    updateMyLocationOnMap(myLocation: location)
}

スクリーンショット: マップ上の現在の位置を示す位置情報インジケータ。

上記の実装に示されているように、updateLocation()を呼び出して、Locationオブジェクトを位置情報インジケータに渡すことができます。 この例では、ユーザーの現在の位置を追跡することを目的としています。そのため、マップビューポートの中心位置も更新されます。

」に一致する結果は 件です

    」に一致する結果はありません