💭

【Flutter】GPSの正確な位置情報がOFFの場合での出来事

に公開

正確な位置情報がOFFの場合

android12&iOS14以降にGPSの設定で「正確な位置情報」の選択が可能になりました。
その際に、正確な位置情報をOFFにしたい場合、位置情報が取得できないエラーが発生しました。

位置情報取得で利用していたのは下記のパッケージになります。
https://pub.dev/packages/location

何が起きたのか?

正確な位置情報をoffにした場合に、位置情報を取得できなくなる現象が発生。。。
取得時の処理が終わらずずっと画面がローディング状態。。。

なんぞなんぞと色々調べていたら、現在地取得に時間がかかっているっぽい。

下記コードが位置情報を取得する際に使用しているclassの簡易版です。
getPositionメソッドの部分で非同期処理をしているのだが、ここが問題点だと推測。
(それ以外に考えられなかった。ちなみにonの場合は問題なく取得可能)

/// 位置情報サービス
class LocationPermission {
 /////// 以上省略
 /// 現在位置を取得
 /// 取得できない場合はnullを返す
  static Future<LocationData?> getPosition(
    Location location,
  ) async {
    // 現在地許可状態確認
    final permissionStatus = await _isPermissionStatusGranted(
      location,
    );

    if (permissionStatus.isGranted) {
      final position = await location.getLocation(); /// 問題点
      return position;
    }
    return null;
  }
    //////// 以下省略 
}

実際にパッケージのgetLocationは下記の様になっている。
返り値がLocationDataを返しておりnullではない。

 
  Future<LocationData> getLocation() async {
    return LocationPlatform.instance.getLocation();
  }

何が言いたいかと言うと、

要は、正確な位置情報がOFFでも返り値決まってるし絶対に位置情報返したるからね!!!と頑張ってくれてるけど一向に取得ができなくて非同期処理が終わらない状態になっているのではないかと。。。

offにするとGPS取得時の判断材料が少なるなるよとも記載ありました。
https://support.google.com/android/answer/3467281?hl=ja#zippy=%2C位置情報の精度-がオフの場合

制度を下げればいいんじゃないの

現在地取得の制度をさげればいいんじゃないの?と思いましたし、パッケージには下記の様にチェンジメソッドがありました。ただこれだと正確な位置情報のon/offの判断ができなくないか?と思い下記は導入断念。

 
  Future<bool> changeSettings({
    LocationAccuracy? accuracy = LocationAccuracy.high,
    int? interval = 1000,
    double? distanceFilter = 0,
  }) {
    return LocationPlatform.instance.changeSettings(
      accuracy: accuracy,
      interval: interval,
      distanceFilter: distanceFilter,
    );
  }

今回の解決策

パッケージを下記に変更
https://pub.dev/packages/geolocator

geolocaterパッケージを利用する点として【「正確な位置情報のon/OFF」判断ができるから】です。
下記の様にクラスを作成しました(簡易版で省略しています)

class GeoLocationPermission {
  /// 以上省略
  /// 位置情報
  static Future<Position?> getGeoPosition() async {
    final allow = await isPermissionStatus();
    // 拒否の場合はすぐnullで返す
    if (allow == LocationPermission.denied) {
      return null;
    }
    /// 正確な位置情報か否か
    final isApproximated = await isApproximateLocation();

    if (allow == LocationPermission.always ||
        allow == LocationPermission.whileInUse) {
      /// 曖昧で取得
      if (isApproximated) {
        return Geolocator.getCurrentPosition(
          locationSettings: const LocationSettings(
            accuracy: LocationAccuracy.low,
          ),
        );
      }
      return Geolocator.getCurrentPosition();
    }
    return null;
  }

  /// 正確な位置情報設定 
  static Future<bool> isApproximateLocation() async {
    final status = await Geolocator.getLocationAccuracy();
    if (status == LocationAccuracyStatus.reduced) {
      // Approximate (あいまい)
      return true;
    } else if (status == LocationAccuracyStatus.precise) {
      // Precise (正確な位置)
      return false;
    } else {
      // Unknown or not supported
      return false;
    }
  }
}

重要なのがisApproximateLocationメソッドです。これを導入した際にandroid端末で正確な位置情報をoffにした際に、しっかりと判断できるようになりました。

これで正確な位置情報OFFの場合は、精度を下げて位置情報を取得すればOKや!っておもったのですが、、、、

けっこう位置情報取れるときと取れないときがあり、不安定だなと。。。

ですので結局正確な位置情報がOFFの際は、ONにしてくださいとモーダル表示して設定変更を促すようにしました。

位置情報が取得できずに待ち時間が多くなると、ユーザー体験が著しく落ちてしまうので正確な位置情報がONを推奨にしておくべきかなとおもった次第です。

でもその判断が出来るのがgeoLocaterのいいところかなと!

以上!!!!

Discussion