出典:ArcGIS Maps SDK for Flutter - Tutorials - Display a map
このチュートリアルでは ArcGIS Maps SDK for Flutter を使用して、マップとベースマップ レイヤーを表示する方法を紹介します。
マップには、地理データのレイヤーが含まれています。マップには、ベースマップ レイヤーと、オプションで 1 つ以上のデータ レイヤーを追加できます。
このチュートリアルでは、地形図ベースマップ レイヤーを使用して、富士山付近を表示する地図を作成します。
このマップとコードは、他の 2D チュートリアルの出発点として使用されます。
このチュートリアルのトピックの背景情報については、Mapping API and location services guide の Maps (2D) と ベースマップ を参照してください。
Android Studio の最新リリースである Meerkat 2024.3.1 以降を使用している場合、pub.dev で arcgis_maps パッケージを使用すると、SDK の依存関係の管理で問題が発生する可能性があります。 これを解決するには、Flutter のデフォルト JDK として JDK 17 を設定する必要があります。
macOS の場合:Homebrew を使用して macOS に JDK 17 をインストールします。
brew install openjdk@17
sudo ln -sfn /opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-17.jdk
flutter config --jdk-dir=/opt/homebrew/Cellar/openjdk@17/17.0.14/libexec/openjdk.jdk/Contents/Home
Windowsの場合:Microsoft の OpenJDK ページから OpenJDK 17 をダウンロードして、zip ファイルを任意のフォルダに解凍した後、PowerShell を使用して設定します。
flutter config --jdk-dir PATH-TO-JDK
このチュートリアルを実施するには、以下が必要です。
VS Code を開き、Welcome タブで [Open Folder…] を選択します。プロジェクトの場所を選んでください。
[View] > [Terminal] に進みます。
ターミナル ウィンドウで以下のコマンドを使い、display_a_map という新しい Flutter アプリを作成します。 必要なターゲット プラットフォームと 組織名 com.example.app を設定します。
flutter create -e display_a_map --platforms ios,android --org com.example.app
arcgis_maps
パッケージに依存関係を追加します。
cd display_a_map
dart pub add arcgis_maps
flutter pub upgrade
dart run arcgis_maps install
プロジェクトの android/app/build.gradle.kts
ファイルを編集して、最小要件を更新します。
build.gradle.kts
android {
namespace = "com.example.app.display_a_map"
compileSdk = flutter.compileSdkVersion
ndkVersion = "27.0.12077973" //変更
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
defaultConfig {
// TODO: 任意のアプリケーション ID を指定します (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.app.display_a_map"
// アプリケーションの要件に合わせて次の値を更新します。
// 詳細については https://flutter.dev/to/review-gradle-config を参照してください。
minSdk = 26 //変更
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
プロジェクトの android/settings.gradle.kts
ファイルを編集して、Kotlin のバージョンを更新します。
settings.gradle.kts
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.7.0" apply false
id "org.jetbrains.kotlin.android" version "1.9.0" apply false //変更
}
android/app/src/main/AndroidManifest.xml
に、オンライン リソースにアクセスするためのパーミッションを追加します。
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" /> <!-- 追加 -->
<application
android:label="display_a_map"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
ios/Podfile
ファイルを編集して iOS 16.0 を最小に設定します。 行のコメントを解除し、バージョン番号を更新します。
Podfile
# Uncomment this line to define a global platform for your project
platform :ios, '16.0' #変更
Runtimecore
pod と arcgis_maps_ffi
pod を Runner
ターゲット セクションに追加します。
Podfile
target 'Runner' do
use_frameworks!
use_modular_headers!
#変更開始
pod 'Runtimecore', :podspec => '../arcgis_maps_core/ios/Runtimecore.podspec'
pod 'arcgis_maps_ffi', :podspec => '../arcgis_maps_core/ios/arcgis_maps_ffi.podspec'
#変更終了
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
pod update
を使用して Pods を設定します。
cd ios && pod update && cd ..
このチュートリアルで使用するロケーション サービスを使用するには、アクセス トークンが必要です。
アクセス トークンを取得する他の方法については、Types of authentication を参照してください。
VS Codeで、lib/main.dart
を開きます。
arcgis_maps
パッケージをインポートします。
main.dart
import 'package:flutter/material.dart';
import 'package:arcgis_maps/arcgis_maps.dart'; //追加
main()
関数で、const apiKey
を定義し、その値にアクセス トークンを設定します。
void main() {
const apiKey = ''; // アクセス トークンをここに記入します。 //追加
runApp(const MainApp());
}
このチュートリアルでは便宜上、アクセス トークンをコードに直接格納しています。アクセス トークンをソース コードに格納することはベスト プラクティスではありません。
ArcGISEnvironment.apiKey
を apiKey
定数に設定します。
main.dart
void main() {
const apiKey = ''; // アクセス トークンをここに記入します。
ArcGISEnvironment.apiKey = apiKey; //追加
runApp(const MainApp());
}
API キーが必要なのにアクセス トークンが設定されていない(または無効な値が設定されている)場合、チュートリアルのコードを実行すると次のようなエラーが表示されることがあります。
Unhandled Loadable ArcGISMap load error: ArcGISException: code=22; HttpException: Failed to parse header value
このエラーが発生した場合は、有効なアクセス トークンが ArcGISEnvironment.apiKey
プロパティに設定されていることを確認してください。Flutter のコア HTTP スタックに既知の問題があるため、ArcGIS Maps SDK for Flutter は現時点でより明確なエラーを確実に提供することができません。
runApp()
内で MaterialApp
をインスタンス化し、名前付き引数の home
に MainApp
のインスタンスを設定します。
main.dart
void main() {
const apiKey = ''; // アクセス トークンをここに記入します。
ArcGISEnvironment.apiKey = apiKey;
runApp(
//変更開始
const MaterialApp(
home: MainApp(),
),
//変更終了
);
}
地形図ベースマップ レイヤーを含む地図を作成します。 地図は富士山の付近とします。
テンプレート MainApp
クラス定義をリファクタリングして、StatefulWidget
を拡張します。 StatelessWidget
キーワードにマウス カーソルを合わせて右クリックし、[Refactor…] から、[Convert to StatefulWidget] を選択してコードをリファクタリングします。
ArcGIS Maps SDK for Flutter で作業していると、データの変更に応じて UI を更新するなど、アプリケーションの状態の更新が必要になることがよくあります。 ステートフル ウィジェットを実装することで、アプリはこのような状況に対応できます。 ステートレス ウィジェットの実装を使用して、単に地図を表示することも可能です。Display map サンプルをご確認ください。
main.dart
class MainApp extends StatefulWidget { //変更
const MainApp({super.key});
// 変更開始
@override
State<MainApp> createState() => _MainAppState();
// 変更終了
}
//追加開始
class _MainAppState extends State<MainApp> {
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: Center(
child: Text('Hello World!'),
),
),
);
}
}
//追加終了
build メソッド内で返される MaterialApp
ウィジェットを削除します。 このコードは Flutter create テンプレートによって生成されたもので、次項でマップを含むウィジェットを返すコードに置き換えられます。
main.dart
class MainApp extends StatefulWidget {
const MainApp({super.key});
@override
State<MainApp> createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
@override
Widget build(BuildContext context) {
// 削除開始
return const MaterialApp(
home: Scaffold(
body: Center(
child: Text('Hello World!'),
),
),
);
// 削除終了
}
}
_MainAppState
クラスの内部で、最後のクラス メンバー変数 _mapViewController
を定義し、ArcGISMapView
クラスの createController()
を呼び出して ArcGISMapViewController
で初期化します。
ArcGIS マップ ビュー コントローラーは、ArcGISMap
で定義された 2 次元 (2D) 地理コンテンツを表示するユーザー インタフェース コントロールです。
main.dart
class _MainAppState extends State<MainApp> {
final _mapViewController = ArcGISMapView.createController(); //追加
@override
Widget build(BuildContext context) {
}
}
build メソッド内で Scaffold
、Column
、Expanded
からなるウィジェット ツリーに ArcGISMapView
ウィジェットを追加します。 引数名 controllerProvider
をクラス メンバー変数 _mapViewController
に設定し、onMapViewReady
引数を次に定義する引数と同じ名前の新しいメソッドに設定します。
Scaffold
ウィジェットは基本的なマテリアル デザインのビジュアル レイアウト構造を提供し、Column
ウィジェットは子ウィジェットを垂直配列で表示します。ArcGISMapView
ウィジェットは、サイズが制限されたウィジェット内でのみ使用できます。 サイズが制限されていない状態で使用すると、アプリケーションは例外をスローします。 たとえば、ArcGISMapView
を Column
ウィジェット内で使用すると、サイズが制限されないため、このような例外が発生します。 代わりに、チュートリアルのこのステップで説明するように、ArcGISMapView
を Expanded
ウィジェットでラップして、適切な境界を提供することができます。
main.dart
class _MainAppState extends State<MainApp> {
final _mapViewController = ArcGISMapView.createController();
@override
Widget build(BuildContext context) {
//追加開始
return Scaffold(
body: Column(
children: [
Expanded(
child: ArcGISMapView(
controllerProvider: () => _mapViewController,
onMapViewReady: onMapViewReady,
),
),
],
),
);
//追加終了
}
}
MainAppState
内で、何も返さない新しいメソッド onMapViewReady()
を定義します。
main.dart
class _MainAppState extends State<MainApp> {
final _mapViewController = ArcGISMapView.createController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: ArcGISMapView(
controllerProvider: () => _mapViewController,
onMapViewReady: onMapViewReady,
),
),
],
),
);
}
//追加開始
void onMapViewReady() {
}
//追加終了
}
新しいメソッド内で final 変数 basemapStyleParams
、basemap
、map
を定義します。それぞれの定義は以下の通りです。
basemapStyleParams
: BasemapStyleParameters
をインスタンス化し、specificLanguage を日本語に変更します。basemap
: ArcGIS Topographic ベースマップ スタイルと 生成した basemapStyleParams
で Basemap
をインスタンス化します。map
: basemap
で ArcGISMap
をインスタンス化します。main.dart
class _MainAppState extends State<MainApp> {
final _mapViewController = ArcGISMapView.createController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: ArcGISMapView(
controllerProvider: () => _mapViewController,
onMapViewReady: onMapViewReady,
),
),
],
),
);
}
void onMapViewReady() {
//追加開始
final basemapStyleParams = BasemapStyleParameters();
basemapStyleParams.specificLanguage = "ja"; //ベースマップの言語を日本語に設定
final basemap = Basemap.withStyle(BasemapStyle.arcGISTopographic, parameters: basemapStyleParams); //ベースマップに設定を適用
final map = ArcGISMap.withBasemap(basemap); //設定したベースマップでマップを生成
//追加終了
}
}
ArcGIS マップ ビュー コントローラーの arcGISMap
プロパティーを map
に設定します。 さらに、setViewpoint()
を呼び出して、富士山にズームします。
main.dart
class _MainAppState extends State<MainApp> {
final _mapViewController = ArcGISMapView.createController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: ArcGISMapView(
controllerProvider: () => _mapViewController,
onMapViewReady: onMapViewReady,
),
),
],
),
);
}
void onMapViewReady() {
final basemapStyleParams = BasemapStyleParameters();
basemapStyleParams.specificLanguage = "ja"; //ベースマップの言語を日本語に設定
final basemap = Basemap.withStyle(BasemapStyle.arcGISTopographic, parameters: basemapStyleParams); //ベースマップに設定を適用
final map = ArcGISMap.withBasemap(basemap); //設定したベースマップでマップを生成
//追加開始
_mapViewController.arcGISMap = map;
_mapViewController.setViewpoint(
Viewpoint.withLatLongScale(
latitude: 35.360626,
longitude: 138.727363,
scale: 200000.0,
),
);
//追加終了
}
}
完成版のプロジェクトはこちらからダウンロードできます(マップの表示場所は本チュートリアルで設定した場所とは異なります)。
プロジェクト ソリューションをダウンロードした場合は、以下の手順に従ってアプリケーションを実行します。
VS Code で展開したプロジェクトを開きます。
VS Code のターミナルで、以下のコマンドを実行します。
flutter pub upgrade
以下のコマンドを実行します。
dart run arcgis_maps install
アクセス トークンを取得し、ソース コード ファイルに API キーを設定します。
Android エミュレーター、iOS シミュレーター、または物理デバイスが設定され、実行されていることを確認します。
VS Code で、[Run] > [Run Without Debugging] を選択します。
「Web マップの作成」のガイドで Web マップを作成している場合は、作成した Web マップも基本的に同じステップで表示できます。
マップを表示するのステップで作成したプロジェクトの main.dart
を開き、onMapViewReady()
を下記のように書き換えます。
main.dart
void onMapViewReady() {
//アイテム ID を使用して、Web マップをポータル アイテムとして取得します。
final portalItem = PortalItem.withPortalAndItemId(
portal: Portal.arcGISOnline(),
itemId: "Web マップの ID",
);
//ポータル アイテムからマップを作成します。
final map = ArcGISMap.withItem(portalItem);
_mapViewController.arcGISMap = map;
}
アプリの動作が確認できたら ArcGIS の セキュリティーと認証について学びましょう!