capacitor-community / background-geolocation

A Capacitor plugin that sends you geolocation updates, even while the app is in the background.
MIT License
196 stars 58 forks source link

Missing locations while the app is in the background #80

Open HarelM opened 2 years ago

HarelM commented 2 years ago

Describe the bug I'm using this plugin in my app and it generally works great. Thanks for all the effort you put into it! Having said that, I noticed in my last recording that there was a place where there were no locations updates for 6 minutes when the app was in the background and after that the GPS seems to trying to reposition itself as the accuracy went down from 120 meters to around 10 in a few seconds. This can be seen in the following image (I was walking on the blue trail): image I can share the recoding of this session or the log file my app collected if needed.

My question/request is to understand how to better debug these kind of glitches to better understand what went wrong in this case - was the service killed/stopped/paused? the GPS from the phone stopped sending signals? Capacitor stopped receiving messages? etc...

In some cases the OS kills the app, but it doesn't look like it in this case as the app's log doesn't show boot-up messages.

To Reproduce Steps to reproduce the behavior:

  1. Start location tracking
  2. Go to the background
  3. Return from background
  4. Expect some GPS signal to be collected while in the background - this doesn't happen all the time, and on a trip of around 3 hours it only happened once, while the app went to the background for multiple times for varying time spans.

Expected behavior Get locations updates while in the background

Screenshots See above

Smartphone (please complete the following information):

Additional context I think it might prove beneficial to store some logging information in the native code and allow fetching this info when required for better debugging? IDK, any insight and thought will be helpful. If you think there's something I can push forward in terms of PR please let me know. This plugin is a core capability of my app and I'm willing to invest the time needed to improve this plugin to better support my needs.

diachedelic commented 2 years ago

I test this plugin using the example app. If you can reproduce your problem using the example app, then there is a problem with the plugin.

To debug problems, I litter the code with print statements and then walk around with my phone plugged into my laptop, and a debugger open. The relevant Android code is in BackgroundGeolocation.java and BackgroundGeolocationService.java.

HarelM commented 2 years ago

Thanks for the super fast response! I don't think I'll have an easy time reproducing the issue. As I said, I walked for 3 hours and it only happened once. In most cases I can't walk around with my laptop plugged to my phone to allow debugging so I believe a better debugging option is needed. This might complicate things a bit but the previous plugin I used had the logs written to an sqlite DB and allowed fetching those when needed. I really like the simplicity of this plugin and I don't want to return to the old one since its too complicated, but still had some nice features... I also prefer not to create a fork and have this code available for others. Let me know how you would like to proceed.

diachedelic commented 2 years ago

Was your phone locked the entire time? Or just for the short time when it stopped recording?

You could modify the plugin to write to a log file on disk, that would be much simpler than writing to a database. You could also modify your application to write to a separate log file. Then, the log files can be compared.

HarelM commented 2 years ago

Ah, yes, disk log file is a lot simpler. The phone was locked from time to time, not all the time. In the time this glitch happened (the straight line) it was locked and the positions afterwards are from when it was open and the app in the front. After that and before that it was locked again from time to time without any issues.

HarelM commented 2 years ago

Would you be interested in a PR which writes some app logs to file and allowing to retrieve the file's content from capacitor js code?

diachedelic commented 2 years ago

No, sorry. I intend to keep this plugin as simple as possible. But if you find a way to reliably reproduce the problem I will take a look at it.

Keep in mind that GPS is not super reliable - satellites are constantly moving, and the device must work to maintain a fix. We have found that in certain places, at certain times, with certain devices, or even in certain cars (interference?) GPS can be extremely flakey.

diachedelic commented 2 years ago

Actually, I'm thinking that this might be a good idea. What about something like this?

