WEBサイト制作・アプリ開発・システム開発・ブランディングデザイン制作に関するご相談はお気軽にご連絡ください。
構想段階からじっくりとヒアリングし、お客様の課題にあわせたアプローチ手法でお客様の“欲しかった”をカタチにしてご提案いたします。
Blog スタッフブログ
Android
Flutter
iOS
システム開発
[Flutter]位置情報をバックグラウンドで取得する
こんにちは、株式会社MIXシステム開発担当のBloomです。
早速本題のFlutterで位置情報をバックグラウンドで取得する手順について、
お仕事の中で得た知見を共有させていただきたいと思います。
導入
まずはlocationパッケージを導入しましょう。pubコマンドを利用します。
flutter pub add location
さらに位置情報を取得するための権限について記述しましょう。AndroidManifest.xmlおよびinfo.plistへ追記します。
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>バックグラウンドおよびアプリを使用中にGPS情報を利用する理由を書きます。</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>バックグラウンドおよびアプリを使用中にGPS情報を利用する理由を書きます。</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>アプリを使用中にGPS情報を利用する理由を書きます。</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
<string>fetch</string>
</array>
実装
では、いよいよ位置情報を取得しましょう。今回は位置情報を取得するためのシングルトンクラスを作っています。
class LocationManager {
// シングルトンインスタンス
static final LocationManager _instance = LocationManager._internal();
factory LocationManager() => _instance;
LocationManager._internal();
Future<void> initialize() async {}
Future<bool> startLocationTracking() async {
if (_locationChangedListen != null) {
finishLocationTracking();
}
Location location = new Location();
bool _serviceEnabled;
PermissionStatus _permissionGranted;
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
debugPrint("service not enabled");
return false;
}
}
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
debugPrint("permisson not enabled");
return false;
}
}
_serviceEnabled = await enableBackgroundMode(location);
if (!_serviceEnabled) {
debugPrint("background service not enabled");
}
_locationChangedListen = location.onLocationChanged.listen((LocationData result) async {
debugPrint("lat: ${result.latitude}");
debugPrint("lng: ${result.longitude}");
debugPrint(result.toString());
});
return true;
}
void finishLocationTracking() {
_locationChangedListen?.cancel();
_locationChangedListen = null;
}
Future<bool> reloadLocationTracking() async {
finishLocationTracking();
return await startLocationTracking();
}
// https://stackoverflow.com/questions/70545730/flutter-location-unhandled-exception-platformexceptionpermission-denied-neve
Future<bool> enableBackgroundMode(Location location) async {
bool _bgModeEnabled = await location.isBackgroundModeEnabled();
if (_bgModeEnabled) {
return true;
} else {
try {
await location.enableBackgroundMode();
} catch (e) {
debugPrint(e.toString());
}
try {
_bgModeEnabled = await location.enableBackgroundMode();
} catch (e) {
debugPrint(e.toString());
}
print(_bgModeEnabled);
return _bgModeEnabled;
}
}
ここで、enableBackgroundModeメソッド内においてlocation.enableBackgroundMode()を複数回実行しています。これはstackoverflowで報告のあった挙動を回避するために設定しています。
あとは位置情報の取得を行いたいタイミングでLocationManager().startLocationTracking();と実行するだけで位置情報を取得できます。良かったですね。
参考文献
location | Flutter package – pub.dev
flutter location , Unhandled Exception – stackoverflow