-
-
Notifications
You must be signed in to change notification settings - Fork 829
Background Location Updates
You should not use this guide now. Check the README for the latests way to get background location updates.
The FlutterLocation Plugin has experimental supports for Background Location. Expect bugs, maybe more in iOS since I don't have a real device to test on it. Any report to help the development of this feature is more than welcome.
A sample app to help you start is available.
You can register your application to receive location updates even when the application was closed by the user. The location updates will be dispatched 3 to 4 times by hour, or more often if the user has open another app that is using the Location service.
The first things to do is to switch to the master channel of flutter, the iOS native view plugin is only available on this channel for now:
flutter channel master
Then add the plugin to your dependencies with a link to the background_location branch in you pubspec.yaml
:
dependencies:
location:
git:
url: git://github.com/Lyokone/flutterlocation.git
ref: background_location
Add the AndroidX necessaries dependencies in gradle.properties
:
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536M
Your application should launch correctly with this setup. Let's now add background location capabilities !
To add the headless capability on Android, you have to declare a separate Application.java that will extends Flutter application. In android/app/src/main/java/com/.../your_package/
create an Application.java
next to MainActivity.java
.
package com.company.yourpackage;
import com.lyokone.location.LocationPlugin;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class Application extends FlutterApplication implements PluginRegistry.PluginRegistrantCallback {
@Override
public void onCreate() {
super.onCreate();
LocationPlugin.setPluginRegistrant(this);
}
@Override
public void registerWith(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
}
}
Don't forget to change the first line to your package name ! You can find it in MainApplication.java
.
You then have to register this new Application in the AndroidManifest.xml
to use it and have headless capability. Change io.flutter.app.FlutterApplication
to .Application
.
...
<application
android:name=".Application"
android:label="location_example"
...
And in the same AndroidManifest.xml
you have to specify which Activity is responsible of handling background location updates, which is the one of the plugin. You have to add everything between the receiver
tags.
...
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver android:name="com.lyokone.location.BackgroundLocationBroadcastReceiver"
android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="com.lyokone.location.BackgroundLocationBroadcastReceiver.ACTION_PROCESS_UPDATES" />
</intent-filter>
</receiver>
</application>
...
Your Android application is now ready to receive background location updates ! Let's move to iOS.
While Flutter is merging the AndroidManifest.xml
of the plugin with the one of your application, you need to manually add the permission for iOS
in your ios/Runner/Info.plist
:
<dict>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>I need it in background because ...</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>I need it in front because</string>
...
Please note that you need both permission to be able to be allow for background location updates.
Then you need to register your Application for headless execution, modify your AppDelegate.m
with #import <location/LocationPlugin.h>
, registerPlugins
function and [LocationPlugin setPluginRegistrantCallback:registerPlugins];
:
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#import <location/LocationPlugin.h>
@implementation AppDelegate
void registerPlugins(NSObject<FlutterPluginRegistry>* registry) {
[GeneratedPluginRegistrant registerWithRegistry:registry];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
[LocationPlugin setPluginRegistrantCallback:registerPlugins];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
Your iOS installation is ready to receive background location updates!
Let's now see how you can use the plugin for background notification: You use registerBackgroundLocation to register a callback function that will receive a list of Location periodically:
static void backgroundCallback(List<LocationData> locations) {
print('Location data received from background: $locations');
}
void _registerListener() async {
bool _permission = await _locationService.requestPermission();
print("Permission: $_permission");
if (_permission) {
bool statusBackgroundLocation = await _locationService.registerBackgroundLocation(backgroundCallback);
print("statusBackgroundLocation: $statusBackgroundLocation");
} else {
print("Permission denied");
}
}
void _removeListener() async {
await _locationService.removeBackgroundLocation();
}
Please note that you need to have the location permission checked in order to receive background location.
Background location and more generally waking up an application in the background can cause battery drain. Please note that taking too long to handle the callback can cause your application to be waked up less frequently by the system.