I’m having Trouble Getting GPS Location in the Background [Flutter]

Save your time as beginners to avoid what I’ve been trying to develop background tracking on the Flutter app.

Matatias Situmorang
6 min readApr 15, 2023
Photo by henry perks on Unsplash

Currently, I'm developing a new feature for tracking location in Flutter apps. Everything is work fine when it's running on FOREGROUND. But the problem is how to keep tracking and get the location when the app is in the background and also when the app is terminated.

Let's make the same definition for better understanding. There are 3 common states in mobile apps.

  • Foreground: When the application is open, in view & in use
  • Background: When the application is open, however in the background (minimized)
  • Terminated: When the device is locked, or the application is not running.

Actually, this issue is not “Clearly” solved by me 😏. I'm still looking for the best workaround. And I will share my current solution in another article.

I’ve tried many solutions that I found from many sources. And this article will explain what I tried and the result. Of course, I really appreciate it if you suggest any workaround. Probably I missed those things.

I’ve tried some plugins from pub.dev. FYI, I use Xiaomi Redmi Note 7 to develop this feature. I also have pixel 3a.

1. geolocator | Flutter Package (pub. dev)

While developing background tracking, my mistake is not upgrading the package. I still use v7.x.x while developing this tracking feature. The tracking was working fine only in the foreground. For the background and terminated state the tracking method stuck on getLocation() and not throw any errors.
When you call await Geolocator.getCurrentPosition() in the background, and all the permission guaranteed, this method will not return any value and also no error. The method will be stuck until terminated by the Operating System (OS).

Since the issue is only in the background, then I tried some tricks to help the package run in the background state.

  • My first idea is, I want to trigger the getCurrentPosition method with a push notification. I try to call to get a position inside backgroundMessageHandler of my Firebase Cloud Messaging (FCM). The mechanism is tried to get the location of every received notification in the background.
    With this method, still no luck. The method stuck while getCurrentPosition and no return anything.
  • The second idea is to combine geolocator + workmanager to get the location in the background and terminated state. I also tried registering scheduled tasks and calling the getCurrentPosition
    inside. It works sometimes, but mostly no value is returned from the method and the workmanager will throw result Failure. Btw, I just named the apps as fcm_gps_tracking, for the image below the notification come from workmanager package.
  • last, I figure out, there are changes in v8. (My current solution is using this package). Especially in version 8.2.0 : Adds support to make a foreground service on Android and continues processing location updates when the application is moved into the background. With this method, we can keep tracking the location. But you can’t dismiss the foreground service once you close the app. I can get the location every interval time around 15 min (default android).

2. location | Flutter Package (pub.dev)

After desperate with the geolocator package, I found one suggestion on the GitHub issue to use this package. They said the location package support run in the background for Android and iOS. And here I am, changing my dependencies from geolocator to location package.

and…. IT'S SAME! still no luck.

with the location package, when I call await location.getLocation(); in the background state, throws an error if it's failed.

I/flutter ( 3024): PlatformException(error, Attempt to write to field 
'io.flutter.plugin.common.MethodChannel$Result com.lyokone.location.FlutterLocation.getLocationResult' on a null
object reference, null, java.lang.NullPointerException: Attempt to write to field
'io.flutter.plugin.common.MethodChannel$Result com.lyokone.location.FlutterLocation.getLocationResult' on a null object reference
I/flutter ( 3024): at com.lyokone.location.MethodCallHandlerImpl.onGetLocation(MethodCallHandlerImpl.java:117)

I also try push notifications to trigger the getLocation() and registered task from workmanager + location, but both failed. I still can't get the GPS location in the background state.

3. flutter_background_geolocation | Flutter Package (pub.dev)

This package is free for debug mode. If you want to use it in release mode, you have to buy the licenses from the publisher. The documentation says that flutter_background_geolocation support for the headless method.

when I use this package in debug mode, the location is not guaranteed collected. Because of a different manufacturer, also different behavior to the package. When I run on pixel 3a, I can get the GPS value while in the background. But for Xiaomi, mostly failed and throw timeout to get the GPS value while in the background state.

HeadlessMode? true
I TSBackgroundFetch: - cancel taskId=flutter_background_fetch, jobId=999
D TSBackgroundFetch: - onStopJob
D TSBackgroundFetch: [BGTask] timeout: flutter_background_fetch
E TSBackgroundFetch: [BGTask] failed to load config for taskId: flutter_background_fetch
D TSBackgroundFetch: - finish: flutter_background_fetch
D TSBackgroundFetch: - jobFinished

Here is another log that I got:

I AutoStartManagerService: MIUILOG- Reject service :Intent { cmp=com.myapp.fcm_gps_tracking/com.transistorsoft.tsbackgroundfetch.FetchJobService } userId : 0 uid : 10640
I JobServiceContext: MIUILOG- Reject Start Job, cancelJob uid : 10640 jobId :999

as you can see the MIUILOG reject the service in the background. It comes from the operating system MI. But for the solution, you can handle based on device manufacture. find your device from the listed manufacturer below:

Don’t kill my app! | Hey Android vendors, don’t kill my app! (dontkillmyapp.com)

4. flutter_background_service | Flutter Package (pub.dev)

After trying the 3 package above, I was wondering that to bring the background service to the foreground. And finally, I end up with the flutter_background_service package. Since the workmanager and push notification failed, then I try this package.

This package helps me to bring Background service to the foreground as a notification. So, we can execute the geolocator or location inside the services. And yeah, I can receive GPS value when in the background as long as the foreground notification is still running.

In my Redmi Note 7, the service can still run for around 6 hours. And after that, I think the service was terminated by the system.
So, flutter_background_service + location/geolocator success to get the location in the background as long as the foreground notification service is running.

one time, I was wondering about other location plans. Then I tried using another location package which has a bit of a like in pub.dev. Implemented it hoping that the package will work in the background.

5. location_plus | Flutter Package (pub.dev)

This plugin is to get current_location. I try to implement and test it in the background. And here are the logs that I received:

* What went wrong:
Execution failed for task ':location_plus:compileDebugJavaWithJavac'.
> Could not resolve all files for configuration ':location_plus:androidJdkImage'.
> Failed to transform core-for-system-modules.jar to match attributes {artifactType=_internal_android_jdk_image, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime}.
> Execution failed for JdkImageTransform: C:\Users\user\AppData\Local\Android\sdk\platforms\android-33\core-for-system-modules.jar.
> jlink executable C:\Program Files\Android\Android Studio\jre\bin\jlink.exe does not exist.

again it throws an error while getting the location in the background.

6. fl_location | Flutter Package (pub.dev)

Tried another plugin from pub.dev. And also throws another error while getting the location in the background:

error: PlatformException(ACTIVITY_NOT_ATTACHED, 
The function to use Activity is not available
because Activity is not attached to FlutterEngine., null, null)

After explore some plugin from pub.dev, currently the best solution is using geolocator (v8.2 above) + workmanager with additional setting from Don’t kill my app! | Hey Android vendors, don’t kill my app! (dontkillmyapp.com) .

As I mentioned above in package geolocator point 3, the tracking feature works on the background with stream location. More detail will be explained in another article.

If you have a better workaround for tracking location in the background and terminated state, feel free to leave a comment below.

Thank you for reading….

--

--

Matatias Situmorang
Matatias Situmorang

Written by Matatias Situmorang

Flutter developer | Blogger | Reach me on twitter @pmatatias_

Responses (5)