ガイド変更履歴API references
ガイド

マップ データを更新する

オフラインマップはNavigateライセンスでのみ使用できます。

MapUpdaterクラスを使用すると、新しいマップバージョンが利用できるかを確認でき、利用できる場合は、すでにインストールされている地域を更新できます。HERE SDK の各バージョンには、特定のマップ バージョンがハードコードされています。これにより、キャッシュ内のマップ データとダウンロードされた地域 (存在する場合) が定義されます。

関連する「API リファレンス」ドキュメントまたはこのガイドに記載されているように、一部の HERE SDK 機能には特定の地図のバージョンが必要になる場合があります。

地図の差分更新は、デフォルトでサポートされています。地域全体をダウンロードするのではなく、変更された部分のみがインストールされます。これにより、更新プロセスが高速化され、ダウンロードされるデータが減少します。CatalogConfigurationpatchHrn フィールドが nil の場合、差分更新は無効になり、マップ データはある程度まで増分的にダウンロードされますが、バンドルが大きくなるため、帯域幅の消費量が増加します。通常、これは HERE SDK によって内部的に処理されるため、開発者が独自に CatalogConfiguration を作成する必要はありません。

通常、地図更新は毎週提供されています。初めて使用する場合、ユーザーはリージョン全体をダウンロードする必要があります。初回ダウンロード後の更新では、差分更新を実行できます。全体のダウンロードを実行するか差分更新のみを実行するかは、HERE SDK によって自動的に決定されます。

マップの増分更新 (「パッチ適用」とも呼ばれます) を行うと、約8つのOCMマップバージョンでダウンロードのサイズが小さくなります。たとえば、OCMバージョンx.y.7の新しいマップバージョンをインストールした場合、x.y.15までは増分更新のメリットがあります。OCMバージョンx.y.16以降では、バージョンがスキップされた場合でも、再び多くのマップデータが必要になります。
OCMマップが毎週更新される場合、約8週間後には、mapUpdater.updateCatalog(...)の実行時にMapUpdaterによってさらに多くのデータがダウンロードされます。更新を実行する前に、CatalogUpdateInfoによって更新されるマップデータの量に関する情報が提供されます。

MapUpdater を使用する

新しい HERE SDK バージョンを統合するアプリの更新がインストールされると、ほとんどの場合、新しいマップ バージョンも統合されます。ただし、MapUpdater を使用してこのタスクを実行しない限り、インストール済みの地域は自動的に更新されません。もちろん、古い HERE SDK バージョンの地図更新もインストールできます。

  • mapUpdater.getCurrentMapVersion() を呼び出して、現在使用されている地図のバージョンを確認します。
  • mapUpdater.retrieveCatalogsUpdateInfo() を呼び出して、更新が利用できるかを確認します。

このクラスは、UI スレッドをブロックしないように、MapDownloader と同じ方法で非同期に作成する必要があります。

guard let sdkNativeEngine = SDKNativeEngine.sharedInstance else {
    fatalError("SDKNativeEngine not initialized.")
}

// Create MapUpdater in background to not block the UI thread.
MapUpdater.fromEngineAsync(sdkNativeEngine, { mapUpdater in
    let mapUpdaterInstance = mapUpdater
    // Use the instance ...
})

現在のマップ バージョンを取得する

マップ キャッシュに使用されるマップ バージョンとインストールされている Region データを知っておくと役に立つ場合があります。以下のコード スニペットを使用すると、現在使用されているマップ バージョンを記録できます。

guard let sdkNativeEngine = SDKNativeEngine.sharedInstance else {
    fatalError("SDKNativeEngine not initialized.")
}

// Create MapUpdater in background to not block the UI thread.
MapUpdater.fromEngineAsync(sdkNativeEngine, { mapUpdater in
    let mapUpdaterInstance = mapUpdater

    do {
        let mapVersionHandle = try mapUpdaterInstance.getCurrentMapVersion()
        let versionInfo = mapVersionHandle.stringRepresentation(separator: ",")
        print("Info: \(String(describing: versionInfo))")
    } catch let mapLoaderException {
        fatalError("Get current map version failed: \(mapLoaderException.localizedDescription)")
    }
})

バージョン情報は主にデバッグ目的に役立ちます。マップ バージョンは、マップ ビューが初めて表示されたときにも HERE SDK によって記録されます。

形式は [cache-version].[offline-maps-version],[japan-cache-version].[japan-offline-maps-version] です。結果の例は、「47.47,47.47」のようになります。マップ キャッシュとオフライン マップで異なるバージョンを取得することはできません。

地図の更新を確認する

アプリの起動時に、地図に更新があるかを確認できます。ただし、地域データがインストールされている場合は、作業に時間がかかる可能性があるため、ユーザーに通知します。通常、最初にretrieveCatalogsUpdateInfo() を呼び出して更新を確認します。これにより、updateCatalog() の呼び出しに使用できる 1 つ以上の CatalogUpdateInfo 項目が提供されます。

private func checkForMapUpdates() {
    guard let mapUpdater = mapUpdater else {
        showMessage("MapUpdater instance not ready. Try again.")
        return
    }

    _ = mapUpdater.retrieveCatalogsUpdateInfo(callback: onCatalogUpdateCompleted)
}

