🤖

【Flutter】スマホの位置情報を取得するやり方

2022/03/01に公開

Flutterのアプリ開発で位置情報の取得が必要だったので実装してみました。
自分のメモ代わりに残しておきます。
何かご指摘があればお気軽にコメントにどうぞ!

使用する環境

  • Android Studio Arctic Fox | 2020.3.1 Patch 4
  • macOS Monterey version12.1
  • 使用パッケージ

1. パッケージのインストール

下記サイトからパッケージを二つインストールします。
https://pub.dev/packages/geolocator
https://pub.dev/packages/geocoding

2. Androidの権限設定

2-1. Android SDKバージョンを31に設定

android / app /build.gradleファイルを開き、

build.gradle
 android {
+  compileSdkVersion 31 // <= ここの値が31になっているか確認
 ...
     defaultConfig {
         // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
         applicationId "com.example.insta_clone"
         minSdkVersion 21
+        targetSdkVersion 31 // <= ここの値も同様に31にしないとエラーが出る
         versionCode flutterVersionCode.toInteger()
         versionName flutterVersionName
     }
 ...

2-2. AndroidManifest.xmlファイルの編集

android/app/src/main/AndroidManifest.xmlファイルを下記のように編集します

AndroidManifest.xml
...
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    
    <application
...

3. iOSの権限設定(Macのみ)

3-1. info.plistファイルの編集

ios/Runner/Info.plistファイルを編集。

info.plist
...
+    <!-- geolocator Section -->
+    <key>NSLocationWhenInUseUsageDescription</key>
+    <string>Required to post location information when posting photos and videos.</string>
+    <key>NSLocationAlwaysUsageDescription</key>
+    <string>Required to post location information when posting photos and videos.</string>
+    <!-- End of the geolocator Section -->
 
 </dict>
 </plist>

4. 位置情報の取得

4-1 位置情報を取得する

下記のコードでは

  1. ユーザーに位置情報サービスを利用しても良いか促す
  2. 許可された場合に位置情報を取得する

という二つの処理をしております。

position.dart
import 'package:geolocator/geolocator.dart';

/// デバイスの現在位置を決定する。
/// 位置情報サービスが有効でない場合、または許可されていない場合。
/// エラーを返します
Future<Position> _determinePosition() async {
  bool serviceEnabled;
  LocationPermission permission;

  // 位置情報サービスが有効かどうかをテストします。
  serviceEnabled = await Geolocator.isLocationServiceEnabled();
  if (!serviceEnabled) {
    // 位置情報サービスが有効でない場合、続行できません。
    // 位置情報にアクセスし、ユーザーに対して 
    // 位置情報サービスを有効にするようアプリに要請する。
    return Future.error('Location services are disabled.');
  }

  permission = await Geolocator.checkPermission();
  if (permission == LocationPermission.denied) {
    // ユーザーに位置情報を許可してもらうよう促す
    permission = await Geolocator.requestPermission();
    if (permission == LocationPermission.denied) {
      // 拒否された場合エラーを返す
      return Future.error('Location permissions are denied');
    }
  }
  
  // 永久に拒否されている場合のエラーを返す
  if (permission == LocationPermission.deniedForever) {
    return Future.error(
      'Location permissions are permanently denied, we cannot request permissions.');
  } 

  // ここまでたどり着くと、位置情報に対しての権限が許可されているということなので
  // デバイスの位置情報を返す。
  return await Geolocator.getCurrentPosition();
}

4-1. 取得した位置情報から具体的な「国」などの情報を取り出す

この処理をするために2番目のパッケージgeocodingが必要です。

position.dart
import 'package:geocoding/geocoding.dart' as geoCoding;
import 'package:geolocator/geolocator.dart';
... // 先ほどの続き

- return await Geolocator.getCurrentPosition();
+ final position = await Geolocator.getCurrentPosition();

// 取得した位置情報の経度と緯度を使い、詳細情報を取り出す
+ final placeMarks = await geoCoding.placemarkFromCoordinates(position.latitude, position.longitude);

// 上記のplaceMarksは配列で帰ってくるので一つだけ取り出す
+ final placeMark = placeMarks[0],

// 出力してみる
+ print(placeMark.country); // 国が取得できます
+ print(placeMark.administrativeArea); // 県が取得できます(日本の場合)
+ print(placeMark.locality); // 市が取得できます(日本の場合)

終わり

今回はgeolocatorgeocodingの2つのパッケージを利用して、位置情報や国名などの詳細情報を取得してみました。
Android、iOSそれぞれに権限の設定をしたり、ユーザーに権限の許可をしてもらうように促したりと意外とやることが多かった気がします。
今回は紹介していませんが、geolocatorパッケージの中のgetCurrentPostionで緯度、経度を取得する際にLocationAccuracyというプロパティで位置情報の精度を変えたりできます。
もちろん精度を上げれば、位置情報取得までに時間がかかりますので、アプリの特徴によってこの辺りの設定も変更するべきだと思いました。
以上です。

Discussion