📘

【Flutter】GoogleMapの表示からgeolocatorで現在地を取得まで

2022/03/28に公開

概要

  1. GoogleMapの表示
  2. 現在地の取得及び表示

GoogleMapの表示

Google Cloud Platformでプロジェクトを作成する

GoogleCloudPlatformでプロジェクトを作成します。今回はプロジェクト名をgoogle map sampleにしてるよん
Google Cloud Platform

Maps SDK for iOS/Android API を有効にする

  1. APIとサービスのライブラリをクリック

  2. mapと検索すると Maps SDK for iOS  Maps SDK for Androidを発見じゃ

  3. Maps SDK for iOS/Androidを有効にするゾ!

  4. 有効なAPIの欄にそれぞれ表示されていたらOK!

APIキーを発行する

  1. APIとサービス>認証情報で「認証情報を作成」からAPIキーを発行する

  2. 発行したAPIキーをこの後に使用していくよ〜ん

パッケージをインストール

https://pub.dev/packages/google_maps_flutter

google_maps_flutterpubspec.yamlに記述しpub get!

dependencies:
  google_maps_flutter: ^2.1.3

Androidの設定

1. android/app/build.gradle 内の minSdkVersionを20以上に設定する

android {
    defaultConfig {
        minSdkVersion 20
    }
}

2. 先ほど取得したAPIキーをandroid/app/src/main/AndroidManifest.xmlに設定する

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

YOUR KEY HEREの部分に先ほど取得したAPIキーを設定する

Androidのエミュレータの注意点

https://zenn.dev/wakanao/articles/9ed5be61d25419
↑Androidのエミュレータで表示されずに沼りました。

iOSの設定

  1. APIキーをios/Runner/AppDelegate.swiftに設定する
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)
  }
}

YOUR KEY HEREにAPIキーを設定する

サンプルコードで動かしてみる

GoogleMapを表示するだけの最小構成

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Google Maps Demo',
      home: MapSample(),
    );
  }
}

class MapSample extends StatefulWidget {
  const MapSample({Key? key}) : super(key: key);

  
  State<MapSample> createState() => MapSampleState();
}

class MapSampleState extends State<MapSample> {
  late GoogleMapController _controller;
    //初期位置
  final CameraPosition _kGooglePlex = const CameraPosition(
    target: LatLng(43.0686606, 141.3485613),
    zoom: 14,
  );

  
  Widget build(BuildContext context) {
    return GoogleMap(
      mapType: MapType.normal,
      initialCameraPosition: _kGooglePlex,
      onMapCreated: (GoogleMapController controller) {
        _controller = controller;
      },
    );
  }
}

iOS Android
iOS Android

iOS、Android両方表示できていればOK! ちなみに座標は札幌です!いいとこだよ

現在地の表示

location vs geolocator

現在地取得のパッケージとしてlocationgeolocatorの2つが挙げられます。この2つを比較してみます!

location geolocator
Star数(2022/3/27時点) 868 955

どちらでもできること

  • デバイスの現在位置を取得
  • 継続的な位置情報の更新
  • 位置情報が有効になっているかどうかの確認
  • 位置情報の許可のリクエスト

locationでできること

  • backgroundで位置情報を受け取ることができる(geolocatorも8.2.0からできるようになったかも)

geolocatorでできること

  • 最後に確認した位置を取得
  • 2つの座標間の距離計算
  • 2つの座標間の方位を計算
  • 8.2.0からbackgroundで位置情報を受け取れるっぽい

次回以降の記事で2つの座標間の距離計算を使いたいのでgeolocatorを使っていくよん

geolocatorで現在位置の取得を実装

pubspec.yaml
dependencies:
  geolocator: ^8.2.0

pub get!!

iOSの設定

iOS/Runner/Info.plistに以下を追加

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>

Androidの設定

ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATIONのいずれかをandroid/app/src/main/AndroidManifest.xmlに追加する。
両方設定した場合はACCESS_FINE_LOCATIONが使用されるようです。

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

FlutterのGeoLocationで位置情報を取ってみるの記事によると

位置情報に関する権限には、ACCESS_FILE_LOCATIONとACCESS_COARSE_LOCATIONがありますが、前者が詳細な位置。後者が大まかな位置情報となり、このパッケージでは、後者だと動かない場合があるようなので、詳細な位置情報を取得できる権限を要求しています。

とあるのでACCESS_FINE_LOCATIONを使用するのが無難かもしれないですね。

エミュレータの位置情報を設定

iOS

iOSはFeatures/Location/Custom Locationで現在位置を設定できます!!
iOS

Android

エミュレータの右下の・・・をタップ→Locationから位置情報を設定
Android

実装

main.dart
import 'dart:async';

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Google Maps Demo',
      home: MapSample(),
    );
  }
}

class MapSample extends StatefulWidget {
  const MapSample({Key? key}) : super(key: key);

  
  State<MapSample> createState() => MapSampleState();
}

class MapSampleState extends State<MapSample> {
  Position? currentPosition;
  late GoogleMapController _controller;
  late StreamSubscription<Position> positionStream;
  //初期位置
  final CameraPosition _kGooglePlex = const CameraPosition(
    target: LatLng(43.0686606, 141.3485613),
    zoom: 14,
  );

  final LocationSettings locationSettings = const LocationSettings(
    accuracy: LocationAccuracy.high, //正確性:highはAndroid(0-100m),iOS(10m)
    distanceFilter: 100,
  );

  
  void initState() {
    super.initState();

    //位置情報が許可されていない時に許可をリクエストする
    Future(() async {
      LocationPermission permission = await Geolocator.checkPermission();
      if(permission == LocationPermission.denied){
        await Geolocator.requestPermission();
      }
    });

    //現在位置を更新し続ける
    positionStream =
        Geolocator.getPositionStream(locationSettings: locationSettings)
            .listen((Position? position) {
      currentPosition = position;
      print(position == null
          ? 'Unknown'
          : '${position.latitude.toString()}, ${position.longitude.toString()}');
    });
  }

  
  Widget build(BuildContext context) {
    return GoogleMap(
      mapType: MapType.normal,
      initialCameraPosition: _kGooglePlex,
      myLocationEnabled: true,//現在位置をマップ上に表示
      onMapCreated: (GoogleMapController controller) {
        _controller = controller;
      },
    );
  }
}

iOS Android
iOS Android

現在位置が表示されていれば成功!!

まとめ

本記事ではGoogleMapの表示からgeolocatorによる現在位置の取得まで行いました!
次の記事ではGoogleMap+カードのUI作成,geoflutterfireについての紹介を行います!

Discussion