Flutter

【Flutter】Google Maps APIを使用した地図表示について簡単にまとめてみる

Flutter

こんにちは。

今回はGoogle Maps APIを使用して、Flutterアプリ内にGoogleマップを表示する方法についてまとめたいと思います。FlutterにはGoogle Mapのプラグインがあり、そのプラグインを使用することで簡単にマップ表示することができます。

0. (事前準備)Google MapのAPIキー取得

まずはこちらからGoogle MapのAPIキーを取得します。

Google Map APIキー取得

毎月200ドル分であれば無料でGoogle Maps APIを使用することができます。

Google Maps Platform では、マップ、ルート、プレイスで使用できる 200 ドル分のクレジットが毎月付与されます(請求先アカウントのクレジットをご覧ください)。1 か月あたり 200 ドル分のクレジットがあれば、お客様によってはこれらのサービスを無料でご利用いただけます。1 か月の使用量が 200 ドル分を超えるまで課金されることはありません。

参考: 料金プランとAPIの費用

GoogleMapAPIクレジット

1. 新規アプリケーションの作成

Flutterの新規アプリケーションを立ち上げます。

% flutter create google_maps_in_flutter
% cd google_maps_in_flutter
% flutter run
  • Dartバージョン: 3.5.4
  • Flutterバージョン: 3.24.4
  • アプリケーション名: google_maps_in_flutter

2. Google Mapのプラグイン導入

Pubコマンドを使用して、Google Mapのプラグインである「google_maps_flutter」をインストールします。

% flutter pub add google_maps_flutter

Pubパッケージとは、DartおよびFlutterプロジェクトで使用できるライブラリやツールのことです。DartとFlutterのエコシステムには、パッケージ管理システムであるPubがあり、これを利用してパッケージをインストールしたり、依存関係を管理したりします。

3. Android側の設定

3-1. Android SDKのバージョン設定

android/app/build.gradleにAndroid SDKの最小バージョンを設定します。

この数値を20に設定することで、Android SDK 20(Android 4.4W)以上のバージョンを搭載している端末でのみアプリが動作するようになります。

android {
    defaultConfig {
        minSdkVersion 20
    }
}

3-2. APIキーの設置

Goodle Maps APIのキーをandroid/app/src/main/AndroidManifest.xmlに設置します。手元で動作確認するのみであれば、「YOUR KEY HERE」に直接キーを貼り付けても良いですが、Githubにプッシュしてしまうリスクを考慮し、ここではgradle.propertiesbuild.gradle を利用して、AndroidManifest.xmlにキーを渡すようにします。

<manifest ...
  <application ...
    <meta-data android:name="com.google.android.geo.API_KEY"
               android:value="YOUR KEY HERE"/>

3-2-1. gradle.properties にAPIキーを設定

gradle.propertiesにGoogle Maps APIのキーを設定します。

# Google Maps API Key
GOOGLE_MAPS_API_KEY=<Google Maps APIキー>

gradle.propertiesは、Gradleビルドシステムに関する設定を記述するためのファイルで、Androidプロジェクトではビルド設定や環境変数、メモリ設定、カスタムプロパティなどを指定するために使用されます。

gradle.propertiesに定義したプロパティは、build.gradle内で${プロパティ名}で参照できます。

3-2-2. .gitignoreに追加

APキーを定義したgradle.propertiesandroid/.gitignoreに追加します。

# APIキー等を設定するファイル
gradle.properties

3-2-3. build.gradlegradle.propertiesの値を読み込む

build.gradleを開き、以下の記述を追記します。

