-
Notifications
You must be signed in to change notification settings - Fork 231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
geofence events not logged to server in real-time #43
Comments
Show me where you’re listening to #onLocation, #onGeofence relative to where you’re executing #ready. |
My import 'package:background_fetch/background_fetch.dart';
import 'package:flutter/material.dart';
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart'
as bg;
import 'package:pointbee/utilities/notifications.dart';
import 'package:pointbee/state/app_state.dart';
/// Receive events from BackgroundGeolocation in Headless state
void backgroundGeolocationHeadlessTask(bg.HeadlessEvent headlessEvent) async {
print('📬 --> $headlessEvent');
await setupNotifications();
switch (headlessEvent.name) {
case bg.Event.LOCATION:
bg.Location location = headlessEvent.event;
print('[BackgroundGeolocation] Headless LOCATION: $location');
showNotification(
title: '[BackgroundGeolocation] Headless LOCATION',
body: 'speed: ${location.coords.speed} time: ${location.timestamp}',
);
break;
case bg.Event.GEOFENCE:
bg.GeofenceEvent geofenceEvent = headlessEvent.event;
print('[BackgroundGeolocation] Headless GEOFENCE: $geofenceEvent');
showNotification(
title: '[BackgroundGeolocation] Headless GEOFENCE',
body:
'speed: ${geofenceEvent.location.coords.speed} time: ${geofenceEvent.location.timestamp}',
);
break;
case bg.Event.GEOFENCESCHANGE:
bg.GeofencesChangeEvent event = headlessEvent.event;
print('[BackgroundGeolocation] Headless GEOFENCESCHANGE: $event');
showNotification(
title: '[BackgroundGeolocation] Headless GEOFENCESCHANGE',
body: 'speed: $event',
);
break;
}
}
/// Receive events from BackgroundFetch in Headless state
void backgroundFetchHeadlessTask() async {
bg.Location location =
await bg.BackgroundGeolocation.getCurrentPosition(samples: 1);
await setupNotifications();
print('[BackgroundFetch] Headless LOCATION: $location');
showNotification(
title: '[BackgroundFetch] Headless LOCATION',
body: 'speed: ${location.coords.speed} time: ${location.timestamp}',
);
BackgroundFetch.finish();
}
/// Add a geofence to the plugin
void addGeofence({
@required String id,
@required double lat,
@required double lng,
@required int radius,
}) async {
bg.Geofence geofence = bg.Geofence(
identifier: id,
latitude: lat,
longitude: lng,
radius: double.parse(radius.toString()),
notifyOnEntry: true,
notifyOnDwell: true,
notifyOnExit: true,
);
try {
await bg.BackgroundGeolocation.addGeofence(geofence);
} catch (e) {
print('Error adding geofence with id $id');
return;
}
print('Successfully added geofence with id $id');
}
/// Initialize plugin to start tracking
Future<bool> startTracking({String env}) async {
// Apply tracker url with username & device params for recognition by tracking server
Map<String, dynamic> deviceParams = await bg.Config.deviceParams;
await bg.BackgroundGeolocation.ready(bg.Config(
desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH,
persistMode: bg.Config.PERSIST_MODE_GEOFENCE,
logLevel: bg.Config.LOG_LEVEL_VERBOSE,
stopOnTerminate: false,
enableHeadless: true,
startOnBoot: true,
reset: true,
autoSync: true,
httpRootProperty: '.',
locationTemplate:
'{ "query": "mutation { insert_location(objects: { lat: <%= latitude %> lng: <%= longitude %> speed: <%= speed %> heading: <%= heading %> accuracy: <%= accuracy %> altitude: <%= altitude %> altitude_accuracy: <%= altitude_accuracy %> timestamp: \\\"<%= timestamp %>\\\" uuid: \\\"<%= uuid %>\\\" event: \\\"<%= event %>\\\" odometer: <%= odometer %> activity_type: \\\"<%= activity.type %>\\\" activity_confidence: <%= activity.confidence %> battery_level: <%= battery.level %> battery_is_charging: <%= battery.is_charging %> device_model: \\\"${deviceParams['device']['model']}\\\" device_platform: \\\"${deviceParams['device']['platform']}\\\" device_manufacturer: \\\"${deviceParams['device']['manufacturer']}\\\" device_version: \\\"${deviceParams['device']['version']}\\\" } ) { affected_rows } }" }',
geofenceTemplate:
'{ "query": "mutation { insert_location(objects: { lat: <%= latitude %> lng: <%= longitude %> speed: <%= speed %> heading: <%= heading %> accuracy: <%= accuracy %> altitude: <%= altitude %> altitude_accuracy: <%= altitude_accuracy %> timestamp: \\\"<%= timestamp %>\\\" uuid: \\\"<%= uuid %>\\\" event: \\\"<%= event %>\\\" odometer: <%= odometer %> activity_type: \\\"<%= activity.type %>\\\" activity_confidence: <%= activity.confidence %> battery_level: <%= battery.level %> battery_is_charging: <%= battery.is_charging %> device_model: \\\"${deviceParams['device']['model']}\\\" device_platform: \\\"${deviceParams['device']['platform']}\\\" device_manufacturer: \\\"${deviceParams['device']['manufacturer']}\\\" device_version: \\\"${deviceParams['device']['version']}\\\" geofence_identifier: \\\"<%= geofence.identifier %>\\\" geofence_action: \\\"<%= geofence.action %>\\\" } ) { affected_rows } }" }',
url: '${appBase.hasuraUrl}',
locationAuthorizationRequest: 'Always',
locationAuthorizationAlert: {
'titleWhenNotEnabled': 'Location services not enabled',
'titleWhenOff': 'Location services are OFF',
'instructions':
'Location services required to start earning points. Please enable \'Always\' in location settings.',
'cancelButton': 'Cancel',
'settingsButton': 'Settings'
},
// Do not record location event if more than 300 meters/second since last
// recorded event - Android only, iOS does not allow mock locations on device
speedJumpFilter: 300,
foregroundService: true,
notificationPriority: bg.Config.NOTIFICATION_PRIORITY_MIN,
notificationTitle: 'Zone Tracker',
notificationText: 'Zone search underway',
notificationChannelName: 'Zone Tracker',
));
try {
await bg.BackgroundGeolocation.startGeofences();
} catch (e) {
print(e);
}
// Register BackgroundGeolocation headless-task
bg.BackgroundGeolocation.registerHeadlessTask(
backgroundGeolocationHeadlessTask);
// Register BackgroundFetch headless-task
BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
// Fired whenever a location is recorded
bg.BackgroundGeolocation.onLocation((bg.Location location) {
print('[BackgroundGeolocation] onLocation $location');
showNotification(
title: '[BackgroundGeolocation] onLocation',
body: 'speed: ${location.coords.speed} time: ${location.timestamp}',
);
}, (bg.LocationError error) {
print('[onLocation] ERROR: $error');
});
bg.BackgroundGeolocation.onHttp((bg.HttpEvent event) {
print('[BackgroundGeolocation] onHttp $event');
});
bg.BackgroundGeolocation.onGeofence((bg.GeofenceEvent event) {
print('[BackgroundGeolocation] onGeofence $event');
showNotification(
title: '[BackgroundGeolocation] onGeofence',
body:
'speed: ${event.location.coords.speed} time: ${event.location.timestamp}',
);
});
try {
// force location permission dialog
await bg.BackgroundGeolocation.getCurrentPosition(
persist: false,
samples: 1,
);
} catch (e) {
print(e);
// Permission was denied
if (e.code == 1) return false;
}
return true;
} Later in the application on a button tap before starting bicycle ride this is executed: await bg.BackgroundGeolocation.start(); |
|
With that change The log for this last run is available here. For this run I did not persist location, only geofence. |
With further observation the http requests for the geofence events is performed in the background, just not in perfect real-time. If I wait a minute eventually the request is sent for a group of pending events at once while in background. If I open the app it sends them all at that time. I have |
I see you closed this? it's no issue? |
Once I set the listeners before calling After that there was a slight delay in the time the data was appearing on my server, but I was think I just being impatient. Will keep monitoring and reopen if needed. Thanks for checking up on this issue. |
Next beta arriving soon. |
flutter doctor
):Expected Behavior
When app is terminated both location and geofence events produce an http request to the server.
Actual Behavior
When app is terminated only location events produce an http request to the server. When app is reopened the geofence events are sent to the server all at once.
Context
On iOS simulator when the app is terminated location events are reliably sent to the server. However, geofence events are not sent to the server until the application is reopened. That causes the
timestamp
to be identical on all geofence records, thus giving the appearance the geofence events happened after the location events. I have not tried to replicate yet on Android.Ideally, the geofence events would be sent in real-time, just like the location events.
The log for this issue can be found here.
geofence event uuid values:
ed229f41-1f76-4d08-815c-4abf2e5d8d1f
ab8965fa-1ccc-46d1-8d20-db1ea675152f
5d534cd7-6e4f-4bb6-a644-a9a7caa54d04
1d3ddf9e-a5df-441b-a462-e06e963a03c8
cb196d57-f705-4562-aa6a-057c5e9597f9
1e535b14-2e9c-48ea-b8c1-30eb7ca27d25
1abe219f-a707-4510-84d3-c9d0d76c81f1
1159efaf-fd77-40fa-b422-56abfd2497c4
75123ec7-c6ee-40c7-adae-519ce403003c
The text was updated successfully, but these errors were encountered: