Flutter
出典:ArcGIS Maps SDK for Flutter - Tutorials - Display a map
マップを表示する
このチュートリアルでは ArcGIS Maps SDK for Flutter を使用して、マップとベースマップ レイヤーを表示する方法を紹介します。

マップには、地理データのレイヤーが含まれています。マップには、ベースマップ レイヤーと、オプションで 1 つ以上のデータ レイヤーを追加できます。
このチュートリアルでは、地形図ベースマップ レイヤーを使用して、富士山付近を表示する地図を作成します。
Flutter 3.44.x に関する注意事項と依存関係の要件につきましては、こちらをご覧ください。
前提条件
このチュートリアルを実施するには、以下が必要です。
- API キーにアクセスするための ArcGIS 開発者アカウント。アカウントをお持ちでない場合は、サインアップ(無料)してください。アカウントの作成方法は「開発者アカウントの作成」をご覧ください。
- 開発環境がシステム要件を満たしていることを確認します。
- Flutter 用の IDE。VS Code を推奨しています。
認証の設定
このチュートリアルで使用するセキュアな ArcGIS ロケーション サービスにアクセスするには、ArcGIS Location Platform または ArcGIS Online アカウントを使用して、API キー認証を実装する必要があります。
- ユーザーはサインインする必要がありません。
- 適切な権限を持つ API キーの認証情報を作成する必要があります。
- API キーは長期間のアクセス トークンです。
- サービス使用料は、API キーの所有者/開発者に請求されます。
- 実装が最も簡単な認証方法です。
- 新規の ArcGIS 開発者に推奨される方法です。
詳しくは API キー認証をご覧ください。
このチュートリアルで使用するセキュアなリソースにアクセスする権限を持つ、新しい API キーのアクセス トークンを作成します。
- API キーの作成のチュートリアルを完了し、以下の権限を持つ API キーを作成します。
- Privileges
- Location services > Basemaps
- Privileges
- API キーのアクセス トークン をコピーし、安全な場所に貼り付けます。これは後のステップで使用します。
- ユーザーは、ArcGIS アカウントでサインインする必要があります。
- ユーザー アカウントには、アプリケーションで使用する ArcGIS サービスにアクセスする権限が必要です。
- OAuth 認証情報の作成が必要です。
- アプリケーションには、リダイレクト URL とクライアント ID を使用します。
- サービスの使用料は、アプリケーションにサインインしたユーザーの組織に請求されます。
詳しくは、ユーザー認証をご覧ください。
このチュートリアルで使用するセキュアなリソースにアクセスするための新しい OAuth 認証情報を作成します。
ユーザー認証用の OAuth 認証情報を作成するチュートリアルを完了し、Client ID と Redirect URL を取得してください。
Client IDは、認証サーバー上でアプリを一意に識別するものです。サーバーが指定された Client ID を持つアプリを見つけられない場合、認証は続行されません。Redirect URL(Callback URL とも呼ばれます)は、OAuth ログイン後にシステムが制御をアプリに戻す際、認証サーバーからの応答を識別するために使用されます。Redirect URL は、必ずしもユーザーが移動できる有効なエンドポイントを表すわけではないため、my-app://authのようなカスタム スキームを使用できます。アプリのコードで使用される Redirect URL が、認証サーバーで設定された Redirect URL と一致していることを確認することが重要です。ClientID と Redirect URL をコピーして安全な場所に貼り付けます。これらは後のステップで使用します。
このアプリケーションにアクセスするすべてのユーザーには、ベースマップ スタイル サービスにアクセスするためのアカウント権限が必要です。
開発またはダウンロード
このチュートリアルを完了するには、2 つの選択肢があります。
オプション 1: コードを開発する
新しい Flutter アプリを作成する
- VS Code を起動し、ウェルカム タブで [Open…] を選択します。プロジェクトを保存したい場所を選択してください。
- [View]>[Terminal] に移動してください。
- ターミナル ウィンドウで、次のコマンドを実行して display_a_map という名前の新しい Flutter アプリを作成します。必要なターゲット プラットフォームと、組織名 com.example.app を設定してください。
flutter create -e display_a_map --platforms ios,android --org com.example.app
テンプレート コードをリファクタリングする
ArcGIS Maps SDK for Flutter を使用する際、データの変更に応じて UI を更新するなど、アプリケーションの状態を更新する必要が生じることはよくあります。アプリがこうした処理に対応できるよう、ステートフル ウィジェットを実装します。
ステートレスなウィジェットの実装を使用して地図を表示することも可能です。詳細は Display map サンプルを参照してください。
- VS Code で、lib/main.dart を開きます。
main()関数内で、runApp()内にMaterialAppをインスタンス化し、名前付き引数homeにMainAppのインスタンスを設定します。void main() { runApp( const MaterialApp(home: MainApp()), //変更 ); }- テンプレートの
MainAppクラスの定義を、StatefulWidgetを継承するようにリファクタリングします。StatelessWidgetキーワードにマウスを合わせ、右クリックして [Refactor…] を選択し、[Convert to StatefulWidget] を選んでコードをリファクタリングします。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の build メソッド内で返されているMaterialAppウィジェットを削除してください。このコードは Flutter の作成テンプレートによって生成されたものであり、後の手順で、マップを含むウィジェットを返すコードに置き換えられます。class _MainAppState extends State<MainApp> { @override Widget build(BuildContext context) { //削除開始 return const MaterialApp( home: Scaffold(body: Center(child: Text('Hello World!'))), ); //削除終了 } }
ArcGIS Maps SDK for Flutter を追加する
arcgis_maps パッケージに依存関係を追加します。
- VS Code のターミナルで、ディレクトリーを新しいプロジェクトに変更します。
cd display_a_map - 以下のコマンドを実行します。
dart pub add arcgis_maps - 以下のコマンドを実行します。
flutter pub upgrade - 最後に、以下のコマンドを実行します。
dart run arcgis_maps install - main.dart に戻ります。
arcgis_mapsパッケージをインポートします。import 'package:arcgis_maps/arcgis_maps.dart';//追加
プラットフォーム固有の構成
Android、iOS、またはその両方のアプリを開発する際、Flutter のツールセットでは、いくつかの設定バージョンに対してデフォルト値が設定されています。これらは、新しいプロジェクトを作成する際にあらかじめ設定されます。以下に示す更新内容は、最新バージョンの ArcGIS Maps SDK for Flutter パッケージを使用してアプリケーションをコンパイルするために、これらのデフォルト設定に変更を加える必要がある点です。詳細については、システム要件のページをご覧ください。
プロジェクトの
android/app/build.gradle.ktsファイルを編集して、最小要件を更新します。build.gradle.ktsdefaultConfig { // 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 = 28 //変更 targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode versionName = flutter.versionName }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 17.0 を最小に設定します。行のコメントを解除し、バージョン番号を更新します。podfile# Uncomment this line to define a global platform for your project platform :ios, '17.0' #変更Runtimecorepod とarcgis_maps_ffipod をRunnerターゲット セクションに追加します。podfiletarget '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 endpod updateを使用して Pods を設定します。cd ios && pod update && cd ..
開発者資格情報を設定する
アプリ ユーザーが ArcGIS の位置情報サービスにアクセスできるようにするには、認証の設定 ステップで作成した開発者資格情報を使用して、リソースへのリクエストを認証します。
API キーのアクセス トークンを ArcGISEnvironment に渡してください。
main.dart に戻ります。
main()関数で、ArcGISEnvironment.apiKey の値をアクセス トークンに設定します。main.dartvoid main() { ArcGISEnvironment.apiKey = ''; // アクセス トークンをここに記入します。 //追加 runApp(const MainApp()); }
Authenticator ツールキット コンポーネントを使用して、OAuth 認証情報を管理してください。
- 手順に従って、アプリに「ArcGIS Maps SDK for Flutter Toolkit」パッケージを追加してください。
_MainAppStateクラス内に final クラスのメンバー変数_oAuthUserConfigurationを定義し、portalUri、clientId、redirectUriの値を指定してOAuthUserConfigurationオブジェクトで初期化してください。main.dartclass _MainAppState extends State<MainApp> { //追加開始 final _oAuthUserConfiguration = OAuthUserConfiguration( portalUri: Uri.parse('https://www.arcgis.com'), clientId: 'YOUR_CLIENT_ID', redirectUri: Uri.parse('YOUR_REDIRECT_URL'), ); //追加終了 @override Widget build(BuildContext context) { } }
- アプリケーションのサインアウト時に、認証情報のストアからすべてのトークンを無効化
Authenticator.revokeOAuthTokens()し、すべての認証情報を消去Authenticator.clearCredentials()するコードを追加してください。アプリケーションのサインアウト時には、アプリの要件に応じて、すべてのトークンを無効化し、認証情報ストアからすべての認証情報を削除することを検討してください。ツールキット コンポーネントを使用する際の詳細については、main.dartclass _MainAppState extends State<MainApp> { final _oAuthUserConfiguration = OAuthUserConfiguration( portalUri: Uri.parse('https://www.arcgis.com'), clientId: 'YOUR_CLIENT_ID', redirectUri: Uri.parse('YOUR_REDIRECT_URL'), ); //追加開始 @override void dispose() { Authenticator.revokeOAuthTokens().whenComplete( Authenticator.clearCredentials, ); super.dispose(); } //追加終了 @override Widget build(BuildContext context) { } }Authenticatorのリファレンスを参照してください。 - Android のみ、ユーザー認証にはシステム ブラウザーが必要です。プロジェクトの Android マニフェストに、以下のアクティビティーを追加してください。android/app/src/main/AndroidManifest.xml
<activity android:name="com.linusu.flutter_web_auth_2.CallbackActivity" android:exported="true"> <intent-filter android:label="flutter_web_auth_2"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="YOUR_CALLBACK_URL_SCHEME_HERE" /> </intent-filter> </activity>YOUR_CALLBACK_URL_SCHEME_HEREを、先ほど認証を設定した際に使用しダイレクト URL のスキームに置き換えてください。これは、ログイン フローが完了した後、ブラウザーがアプリに通信を戻すために必要です。
たとえば、my-app://auth のようなリダイレクト URL がある場合、スキームの値は my-app となります。この値が、アクティビティー内のYOUR_CALLBACK_URL_SCHEME_HEREを置き換えることになります。
マップを追加する
地形図ベースマップ レイヤーを含むマップを作成します。 地図は富士山の付近とします。
_MainAppStateクラスの内部で、final クラス メンバー変数_mapViewControllerを定義し、ArcGISMapViewクラスのcreateController()を呼び出してArcGISMapViewControllerで初期化します。ArcGIS マップ ビュー コントローラーは、
ArcGISMapで定義された 2 次元 (2D) 地理コンテンツを表示するユーザー インターフェース コントロールです。main.dartclass _MainAppState extends State<MainApp> { final _mapViewController = ArcGISMapView.createController(); //追加 @override Widget build(BuildContext context) { } }main.dartclass _MainAppState extends State<MainApp> { final _mapViewController = ArcGISMapView.createController(); //追加 final _oAuthUserConfiguration = OAuthUserConfiguration( portalUri: Uri.parse('https://www.arcgis.com'), clientId: 'YOUR_CLIENT_ID', redirectUri: Uri.parse('YOUR_REDIRECT_URL'), ); @override void dispose() { Authenticator.revokeOAuthTokens().whenComplete( Authenticator.clearCredentials, ); super.dispose(); } @override Widget build(BuildContext context) { } }build メソッド内で
Scaffold、Column、Expandedからなるウィジェット ツリーにArcGISMapViewウィジェットを追加します。マップ ビューの名前付き引数controllerProviderをクラス メンバー変数_mapViewControllerに設定し、onMapViewReady引数を次に定義する引数と同じ名前の新しいメソッドに設定します。Scaffoldウィジェットは基本的なマテリアル デザインのビジュアル レイアウト構造を提供し、Columnウィジェットは子ウィジェットを垂直配列で表示します。ArcGISMapViewウィジェットは、サイズが制限されたウィジェット内でのみ使用できます。 サイズが制限されていない状態で使用すると、アプリケーションは例外をスローします。 たとえば、ArcGISMapViewをColumnウィジェット内で使用すると、サイズが制限されないため、このような例外が発生します。 代わりに、チュートリアルのこのステップで説明するように、ArcGISMapViewをExpandedウィジェットでラップして、適切な境界を提供することができます。main.dartclass _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, ), ), ], ), ); //追加終了 } }build()内で、Scaffold、Column、Expanded、Authenticator、およびArcGISMapViewから構成されるウィジェット ツリーにウィジェットを追加します。authenticator の名前付き引数oAuthUserConfigurationsをクラス メンバー変数_oAuthUserConfigurationに設定し、ArcGISMapViewウィジェットを authenticator の子として配置します。最後に、マップ ビューの名前付き引数controllerProviderをクラスのメンバー変数_mapViewControllerに設定し、onMapViewReady引数を、引数と同じ名前の新しいメソッドに設定します。この新しいメソッドは次に定義します。Scaffoldウィジェットは基本的なマテリアル デザインの視覚的レイアウト構造を提供しますが、Columnウィジェットは子要素を縦方向の配列として表示します。ArcGISMapViewウィジェットは、サイズが制限されたウィジェット内でのみ使用できます。サイズが制限されていないウィジェットで使用すると、アプリケーションで例外が発生します。たとえば、Columnウィジェット内でArcGISMapViewを使用すると、サイズが無制限になるため、このような例外が発生します。代わりに、このチュートリアルのこのステップで示されているように、ArcGISMapViewをExpandedウィジェットでラップして、適切な境界を設定することができます。Authenticatorはウィジェット ツリー内のどこにでも配置できますが、このチュートリアルではArcGISMapViewウィジェットの親として使用するのが最も理にかなっています。main.dartclass _MainAppState extends State<MainApp> { final _mapViewController = ArcGISMapView.createController(); final _oAuthUserConfiguration = OAuthUserConfiguration( portalUri: Uri.parse('https://www.arcgis.com'), clientId: 'YOUR_CLIENT_ID', redirectUri: Uri.parse('YOUR_REDIRECT_URL'), ); @override void dispose() { Authenticator.revokeOAuthTokens().whenComplete( Authenticator.clearCredentials, ); super.dispose(); } @override Widget build(BuildContext context) { //追加開始 return Scaffold( body: Column( children: [ Expanded( child: Authenticator( oAuthUserConfigurations: [_oAuthUserConfiguration], child: ArcGISMapView( controllerProvider: () => _mapViewController, onMapViewReady: onMapViewReady, ), ), ), ], ), ); //追加終了 } }_MainAppState内で、何も返さない新しいメソッドonMapViewReady()を定義してください。main.dart//追加開始 void onMapViewReady() { } //追加終了新しいメソッド内で final 変数
mapを定義し、ArcGIS 地形図ベースマップ スタイルを使用してArcGISMapとして初期化します。main.dartvoid 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.dartvoid onMapViewReady() { final map = ArcGISMap.withBasemapStyle(BasemapStyle.arcGISTopographic); //追加開始 _mapViewController.arcGISMap = map; _mapViewController.setViewpoint( Viewpoint.withLatLongScale( latitude: 35.360626, longitude: 138.727363, scale: 200000.0, ), ); //追加終了 }
アプリを実行する
- Android エミュレーター、iOS シミュレーター、または物理的なデバイスが設定され、実行されていることを確認します。
- VS Codeで、[Run] > [Run Without Debugging] を選択します。
富士山を中心に、地形図のベースマップ レイヤーが表示された地図が表示されます。マップ ビューをピンチ、ドラッグ、またはダブルタップして、地図を閲覧してください。
または、以下の手順に従ってチュートリアル ソリューションをダウンロードすることもできます。
オプション 2: 完成したソリューションをダウンロードする
- こちらをクリックしファイルをダウンロードし、コンピュータ内の任意の場所に解凍してください。
- VS Code で、プロジェクトを開いてください。
ダウンロードしたソリューションには認証情報が含まれていないため、認証の設定 セクションで作成した開発者資格情報を追加する必要があります。
ソリューションに開発者資格情報を設定する
アプリ ユーザーが ArcGIS の位置情報サービスにアクセスできるようにするには、認証の設定 ステップで作成した開発者資格情報を使用して、リソースへのリクエストを認証します。
VS Codeで、lib/main.dart を開きます。
main()関数で、ArcGISEnvironment.apiKeyの値をアクセス トークンに設定します。main.dartvoid main() { ArcGISEnvironment.apiKey = ''; // アクセス トークンをここに記入します。 //追加 runApp(const MainApp()); }
OAuth 認証情報を管理するために、Authenticator ツールキット コンポーネントを追加してください。
以下の手順に従って、アプリに ArcGIS Maps SDK for Flutter Toolkit パッケージを追加してください
main.dart に以下のコードを追加します。
_MainAppStateクラス内に final クラス メンバー変数_oAuthUserConfigurationを定義し、portalUri、clientId、redirectUriの値を渡してOAuthUserConfigurationで初期化します。- アプリケーションのサインアウト時に、認証システムの資格情報ストアからすべてのトークンを無効化(
Authenticator.revokeOAuthTokens())し、すべての資格情報をクリア(Authenticator.clearCredentials())するコードを追加します。 build()内の既存のウィジェット ツリーにおいて、ArcGISMapViewウィジェットの親としてAuthenticatorウィジェットを追加します。名前付きパラメーターoAuthUserConfigurationsの値を、新しいメンバー変数_oAuthUserConfigurationを含むリストに設定します。
main.dartclass _MainAppState extends State<MainApp> { final _mapViewController = ArcGISMapView.createController(); final _oAuthUserConfiguration = OAuthUserConfiguration( portalUri: Uri.parse('https://www.arcgis.com'), clientId: 'YOUR_CLIENT_ID', redirectUri: Uri.parse('YOUR_REDIRECT_URL'), ); @override void dispose() { Authenticator.revokeOAuthTokens().whenComplete( Authenticator.clearCredentials, ); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Column( children: [ Expanded( child: Authenticator( oAuthUserConfigurations: [_oAuthUserConfiguration], child: ArcGISMapView( controllerProvider: () => _mapViewController, onMapViewReady: onMapViewReady, ), ), ), ], ), ); } }
Android のみ、ユーザー認証にはシステム ブラウザーが必要です。プロジェクトの Android マニフェストに、以下のアクティビティーを追加してください。
android/app/src/main/AndroidManifest.xml<!-- ... --> <activity android:name="com.linusu.flutter_web_auth_2.CallbackActivity" android:exported="true"> <intent-filter android:label="flutter_web_auth_2"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="YOUR_CALLBACK_URL_SCHEME_HERE" /> </intent-filter> </activity> <!-- ... -->YOUR_CALLBACK_URL_SCHEME_HEREを、先ほど認証を設定した際に使用したリダイレクト URL のスキームに置き換えてください。これは、ログイン フローが完了した後、ブラウザーがアプリに通信を戻すために必要です。たとえば、my-app://auth のようなリダイレクト URL がある場合、スキームの値は my-app になります。この値が、アクティビティー内の
YOUR_CALLBACK_URL_SCHEME_HEREを置き換えることになります。
アプリを実行する
以下の手順に従ってアプリケーションを実行してください。
VS Codeのターミナルで、次のコマンドを実行してください。
flutter pub upgrade次のコマンドを実行します。
dart run arcgis_maps installAndroid エミュレーター、iOS シミュレーター、または物理的なデバイスが設定され、実行されていることを確認します。
VS Codeで、[Run] > [Run Without Debugging] を選択します。
カリフォルニア州のサンタモニカ山脈を中心に、地形図のベースマップ レイヤーが表示された地図が表示されます。地図ビューをピンチ、ドラッグ、またはダブルタップして、地図を閲覧してください。
アプリの動作が確認できたら ArcGIS の セキュリティーと認証について学びましょう!