Flutter Background Geolocation: Effective Techniques
Constant location tracking can be an important feature for taxi apps, apps that track the location of your children or friends. In such cases, we need to work in the background.
In Flutter, we can use an open-source location package for this purpose. Also, for a visual demonstration of the plugin's work, we used OpenStreetMap.
Let's see how to use this package.
Request Location Permission
Permissions are the first thing to start with. Since access to the location is a dangerous permission, we need to request it from the user.
Android Setup
With Flutter 1.12, all the dependencies are automatically added to the project. But to use location background mode, we have to add the following additional permissions:
Apps that target Android 9 (API level 28) or higher must add the FOREGROUND_SERVICE permission.
If the app targets Android 10 (API level 29) or higher, we also need to check for the ACCESS_BACKGROUND_LOCATION permission.
Add them to AndroidManifest.xml before <application>
tag:
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Remember that to use the background location the user has to accept the location permission to Allow all the time. On Android 11 (API level 30) and higher, however, the system dialog doesn't include the Allow all the time option. Instead, users must enable background location on a settings page.
However, the plugin allows us to immediately show to the user the necessary page by calling the location.requestPermission()
method. This will show the following window:
iOS Setup
We need to add the NSLocationWhenInUseUsageDescription
key to the app's Info.plist file, to use location services in an iOS app.
If your app needs to access the user's location information at all times, even when the app is not running, you can also add the NSLocationAlwaysAndWhenInUseUsageDescription
key.
These keys are used to request permission from the user to access their location information and are required by the operating system.
We also have to add the following to Info.plist:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>The app needs it</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>The app needs it</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
You can always refer to the official repository if you have any problems.
That's all we need to do in the native part. Let’s go to the dart code ⬇️.
Requesting a Location
To request a location, you should always check the Location Service status and Permission status manually:
Location location = new Location();
bool _serviceEnabled;
PermissionStatus _permissionGranted;
LocationData _locationData;
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
return;
}
}
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return;
}
}
Now we can request our current location:
_locationData = await location.getLocation();
Or track the user's movement:
location.onLocationChanged.listen((LocationData currentLocation) {
// Use current location
});
To receive location when the application is in the background you have to enable it:
location.enableBackgroundMode(enable: true);
Display App Notification
When our application is running in the background, we must show the user the appropriate notification.
The plugin allows us to customize the type of notification:
_location.changeNotificationOptions(
title: 'Geolocation',
subtitle: 'Geolocation detection',
);
We can also change iconName
, description
, color
, channelName
, and onTapBringToFront
flag.
On Android, a notification is displayed with information that the location service is running in the background:
On iOS, while the app is in the background and gets the location, the blue system bar notifies users about updates. Tapping on this bar moves the User back to the app.
P.S.
The plugin is open source, so it allows us to understand its internal structure. You can learn how to work with Platforms Channels, natively call notifications, and request location using LocationManager
for Android and CLLocationManager
for iOS.
Thanks Lisa for help with this article.