BackgroundGeolocation.addWatcher(
    {
        ...

        // In addition to being delivered to the callback, locations can be
        // appended to a file. Locations that have been written to disk are
        // more likely to survive a crash. Each location is JSON encoded and
        // appended to the file as a single line.

        // The "file" option, if specified, is a string containing the URI to a
        // writable file. The file is created if it does not exist.
        file: "file:///path/to/my_locations.txt"

        ...
HarelM commented 2 years ago

This is a very simple and elegant solution! I like it. The only question I have is who manages this file, i.e. can the app delete it? If so, how will the plugin avoid file corruption? Or more to the point when can this file be deleted? Any time? Just when not "watching locations". Also the file path stuff is super complicated between ios, Android and how capacitor works. I saw the same problem in sqlite capacitor plugin where giving a location to a file is complicated. But, nevertheless, I find this as a good improvement where I can later on debug the difference between what I got from the callback and what's in the file. It will help me makes things more robuts, hopefully. Thanks for considering it!

diachedelic commented 2 years ago

It is up to the app to delete the file, if it wants to, and it can do any at any time. If at any time the file does not exist and the plugin wants to write a location to it, then a new file will first be created. Why would there be file corruption?

HarelM commented 2 years ago

I see. I don't know, if you delete while writing? In any case, if this is handled by the OS then there's no problem.

diachedelic commented 2 years ago

If the file is deleted partway through a write (which might be possible if each happen on a different thread) then:

We can handle the exception, of course, but I think we can leave it up to the consumer of the file to ignore any lines that can not be parsed as JSON.

In practice, I think there will be minimal opportunity for corruption.

HarelM commented 2 years ago

I see, you're probably right. I'm in 😄

diachedelic commented 2 years ago

Would you like to build it?

HarelM commented 2 years ago

Whatever works for you. I can give it a go.

diachedelic commented 2 years ago

Yes please.

HarelM commented 2 years ago

I have an initial POC that works on my android device. I write to the file in the BG service to make sure that I'm writing it in the closest point to when I get the location signal. I'm pretty sure I don't support cdv:// stuff correctly, not sure how to do that, so currently I only support file://.... Do you think I need to support iOS as well? I feel like these issues mainly exists on android, but I might be wrong, input is welcomed here. Currently I use location.toString() which actually does a good job of writing all the parameters, if it's critical to write is as a json let me know and I'll move the formatLocation function to the service instead of being in the "controller" class. Are there tests I need to write? If so I'll need some info on how to do that.

diachedelic commented 2 years ago

I think it would be a useful feature on iOS because the WKWebView is so prone to crashing.

I imagine file:// is sufficient, I'm not familiar with the cdv:// scheme. A file:// URL is always returned by Filesystem.getUri, right?

I think the file should contain the same format that is delivered to the callback, so yes, JSON please.

There are no tests, but you could modify the example app to make use of this feature.

HarelM commented 2 years ago

Ok, thanks for the info! I'll try to send a PR in the next few days, at least for android to get an initial feedback.

HarelM commented 2 years ago

I had the same problem today twice when I recorded a route. In both cases the problem occurred after doing a "break" in my route - meaning I was in the same location for a few minutes and the app in the background, the GPS returned to show the current location only when I opened the screen and returned to the app, a straight orange line can be seen in the image below (blue line is the planned route): image the problem might be with the "start sticky" return value (I saw it in a SO question somewhere): https://github.com/HaylLtd/cordova-background-geolocation-plugin/blob/c5687db452a598008590d1c5dfc6cf628592c15a/android/common/src/main/java/com/marianhello/bgloc/service/LocationServiceImpl.java#L275

The other option might be to use the GPS provider and not the fused location which I was using in the past (which is more noisy but basically what you want to have here - get the data from the GPS): https://github.com/HaylLtd/cordova-background-geolocation-plugin/blob/c5687db452a598008590d1c5dfc6cf628592c15a/android/common/src/main/java/com/marianhello/bgloc/provider/RawLocationProvider.java#L39

Unfortunately, I didn't have the log PR in my app so I have no more info besides the observation I wrote above. If you are able to reproduce this, please let me know. I'll continue investigating this, but I believe there's a real issue here.

foto-andreas commented 1 year ago

I did see similar problems on iOS when taking photos during tracking. So yes, the geo app is in background, but taking a photo shifts the problem rate to about 80% of the tests.

Andreas

machao81 commented 1 year ago

i remarks that GPS does not work when the device has no network. Perhaps it is your case. Instead receive the event with coordinates i see the log "Location not available".

Easily to reproduce, enable/disable data mobile. Tested on Android, not tested on IOS

i opened a ticket https://github.com/capacitor-community/background-geolocation/issues/98

HarelM commented 1 year ago

I'm not sure this is the cause in my case, but reception shouldn't matter for in theory, might be another issue...

roelfilweb commented 1 year ago

Facing the same issue on android.

LukasGrubis commented 1 year ago

Has anyone encountered the problem where the app ceases to track geolocation while recording a video through the camera, especially when the app is running in the background?

Issue is on android, with iOS works fine