android {
    defaultConfig {
        manifestPlaceholders = [
            GOOGLE_MAPS_API_KEY: "${GOOGLE_MAPS_API_KEY}"
    ]
}

manifestPlaceholdersはAndroidのビルドシステムでAndroidManifest.xml内で使用するプレースホルダー(変数)に値を割り当てるための機能です。AndroidManifest.xmlの再利用性やセキュリティを向上させるために、プレースホルダーを使うことで、コード内にハードコーディングしない設計を実現することができます。

3-2-4. AndroidManifest.xmlの修正

AndroidManifest.xml<application>タグ内に以下の<meta-data>タグを追加します。これにより、Google Maps APIキーがビルド時に動的に設定されるようになります。

<manifest ...
  <application ...
    <meta-data android:name="com.google.android.geo.API_KEY"
               android:value="YOUR KEY HERE"/>

4. iOS側の設定

Goodle Maps APIのキーをios/Runner/AppDelegate.swiftに設置します。こちらもAndroid同様、手元で動作確認するのみであれば、「YOUR KEY HERE」に直接キーを貼り付けても良いですが、Githubにプッシュしてしまうリスクを考慮し、ここでは.plistファイルを利用して、ios/Runner/AppDelegate.swiftにキーを渡すようにします。

import UIKit
import Flutter
import GoogleMaps

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GMSServices.provideAPIKey("YOUR KEY HERE")
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

4-1. Config.plistファイルの作成

APIキーを保管するConfig.plistを作成します。

% touch ios/Runner/Config.plist

4-2. APIキーの保管

先ほど作成したConfig.plistにAPIキーを保管する記述を追加します。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>GoogleMapsAPIKey</key>
    <string><Google Maps APIキー></string>
</dict>
</plist>

4-3. .gitignoreに追加

Config.plistios/.gitignoreに追加します。

# APIキー等を設定するファイル
Runner/Config.plist

4-4. ios/Runner/AppDelegate.swiftの修正

Config.plist からAPIキーを読み込み、Google Mapsに渡します。

import UIKit
import Flutter
import GoogleMaps

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    if let path = Bundle.main.path(forResource: "Config", ofType: "plist"),
       let config = NSDictionary(contentsOfFile: path),
       let apiKey = config["GoogleMapsAPIKey"] as? String {
        GMSServices.provideAPIKey(apiKey)
    }
    
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}
  • Bundle.main: アプリケーションのリソース(ファイルなど)にアクセスするためのオブジェクト
  • path(forResource:ofType:): Config.plistファイルのパスを取得。Config.plistファイルが見つかるとそのファイルのパスが返され、見つからない場合はnilが返される
  • NSDictionary(contentsOfFile: path): pathに基づいてConfig.plistファイルの内容を読み込み、キーと値のペアで構成される辞書オブジェクト(NSDictionary)として取得。Config.plistファイルが正しい形式であれば辞書が返されるが、ファイルが見つからない場合や内容が不正な場合はnilが返される
  • config["GoogleMapsAPIKey"] as? String: 読み込んだ辞書configから、"GoogleMapsAPIKey"キーに対応する値を取得し、文字列として apiKeyに代入。as? Stringは型キャストの一種で、GoogleMapsAPIKeyの値が文字列型ならその値が返され、不正な型であればnilが返される

5. サンプルコードの配置

ドキュメントに記載のサンプルコードmain.dartに配置します。

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

void main() => runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late GoogleMapController mapController;

  final LatLng _center = const LatLng(45.521563, -122.677433);

  void _onMapCreated(GoogleMapController controller) {
    mapController = controller;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: GoogleMap(
          onMapCreated: _onMapCreated,
          initialCameraPosition: CameraPosition(
            target: _center,
            zoom: 11.0,
          ),
        ),
      ),
    );
  }
}

6. Flutterの起動

% flutter run

iOSでシミュレータを起動する場合、以下のようなエラーが出る可能性があります。このエラーメッセージは、google_maps_flutter_ios が iOS 14.0 以上を要求しているのに対して、Podfile の設定が iOS 12.0 に自動設定されていることが原因です。

Error output from CocoaPods:
↳

    [!] Automatically assigning platform `iOS` with version `12.0` on target `Runner` because no
    platform was specified. Please specify a platform for this target in your Podfile. See
    `https://guides.cocoapods.org/syntax/podfile.html#platform`.

Error: The plugin "google_maps_flutter_ios" requires a higher minimum iOS deployment version than your
application is targeting.
To build, increase your application's deployment target to at least 14.0 as described at
https://flutter.dev/to/ios-deploy
Error running pod install
Error launching application on iPhone 16 Plus.

 

以下のようにios/Podfile を開き、platform :ios, '14.0' を指定するように修正しましょう。

platform :ios, '14.0'

7. 挙動確認

Android
Androidビュー
iPhone
iPhoneビュー

参考

 

今回はGoogle Maps APIを使用して、Flutterアプリケーション内に地図表示する方法について簡単にまとめてみました。今後はアイコンを地図上に表示したり、地図のテイストを変えてみたりと色々とカスタマイズしてみようと思います。