はじめに
「ArcGIS Runtime SDK で実現できるオフラインワークフロー」シリーズブログでは、オフラインアプリの開発を始める方の第一歩として、ArcGIS Runtime で実現できるオフラインワークフロー、データの準備、ポイントとなるコードについてご紹介しています。今回が最後のシリーズとなります 「~サービス パターン~」 についてご紹介します。
前回の記事では、デスクトップ パターンを実現するために必要なデータの作成方法とデータを読み込むためのコードについてご紹介しました。シリーズ第 3 回目となる今回は、サービス パターンをご紹介します。サービス パターンは、オンデマンドとプレプランの 2 つ方法によって、オフライン環境で利用できる地図データを作成することができます。
今回は、オンデマンドとプレプランを活用する第一歩として、Web マップを使用して、地図データをダウンロードして、オフライン マップを扱うまでのコードをご紹介していきます。
オンデマンドの実現に必要な手順
データ準備
① Web マップ
今回は、昨年度開催された「ArcGIS 開発者のための最新アプリ開発塾2019」で使用した街路樹の Web マップを使用します。
Web マップを作成する手順については、ArcGIS for Developers 開発リソース集の Web マップの作成をご参照ください。
② レイヤーの設定
Webマップは、オフラインで地図が使用できるように幾つかの設定を有効にする必要があります。例えば、オフライン マップでデータをダウンロードし、ダウンロードしたデータをフィーチャ サービスとの同期を有効化にするなどの設定があります。
オフラインで使用するための設定については以下をご参照ください。
コードのポイント
Web マップを参照して、オフライン マップを扱うまでのステップをコードでご紹介します。
① オフライン マップのタスク作成とパラメーターの設定
② オフライン マップを生成するためのジョブの作成と実行
① オンライン マップのタスク作成とパラメーターの設定
オンライン マップまたは、ポータルアイテムからオフライン マップのタスク (OfflineMapTask) を作成します。作成には、OfflineMapTask クラスの CreateAsync メソッドを使用します。
パラメーターの設定は、OfflineMapTask クラス の CreateDefaultGenerateOfflineMapParametersAsync メソッドにカバーする目的のエリアを指定して デフォルトのパラメーター (GenerateOfflineMapParameters) を作成します。
デフォルト以外に以下のパラメーターを設定することができます。
その他のパラメーターについては、詳細パラメーターをご参照ください。
// 指定したポータルのアイテム ID から PortalItem クラスのインスタンスを作成 PortalItem webmapItem = await PortalItem.CreateAsync(portal, "acc027394bc84c2fb04d1ed317aac674"); // Map のプロパティに webmapItem を指定して、Map クラスのインスタンスを作成 Map onlineMap = new Map(webmapItem); // 上記で作成した onlineMap もしくは、webmapItem を CreateAsync メソッドに指定 OfflineMapTask takeMapOfflineTask = await OfflineMapTask.CreateAsync(onlineMap); // or webmapItem を指定した場合 OfflineMapTask takeMapOfflineTask = await OfflineMapTask.CreateAsync(webmapItem); // カバーするマップ エリアを指定して、デフォルトのパラメーターを作成します。 Envelope areaOfInterest = GetAreaOfInterest(); GenerateOfflineMapParameters parameters = await takeMapOfflineTask.CreateDefaultGenerateOfflineMapParametersAsync(areaOfInterest);
② オンライン マップを生成するためのジョブの作成と実行
オフライン マップを生成してダウンロードするには、OfflineMapTask クラスの GenerateOfflineMap メソッドに GenerateOfflineMapParameters とマップを保存するためのデバイス上のディレクトリを指定して、GenerateOfflineMapJob を作成します。オフライン マップを作成してデバイスにダウンロードするには、GenerateOfflineMapJob を実行します。ジョブが完了すると、GenerateOfflineMapResult のインスタンスを返します。GenerateOfflineMapResult の OfflineMap プロパティを MapView の Map プロパティに指定することでオフライン マップを表示することができます。
// パラメーターとマップを保存するためのパスを指定して、オフライン マップを生成するジョブを作成します。 GenerateOfflineMapJob offlineMapJob = takeMapOfflineTask.GenerateOfflineMap(parameters, pathToOutputPackage); // ジョブ完了後、オフライン マップを作成してダウンロードを開始します。 GenerateOfflineMapResult offlineMapResult = await offlineMapJob.GetResultAsync(); if (!offlineMapResult.HasErrors) { // ジョブは正常に完了し、すべてのコンテンツが作成されました。 Debug.WriteLine("Map " + offlineMapResult.MobileMapPackage.Item.Title + " was saved to " + offlineMapResult.MobileMapPackage.Path); // オフライン マップを MapView に指定して表示します。 MyMapView.Map = offlineMapResult.OfflineMap; }
以下は、Esri が公開しているサンプルソース (Generate offline map) を使用して実行したアプリの例となります。
上記のコードを使用して実行したイメージとなります。
1. オフラインで使用するマップ エリアを指定してダウンロード
2.指定した範囲のマップがダウンロードされ、ダウンロードしたマップがオフライン マップとして使用できます。
オンデマンドのワークフローによって作成されたオフライン マップは、モバイルマップ パッケージが作成されます。作成されたモバイルマップ パッケージは、ディレクトリを指定することでオフライン マップを参照することができます。次のステップとして、このモバイルマップ パッケージを参照して、必要に応じてデータを編集したり、接続がオンラインになったらオンライン サービスと同期して、オンライン マップを更新したりできます。
詳細については、ArcGIS 開発者のための最新アプリ開発塾 2020 > ArcGIS Runtime SDK for .NET を使用して現地調査アプリを開発してみよう! > Step3:アップロード機能の実装をご参照ください。
プレプランの実現に必要な手順
データ準備
① Web マップ
プレプランでは、モバイル マップパッケージを事前に作成して、現場作業員が必要なときにダウンロードできるようにします。これを行うには、Web マップにプレプラン エリアを作成します。Web マップは、オンデマンドで使用した街路樹の Web マップを使用します。
② プレプラン エリアの作成
プレプラン エリアの作成は、ArcGIS Online または、ArcGIS Enterprise を使用して手動で作成する方法と Python スクリプト、ArcGIS REST API を使用してプログラミングで作成する方法があります。
※ Web マップを使用してプレプラン エリアを作成する場合に、オフラインで使用できるように有効になっていることを確認する必要があります。
※ ArcGIS Enterprise を使用して事前に計画されたプレプラン エリアを作成する場合は、ArcGIS Enterprise 10.6.1 以降を使用する必要があります。
● ArcGIS Online によるプレプラン エリアの作成例
ArcGIS Online では、Web マップの設定で、マップ エリアのカテゴリの「エリアの管理」で作成することができます。
ArcGIS Online または、ArcGIS Enterprise を使用して作成する方法については以下をご参照ください。
Python スクリプト(ArcGIS API for Python)や ArcGIS REST API を使用して作成する方法については、「マップ エリアの作成 (プレプラン)」をご参照ください。
コードのポイント
Web マップを参照して、オフライン マップを扱うまでのステップをコードでご紹介します。
① マップ エリアの指定とパラメーターの設定
② プレプランを行うためのジョブの作成と実行
① マップ エリアの選択とパラメーターの設定
OfflineMapTask クラスの CreateAsync メソッドにマップ (Web マップから作成) または Web マップのポータル アイテムのいずれかを指定して、オフライン マップタスクの (OfflineMapTask) を作成します。OfflineMapTask の GetPreplannedMapAreasAsync メソッドを使用して、Web マップからマップ エリアのリストを取得して選択します。
パラメーターの設定は、DownloadPreplannedOfflineMapParameters クラスを使用してパラメーターを作成します。デフォルトのパラメーター設定には、選択したマップ エリアを OfflineMapTask の CreateDefaultDownloadPreplannedOfflineMapParametersAsync メソッドに指定します。
デフォルト以外に以下のパラメーターを設定することができます。
その他については、「高度なパラメーター」をご参照ください。
// ID を使用して Web マップのアイテムを取得します。 PortalItem webmapItem = await PortalItem.CreateAsync(portal, "acc027394bc84c2fb04d1ed317aac674"); // Web マップのアイテムからマップを作成します。 Map onlineMap = new Map(webmapItem); // マップから OfflineMapTask を作成します。 OfflineMapTask takeMapOfflineTask = await OfflineMapTask.CreateAsync(onlineMap); // ... または、Web マップのポータルアイテムから作成します。 OfflineMapTask takeMapOfflineTask = await OfflineMapTask.CreateAsync(webmapItem); // 利用可能なマップ エリアの一覧を取得します。 IReadOnlyList<PreplannedMapArea> preplannedMapAreaList = await takeMapOfflineTask.GetPreplannedMapAreasAsync(); // すべてのマップ エリア foreach (PreplannedMapArea mapArea in preplannedMapAreaList) { // マップ エリアをロードします。 await mapArea.LoadAsync(); // このエリアのジオメトリを取得します。 Geometry aoi = mapArea.AreaOfInterest; // このエリアのポータルアイテムを取得し、タイトルとサムネイル画像を読み込みます。 PortalItem preplannedMapItem = mapArea.PortalItem; string mapTitle = preplannedMapItem.Title; RuntimeImage areaThumbnail = preplannedMapItem.Thumbnail; } // デフォルトのパラメーターを取得します(マップ エリアを指定します)。 DownloadPreplannedOfflineMapParameters defaultDownloadParams = await takeMapOfflineTask.CreateDefaultDownloadPreplannedOfflineMapParametersAsync(downtownMapArea);
② プレプランを行うためのジョブを作成と実行
OfflineMapTask 上で DownloadPreplannedOfflineMap メソッドを呼び出して、マップをダウンロードするために DownloadPreplannedOfflineMapJob ジョブを作成します。DownloadPreplannedOfflineMap メソッドには、「① マップ エリアの選択とパラメーターの設定」で設定したパラメーターとダウンロードして保存するためのディレクトリのパスを指定します。マップ エリアをデバイスにダウンロードするには、DownloadPreplannedOfflineMapJob ジョブを実行します。
ジョブが完了すると、DownloadPreplannedOfflineMapResult のインスタンスを返します。
DownloadPreplannedOfflineMapResult の OfflineMap プロパティの Map プロパティに指定することでオフライン マップを表示することができます。
// parameters と pathToOutputPackage を指定します。 DownloadPreplannedOfflineMapJob preplannedMapJob = takeMapOfflineTask.DownloadPreplannedOfflineMap(parameters, pathToOutputPackage); // ジョブ完了後、オフライン マップを生成してダウンロードします。 DownloadPreplannedOfflineMapResult preplannedMapResult = await preplannedMapJob.GetResultAsync(); if (!preplannedMapResult.HasErrors) { // ジョブが正常に完了し、すべてのコンテンツが生成されます。 Debug.WriteLine("Map " + preplannedMapResult.MobileMapPackage.Item.Title + " was saved to " + preplannedMapResult.MobileMapPackage.Path); // オフライン マップを MapView で表示します。 MyMapView.Map = preplannedMapResult.OfflineMap; }
以下は、Esri が公開しているサンプルソース (Download preplanned map area) を使用して実行したアプリの例になります。
上記のコードを使用して実行したイメージとなります。
1. オフラインで使用するマップを選択
2. 選択したマップのダウンロード
3. 選択したマップがダウンロードされ、ダウンロードしたマップがオフライン マップとして使用できます。
プレプランもオンデマンドと同様にオフライン マップは、モバイルマップ パッケージが作成されます。作成されたモバイルマップ パッケージは、ディレクトリを指定することでオフライン マップを参照することができます。次のステップとして、このモバイルマップ パッケージを参照して、必要に応じてデータを編集したり、接続がオンラインになったらオンライン サービスと同期して、オンライン マップを更新したりできます。
詳細については、ArcGIS 開発者のための最新アプリ開発塾 2020 > ArcGIS Runtime SDK for .NET を使用して現地調査アプリを開発してみよう! > Step3:アップロード機能の実装をご参照ください。
まとめ
今回は、ArcGIS Runtime SDK を使って実現できるオフライン ワークフローのサービス パターンについてご紹介しました。サービス パターンでは、オンデマンドとプレプランの2パターンがあり、オンデマンドでは、必要な時に必要な範囲のエリアを指定してデータをダウンロードし、プレプランでは、マップの作成者が事前にオフラインで必要なエリアのデータをパッケージ化することで、ダウンロード時間を短縮することができます。
今回は、オンデマンドとプレプランを活用して Web マップを参照して地図データをダウンロードして、オフライン マップを扱うところまでをご紹介しました。
次のステップとして、このオフライン マップを編集したり、ネットワークに再接続した際に編集内容を同期したりすることが必要になってくるかと思います。
今回は詳細にはご紹介することはできませんでしたが、オフライン マップの編集や同期については、2020年8月25日に開催した ArcGIS 開発者のための最新アプリ開発塾の「ArcGIS プラットフォームを活用した現地調査アプリ開発ハンズオン 」で紹介しましたので、ご興味がございましたら参照していただければと思います。
これまで3回に渡って ArcGIS Runtime で実現できるオフラインワークフローにご紹介してきました。
第1回目は概要編として、ArcGIS Runtime SDK を使って実現できるオフライン ワークフローについてご紹介しました。また、第 2 回目のデスクトップ パターンでは、ArcGIS Pro によるモバイル マップ パッケージの使用方法やローカルデータとしてシェープファイルなどの使用方法についてご紹介しました。そして、第 3 回目では、サービスパターンをご紹介しました。
今回でシリーズは最後となりますが、ぜひ、オフライン マップの開発をはじめるきっかけとなれば幸いです。