【Flutter】バックグラウンドで位置情報を取得しよう

Flutterを使ってバックグラウンドで位置情報を取得したくないですか?

近年、GoogleとAppleの両陣営は、プライバシー電池消費に対応するために、バックグラウンド制限位置情報制限などを、毎年のようにOSアップデートでiOS/AndroidOSに適用しています。

この記事では、まずはその制約の概要を説明した上で、実装方法を解説していきます。

OSの制約を学ぼう

Flutterでモバイルアプリを実装する上で、iOSとAndroidOSの制約を理解することは重要です。

OSSのFlutter位置情報ライブラリを組み込むとしても、このOSの制約を理解していないと、実機の挙動を正確に理解することは困難です。

では、OS別に理解していきましょう

Androidの制約

Androidにもいくつか位置情報関連の制約がありますが、特に重要な制約は下記3点かと思います。

  • バックグラウンドで位置情報にアクセスする場合はPlay Storeの審査が必須化
  • バックグラウンドでは、Doze(居眠り)モードが発動する
  • 位置情報パーミッションダイアログに「常に許可」の選択肢がない

それぞれ説明していきます。

バックグラウンドで位置情報にアクセスする場合はPlay Storeの審査が必須化

バックグラウンドで位置情報にアクセスするものはすべてGoogle Play Console上で承認を受ける必要があります。

2021 年 3 月 29 日から全Androidアプリにこの規約が適用されるので、別記事に審査内容を書いたので、詳細はそちらを参照してください。

バックグラウンドでは、Doze(居眠り)モードが発動する

Dozeモードが発動するとアプリの挙動が極端に制限されます。Dozeとは英語で居眠りの事をさしますが、言葉通りOSが居眠りします。

下図のように、画面をOFFにしてから徐々に深い眠りに入っていきます。

位置情報パーミッションダイアログに「常に許可」の選択肢がない

Android11から、ダイアログから「常に許可」の選択肢がなくなりました。これはユーザのプライバシー保護のためだと言われています。

もしモバイルアプリがバックグラウンドで位置情報を取得したい場合は、ユーザにAndroidOSの設定画面に画面遷移してもらい「常に許可」に変更してもらう必要があります。

さらに詳しい情報が知りたい場合はAndroid公式のレファレンスを参照するのがオススメです。

https://developer.android.com/training/location?hl=ja

iOSの制約

iOSにもいくつか位置情報関連の制約がありますが、特に重要な制約は下記2点かと思います。

  • おおよそ位置情報(つまり正確な位置情報は取れない)
  • 位置情報パーミッションダイアログに「常に許可」の選択肢がない

それぞれ説明していきます。

おおよそ位置情報

iOS14から、ダイアログに「正確な位置情報」オプションが追加されました。

ユーザが、「正確な位置情報」をOFFにした場合(つまり「おおよそ位置情報」を選択した)、地図上のメッシュの代表地点(おおよそ合ってる位置)が通知されます。

これを選択したユーザの位置情報はほとんど役に立たないでしょう。

位置情報パーミッションダイアログに「常に許可」の選択肢がない

iOS13から、ダイアログから「常に許可」の選択肢がなくなりました。これはユーザのプライバシー保護のためだと言われています。

もしモバイルアプリがバックグラウンドで位置情報を取得したい場合は、ユーザにiOSの設定画面に画面遷移してもらい「常に許可」に変更してもらう必要があります。

また頻繁にiOSがバックグラウンドで位置情報を取得していることをユーザに通知するので、このダイアログが鬱陶しいので、ユーザの多くは位置情報をOFFにするように促されます。

この制約があるので、バックグラウンドの取得を自然に行うことはかなり難しくなりました

さらに細かい制約が知りたい場合はAppleの公式ドキュメントを参考にしてみると、細かい情報が得られると思います。

https://developer.apple.com/documentation/corelocation

Flutterの実装を学ぼう

さて、ここからFlutterの実装について考えていきましょう。

基本的には、Nativeの位置情報などの機能を使うためには、プラグインパッケージというFlutterとAndroidやiOSのOSをつなぐエンジン部分を実装する必要があります。

今回は、位置情報のプラグインパッケージを自前で実装するのではなく、OSSのライブラリを使う方法を探ります。

OSSのライブラリを使おう

Githubをみると、Flutter位置情報界隈では、LyokoneのflutterlocationというOSSライブラリが有名のようです。Starが711もついてます。

https://github.com/Lyokone/flutterlocation

Flutterへの組み込み手順はGithubのREADMEを参照していただくと簡単かと思いますが、
https://github.com/Lyokone/flutterlocation/blob/master/README.md

基本的には、下記のコードをpubspec.yamlに追記してプラグインを導入するだけのようです。
あとはAndroid/iOSのプラットフォームごとに環境変数を設定すれば良いようです。

すみません、私自身は、ここまで書いて力尽きてしまって、このプラグインの挙動まで認認していないです。挙動を確認できたらこの先も追記しますが、とりあえず概要を書いておきます。

dependencies:
  location: ^4.0.0

APIをみると、下記のAPIでバックグラウンド許可できるようです。

enableBackgroundMode({bool enable})

おわりに

位置情報は難しいです。今回、調べていて、自分自身も学びが多かったです。