// Completion handler to get notified whether a catalog update is available or not.
private func onCatalogUpdateCompleted(mapLoaderError: MapLoaderError?, catalogList: [CatalogUpdateInfo]?) {
    if let error = mapLoaderError {
        print("CatalogUpdateCheck Error: \(error)")
        return
    }

    // When error is nil, then the list is guaranteed to be not nil.
    if catalogList!.isEmpty {
        print("CatalogUpdateCheck: No map updates are available.");
    }

    logCurrentSDKVersion();
    logCurrentMapVersion();

    for catalogUpdateInfo in catalogList! {
        print("CatalogUpdateCheck - Catalog name:" + catalogUpdateInfo.installedCatalog.catalogIdentifier.hrn);
        print("CatalogUpdateCheck - Installed map version: \(String(describing: catalogUpdateInfo.installedCatalog.catalogIdentifier.version))");
        print("CatalogUpdateCheck - Latest available map version: \(catalogUpdateInfo.latestVersion)");
        performMapUpdate(catalogUpdateInfo: catalogUpdateInfo);
    }
}

マップ データとマップ バージョンを更新する

次のステップとして、地図の更新を実行するコードを実装します。これにより、マップ バージョンも上がります。

// Downloads and installs map updates for any of the already downloaded regions.
// Note that this example only shows how to download one region.
private func performMapUpdate(catalogUpdateInfo: CatalogUpdateInfo) {
    guard let mapUpdater = mapUpdater else {
        showMessage("MapUpdater instance not ready. Try again.")
        return
    }

    // This method conveniently updates all installed regions if an update is available.
    // Optionally, you can use the returned CatalogUpdateTask to pause / resume or cancel the update.
    _ = mapUpdater.updateCatalog(catalogInfo: catalogUpdateInfo, completion: catalogUpdateListenerImpl)
}

private let catalogUpdateListenerImpl = CatalogUpdateListenerImpl()

private class CatalogUpdateListenerImpl : CatalogUpdateProgressListener {
    // Conform to the CatalogUpdateProgressListener protocol.
    func onPause(error: heresdk.MapLoaderError?) {
        if let mapLoaderError = error {
            print("Catalog update onPause error. The task tried to often to retry the update: \(mapLoaderError).")
        } else {
            print("CatalogUpdate: The map update was paused by the user calling catalogUpdateTask.pause().")
        }
    }

    // Conform to the CatalogUpdateProgressListener protocol.
    func onProgress(region: RegionId, percentage: Int32) {
        print("CatalogUpdate: Downloading and installing a map update. Progress for \(region.id): \(percentage)%.")
    }

    // Conform to the CatalogUpdateProgressListener protocol.
    func onComplete(error: MapLoaderError?) {
        if let mapLoaderError = error {
            print("CatalogUpdate completion error: \(mapLoaderError)")
            return
        }
        print("CatalogUpdate: One or more map update has been successfully installed.")

        // It is recommend to call now also `getDownloadableRegions()` to update
        // the internal catalog data that is needed to download, update or delete
        // existing `Region` data. It is required to do this at least once
        // before doing a new download, update or delete operation.
    }

    // Conform to the CatalogUpdateProgressListener protocol.
    func onResume() {
        print("MapUpdate: A previously paused map update has been resumed.")
    }
}

updateCatalog() の呼び出しは、実際に変更された Region の部分のみを更新するように内部的に最適化されています。つまり、ほとんどの場合、更新ではユーザーがすべてのパッケージを再ダウンロードする必要はなく、各地域がいくつかの内部バンドルに分割され、その中でマップ データに変更があった場合にのみ再ダウンロードされます。この手順は地図の差分更新とも呼ばれます。

  • オフライン マップがインストールされていない場合、mapUpdater.updateCatalog() を呼び出してもキャッシュがクリアされるだけで、その後、キャッシュには利用できる最新の地図バージョンの新しいデータが書き込まれます。
  • キャッシュは常にオフライン マップと同じマップ バージョンを使用します。オフライン マップが更新されると、キャッシュも更新されます。キャッシュのバージョンがオフライン マップのバージョンより古くなることはありません。

deleteRegions() 経由でダウンロードしたすべての地域をアンインストールし、必要な地域を再度ダウンロードすることで地図更新を強制することはできません。その場合、同じマップ バージョンがダウンロードされます。ただし、updateCatalog() を事前に実行すると、地図の更新が表示され、インストールできる場合があります。

地図を更新するときは、次の点を確認してください。

  • mapUpdater.updateCatalog() が完了したら、getDownloadableRegions() を呼び出して、既存の Region データのダウンロード、更新、削除に必要な内部カタログ データを更新する必要があります。
  • 地図の更新と関連する操作が進行している間は、一部の MapDownloaderMapUpdater の機能にアクセスできない場合があります。多くの操作は並行して実行できますが、場合によっては、実行できず、エラー メッセージが表示されることがあります。そのような場合、現在の操作が成功するまで待ってから再試行してください。

deleteRegions() を呼び出して再試行可能なエラーが発生した場合は、インターネット接続に問題があった可能性があります。この場合、DownloadRegionsStatusListeneronPause() イベントを起動し、影響を受けたダウンロードは一時停止状態になります。ダウンロードが一時停止状態にある場合、ストレージが不整合な状態にある可能性があるため、地域を削除できません。この問題を解決するには、ダウンロードの一時停止を解除するか、キャンセルしてから、もう一度試してください。

詳細については、GitHubの「OfflineMaps」サンプルアプリを参照してください。