I want to get updates on my location every 15 mins even when the phone sleeps and when the app is minimized. I am currently using workmanager and geolocator to get it but it doesn't work. It kept showing me that the location updates is stopped and disposed when I start
void main() async {
_handleLocationPermission();
await Workmanager().initialize(callbackDispatcher, isInDebugMode: true);
runApp(MyApp());
}
Future<void> _getCurrentPosition() async {
final hasPermission = await _handleLocationPermission();
if (!hasPermission) return;
await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
).then((Position position) {
_currentPosition = position;
print(_currentPosition);
}).catchError((e) {
debugPrint(e);
});
}
@pragma(
'vm:entry-point') // Mandatory if the App is obfuscated or using Flutter 3.1+
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
switch (task) {
case simpleTaskKey:
print('executed');
_getCurrentPosition();
print("${ScheduledTask.taskName} was executed. inputData = $inputData");
break;
}
return Future.value(true);
});
}
I am calling this ScheduledTask in another file like this, ScheduledTask.control();
. When the user pressed on the button, it will start the timer using the workmanager.
class ScheduledTask {
static const String taskName = simpleTaskKey;
static void control() {
_getCurrentPosition();
Workmanager().registerPeriodicTask(
ScheduledTask.taskName, ScheduledTask.taskName,
frequency: Duration(minutes: 15),
existingWorkPolicy: ExistingWorkPolicy.append);
// add your control here
}
}
When the interval is up, it shows a notification that the function has been executed but the location somehow is still not. In the debug console, it is showing this,
D/FlutterGeolocator(10382): Disposing Geolocator services
E/FlutterGeolocator(10382): Geolocator position updates stopped
D/FlutterGeolocator(10382): Stopping location service.
I/WM-WorkerWrapper(10382): Worker result SUCCESS for Work [ id=55a8af72-af00-4039-ad88-8fe07e46a58d, tags={ be.tramckrijte.workmanager.BackgroundWorker } ]
I/WM-WorkerWrapper(10382): Setting status to enqueued for b76febdc-ae5e-47b5-8294-3db31dc0e17a
W/FlutterJNI(10382): Tried to send a platform message response, but FlutterJNI was detached from native C++. Could not send. Response ID: 3
Is there something wrong with my code? I tried using StreamSubscription as well but it didnt work for me. Any guide?
Here is my answer.
Future<void> onStart(ServiceInstance service) async {
// Only available for flutter 3.0.0 and later
DartPluginRegistrant.ensureInitialized();
if (service is AndroidServiceInstance) {
service.on('setAsForeground').listen((event) {
service.setAsForegroundService();
});
service.on('setAsBackground').listen((event) {
service.setAsBackgroundService();
});
}
service.on('stopService').listen((event) {
service.stopSelf();
});
print('Flutter Background Service : ${DateTime.now()}');
}
Future<void> initializeService() async {
final service = FlutterBackgroundService();
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'my_foreground', // id
'MY FOREGROUND SERVICE', // title
description:
'This channel is used for important notifications.', // description
importance: Importance.low, // importance must be at low or higher level
);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await service.configure(
androidConfiguration: AndroidConfiguration(
// this will be executed when app is in foreground or background in separated isolate
onStart: onStart,
// auto start service
autoStart: true,
isForegroundMode: true,
notificationChannelId: 'my_foreground',
initialNotificationTitle: 'Supercare Services',
initialNotificationContent: 'Fetching current location for checkout...',
foregroundServiceNotificationId: 888,
),
iosConfiguration: IosConfiguration(
// auto start service
autoStart: true,
onBackground: onIosBackground,
// this will be executed when app is in foreground in separated isolate
onForeground: onStart,
// you have to enable background fetch capability on xcode project
),
);
service.startService();
}
@pragma('vm:entry-point')
Future<bool> onIosBackground(ServiceInstance service) async {
WidgetsFlutterBinding.ensureInitialized();
DartPluginRegistrant.ensureInitialized();
service.on('stopService').listen((event) {
service.stopSelf();
});
return true;
}
Remember to set your location permission to always allow if you want to fetch location in background.
In my case, I will need to request user to allow location permission to While Using. After that, you can request to "Always Allow" so that you can fetch location in background.
var status = await Permission.locationWhenInUse.status;
if (status.isGranted) { //if the status above is granted
var status = await Permission.locationAlways.request(); //if granted, request to always allow
if (status.isGranted) { //if always allow is granted
await initializeService(); //start the background service
} }