Posted at

[Flutter] Geolocatorを使用して現在位置情報を取得する方法


概要

Flutterを運用して5ヶ月が経ちました。

3ヶ月前から弊社ではFlutterが普及しだし、エンジニア4人が全てFlutterをかけるようになってきました。現在は自社アプリの新機能追加とアーキテクチャの導入を頑張っているという感じです。

今回は自社アプリで位置情報を取得する必要があったので、何かライブラリないかなと調べてみたら良さげなものがあったのと、導入にちょっと時間がかかったのと、単純に現在位置だけを返すだけのソースコードがあまりなかったのでその共有をします。


今回やること

iOS実機で現在位置情報を 緯度(Latitude) 経度(Longitude) で取得する(Androidはライブラリ通りでうまくいくので特に記載はしない)


環境


iPhone/iOS

iPhone XR 12.4


Flutter

Flutter 1.9.1

Dart 2.3.0


ライブラリ

geolocator 5.1.3


導入


1. pubspec.yaml に記載してpub get

お約束ですね


pudspec.yaml

 dependencies:

geolocator: ^5.1.3


2. ios/Runner/info.plist にpermissionを記載する

iOS doesn't ask for Location permissionsで記載されているエラーが発生しているので、どうも info.plist に記載する必要があるっぽいので以下のように編集します。


info.plist

...

<dict>
<key>NSLocationAlwaysUsageDescription</key>
<string>Your location is required for this app</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your location is required for this app</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Your location is required for this app</string>
...
</dict>


3. 実装してみる


location.dart

import 'package:flutter/material.dart';

import 'package:geolocator/geolocator.dart';

class LocationSample extends StatefulWidget{
@override
_LocationSampleState createState() => _LocationSampleState();
}

class _LocationSampleState extends State<LocationSample> {
// Location
Position position; // Geolocator

@override
void initState() {
super.initState();
_getLocation(context);
}

Future<void> _getLocation(context) async {
Position _currentPosition = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); // ここで精度を「high」に指定している
print(_currentPosition);
setState(() {
position = _currentPosition;
});
}

@override
Widget build(BuildContext context) {
return FutureBuilder<GeolocationStatus>(
future: Geolocator().checkGeolocationPermissionStatus(),
builder:
(BuildContext context, AsyncSnapshot<GeolocationStatus> snapshot) {
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}

if (snapshot.data == GeolocationStatus.denied) {
return Text(
'Access to location denied',
textAlign: TextAlign.center,
);
}

return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
"Location Infomation",
style: TextStyle(
fontSize: 20.0
),
),
Text("Your Current Location is :"),
Text("${position}")
],
),
);
}
);
}
}



4. 結果


  • Permission

最初にiOSの位置情報のPermissionの処理が走ります。とりあえず「このAppの使用中のみ許可」を選択しましょう。


  • Loading

許可を選択すると、位置情報の取得に数秒時間がかかります。ここではnull値が入ってきています。


  • Current Location

数秒後、無事現在位置が取得し、null値がLat(Latitude)とLong(Longitude)に書き換わりました。(表示されているのはオフィス周辺の情報)

その後、数秒後ごとに現在位置を取得し、返してくれるようになりました。

ライブラリを見ると取得できている緯度経度は double 型なので、適宜 String に加工して使えそうです。

ソースコードは以下にあります。自分の勉強も兼ねて、これから実装するコード反映させるアプリケーションを作りました。

今後はこちらに更新されていく予定です。

https://github.com/cheapthrillandwine/i-am-learning-flutter


補足

位置情報を取得できるライブラリはこの他に locationというのもあります。

ここでの導入の方法を見ると info.plist に Permissionを記載する記述があるので、geolocator同様に位置情報を取得するためには必須の記述のようです。

ネイティブエンジニアの方だったら常識なのかも知れないのですが、自分は初めて知りました。

まだこのライブラリを使いこなしている訳ではないので、位置情報に関してはもっと掘り下げて行きたいと思います。

あと、位置情報の精度に関しても選択ができるので、試してみるのも面白いかと思います。


精度

Android
iOS

lowest
500m
3000m

low
500m
1000m

medium
100 - 500m
100m

high
0 - 100m
10m

best
0 - 100m
~0m

bestForNavigation
0 - 100m
Optimized for navigation