State enabled when BackgroundGeolocation.stop() is called is not updated to false on Android
I am using state.enabled to notify the user when geolocation is switched off or on:
await stopTransistorsoft().then((state) => serviceActive = state.enabled);
Flag serviceActive is used to update the UI based on the geolocation tracking state. I noticed that serviceActive is true after stopTransistorsoft() is finished.
Your Environment
-
Plugin version: v4.7.0
-
Platform: Android
-
OS version: Android 12
-
Device manufacturer / model: emulator
-
Flutter info (
flutter doctor): [✓] Flutter (Channel unknown, 2.10.3, on macOS 12.2.1 21D62 darwin-arm, locale en-RS) [✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 13.4.1) [✗] Chrome - develop for the web (Cannot find Chrome executable at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome) ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable. [✓] Android Studio (version 2021.2) [✓] VS Code (version 1.68.1) [✓] Connected device (2 available) [✓] HTTP Host Availability -
Plugin config:
await bg.BackgroundGeolocation.ready(bg.Config(
notification: bg.Notification(
title:'',
// 'Location Services Active',
text: '',
sticky: true,
layout: 'workday_notification_layout',
smallIcon: 'mipmap/ic_notification',
// <-- defaults to app icon
largeIcon: 'mipmap/ic_notification',
),
locationAuthorizationRequest: 'always',
disableLocationAuthorizationAlert: true,
backgroundPermissionRationale: bg.PermissionRationale(
title: ''
message: '',
positiveAction: ''),
desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH,
distanceFilter: 10.0,
stopOnTerminate: false,
preventSuspend: true,
heartbeatInterval: 60,
startOnBoot: true,
foregroundService: true,
logLevel: bg.Config.LOG_LEVEL_ERROR,
persistMode: bg.Config.PERSIST_MODE_NONE,
)).then((bg.State state) {
_initialized = true;
});
Expected Behavior
serviceActive should be false
Actual Behavior
serviceActive is true on Android
Steps to Reproduce
- start and stop geolocation and check for state.enabled.
The plugin has no method named stopTransistorsoft()
The plugin has no method named
stopTransistorsoft()
Sorry for the confusion. We have method stopTransistorsoft() which calls await bg.BackgroundGeolocation.stop()
Now why don’t you post the source of your custom method?
The stopTransistorsoft() method just calls stop() on geolocation without any additional work:
static Future<bg.State> stopTransistorsoft() async { return await bg.BackgroundGeolocation.stop(); }
bg.State state = await bg.BackgroundGeolocation.stop();
print("************ state.enabled: ${state.enabled}");
07-21 11:47:29.629 25725 25781 I flutter : ************ state.enabled: false
I tried also to print state.enabled value and noticed that sometimes it's false but sometimes it's true:
Code that I tested:
debugPrint('Date time: ${DateTime.now()} stopGeolocation called before with status ${serviceActive}'); await stopTransistorsoft().then((state) => serviceActive = state.enabled); debugPrint('Date time: ${DateTime.now()} stopGeolocation called after with status ${serviceActive}');
Logs:
I/flutter ( 6632): Date time: 2022-07-22 12:27:46.538818stopGeolocation called before with status true
I/flutter ( 6632): Date time: 2022-07-22 12:27:46.542683stopGeolocation called after with status true
I/flutter ( 6632): Date time: 2022-07-22 12:28:02.309110stopGeolocation called before with status true I/flutter ( 6632): Date time: 2022-07-22 12:28:02.311179stopGeolocation called after with status false
stopTransistorsoft() is:
static Future<bg.State> stopTransistorsoft() async { return await bg.BackgroundGeolocation.stop(); }
I suggest you don’t test your function.
test with BackgroundGeolocation.stop()
I received same log with this approach:
debugPrint('Date time: ${DateTime.now()} stopGeolocation called before with status ${serviceActive}'); // await stopTransistorsoft().then((state) => serviceActive = state.enabled); var state = await bg.BackgroundGeolocation.stop(); serviceActive = state.enabled; debugPrint('Date time: ${DateTime.now()} stopGeolocation called after with status ${serviceActive}');
Logs:
I/flutter (10065): Date time: 2022-07-22 12:39:42.730715 stopGeolocation called before with status true
I/flutter (10065): Date time: 2022-07-22 12:39:42.732919 stopGeolocation called after with status true
Ok, I've reproduced this. This is merely a timing issue, where the Java implementation for .stop() executes in a background-thread but the code immediately executes the callback on the main thread.
Before
public void stop(TSCallback callback) {
if (mStartTask != null) {
mStartTask = null;
}
mIsStarted.set(false);
getThreadPool().execute(() -> {
TrackingService.stop(mContext); // <-- implementation runs on a background-thread in order to not block UI
});
callback.onSuccess(); // <-- callback executed immediately on main-thread before background-queued .stop() executes.
}
Fixed
public void stop(final TSCallback callback) {
if (mStartTask != null) {
mStartTask = null;
}
mIsStarted.set(false);
getThreadPool().execute(() -> {
TrackingService.stop(mContext);
getUiHandler().post(callback::onSuccess); // <-- Run callback on main-thread from within background-thread.
});
}
You can work-around this in the meantime by requesting .state immediately after calling .stop().
await bg.BackgroundGeolocation.stop();
bg.State state = await bg.BackgroundGeolocation.state;
print("******** State.enabled: ${state.enabled}");
Fix will arrive when 4.7.1 is released.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You may also mark this issue as a "discussion" and I will leave this open.