capacitor-community / background-geolocation

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

Capacitor 4 after 5 minutes stop working #89

Closed ghimarcos closed 1 year ago

ghimarcos commented 1 year ago

Describe the bug

I have an application that was previously on Capacitor version 3.6.0, and it worked perfectly. So we need to update Capacitor to version 4.6.1 and now it always stops working after 5 minutes in while the application is in Background.

To Reproduce

create an application with the following libs:

"@capacitor-community/background-geolocation": "1.2.7",
"@capacitor/android": "4.6.1",
"@capacitor/ios": "4.6.1",
"@capacitor/core": "4.6.1",
"@capacitor/app": "4.1.1",

Remembering that the same code with these lib versions here work perfectly sending POST for more than 5 minutes:

"@capacitor-community/background-geolocation": "1.2.7",
"@capacitor/android": "3.5.1",
"@capacitor/ios": "3.6.0",
"@capacitor/core": "3.6.0",
"@capacitor/app": "1.1.1",
jamesdiacono commented 1 year ago

Are you using the native HTTP plugin to send your POST requests? See https://github.com/capacitor-community/background-geolocation/issues/14#issuecomment-1293574693.

ghimarcos commented 1 year ago

Yes, in both versions (@capacitor 3.6.0 and @capacitor 4.6.1 ), I used native requests from CapacitorHttp, example:

if (window.navigator.onLine) { const doPost = async () => { const options = { url: 'https://myApiUrl', headers: { 'Authorization': Bearer ${localStorage.getItem('token')}, 'Content-Type': 'application/json' }, data: { trackingCoords: this.trackingCoords }, }; const response: HttpResponse = await Http.post(options); }; doPost(); }

jamesdiacono commented 1 year ago

Can you reproduce this using the app in the example/ directory?

ghimarcos commented 1 year ago

I believe so, but only tomorrow, then I'll let you know

ghimarcos commented 1 year ago

In app from the example/ directory when i generated apk by android studio, it worked correctly in the background for 5 minutes, but then it stopped, I didn't even change the code, could it be that something was missing?

Samy-F commented 1 year ago

I got the same problem. It was working perfectly before I updated to capacitor v4 and it stopped working. Right now it stops after 5 minutes. And yes I am also using HTTP to make requests. Anyone that knows a fix?

diachedelic commented 1 year ago

Is this affecting iOS, or just Android?

Samy-F commented 1 year ago

Only android. On iOS it is working fine. I had this same problem a while ago on version 3but that was because I was using axios.

Op vr 3 feb. 2023 om 22:30 schreef diachedelic @.***>

Is this affecting iOS, or just Android?

— Reply to this email directly, view it on GitHub https://github.com/capacitor-community/background-geolocation/issues/89#issuecomment-1416422816, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANMF7O3JKEZCGGYSUS2H3CDWVV2ILANCNFSM6AAAAAAUPKN4FU . You are receiving this because you commented.Message ID: @.*** com>

diachedelic commented 1 year ago

Were you using the same version of this plugin for both Capacitor v3 and Capacitor v4? I just want to be sure that it's not a bug I introduced recently.

Samy-F commented 1 year ago

I tried 2 things. First on version 1.2.6 and then 1.2.7. Both not working.

Op vr 3 feb. 2023 om 23:10 schreef diachedelic @.***>

Were you using the same version of this plugin for both Capacitor v3 and Capacitor v4? I just want to be sure that it's not a bug I introduced recently.

— Reply to this email directly, view it on GitHub https://github.com/capacitor-community/background-geolocation/issues/89#issuecomment-1416466576, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANMF7OY6AOWEYFKIQLS3WGDWVV64NANCNFSM6AAAAAAUPKN4FU . You are receiving this because you commented.Message ID: @.*** com>

diachedelic commented 1 year ago

Try setting some breakpoints around https://github.com/capacitor-community/background-geolocation/blob/c6e5010663fc0f0da3b87f26e4c39560093edf9e/android/src/main/java/com/equimaps/capacitor_background_geolocation/BackgroundGeolocationService.java#L96. We must determine whether the issue is with the location provider, or communication with the WebView.

Samy-F commented 1 year ago

You want to talk trough discord? Add me if you want:

Add me on https://discord.com/ so we can talk! My username is Samy#1851.

Op vr 3 feb. 2023 om 23:34 schreef diachedelic @.***>

Try setting some breakpoints around https://github.com/capacitor-community/background-geolocation/blob/c6e5010663fc0f0da3b87f26e4c39560093edf9e/android/src/main/java/com/equimaps/capacitor_background_geolocation/BackgroundGeolocationService.java#L96. We must determine whether the issue is with the location provider, or communication with the WebView.

— Reply to this email directly, view it on GitHub https://github.com/capacitor-community/background-geolocation/issues/89#issuecomment-1416488323, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANMF7O5OA2LH3NAX65M2DZ3WVWBYFANCNFSM6AAAAAAUPKN4FU . You are receiving this because you commented.Message ID: @.*** com>

ghimarcos commented 1 year ago

Try setting some breakpoints around

https://github.com/capacitor-community/background-geolocation/blob/c6e5010663fc0f0da3b87f26e4c39560093edf9e/android/src/main/java/com/equimaps/capacitor_background_geolocation/BackgroundGeolocationService.java#L96

. We must determine whether the issue is with the location provider, or communication with the WebView.

I did this in the example, and from what I noticed, it continues to capture the values, but after 5 minutes it stops sending to the application but continues capturing, if we open the app again, leaving to the background, it sends everything that it captured all at once.

https://drive.google.com/file/d/1XOIMpzMi_0tC_Tawal90O0hAZ9iDBTqI/view?usp=share_link https://drive.google.com/file/d/11Was8pK6cmcHQh8Xl60QWmgsgx_DK3VU/view?usp=share_link https://drive.google.com/file/d/1dvS0uXE1L15nigOA6bMDkzZTfT1eRUt8/view?usp=share_link

diachedelic commented 1 year ago

It seems that the operating system is suspending execution of the WebView. Have you ensured battery optimisation is turned off? See https://dontkillmyapp.com/. It seems strange that upgrading to Capacitor 4 would cause this.

Samy-F commented 1 year ago

I had that in the previous version. I might have deleted it by accident. I will try it and let you know. I tried to set the settings on the phone to allow all battery usage the app needs.

Op ma 6 feb. 2023 om 22:24 schreef diachedelic @.***>

It seems that the operating system is suspending execution of the WebView. Have you ensured battery optimisation is turned off? See https://dontkillmyapp.com/. It seems strange that upgrading to Capacitor 4 would cause this.

— Reply to this email directly, view it on GitHub https://github.com/capacitor-community/background-geolocation/issues/89#issuecomment-1419776091, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANMF7O6XNLTUTHGVEA5W2ALWWFTXLANCNFSM6AAAAAAUPKN4FU . You are receiving this because you commented.Message ID: @.*** com>

ghimarcos commented 1 year ago

I resolved my problem, it was probably a structural problem, i removed all my code and did it based on the example, some imports changed too, here's how the code made in typescript was in case anyone needs it.

` async addWatcher(background: boolean): Promise { try { let id: number;

  const theConfig = Object.assign(
    { stale: true },
    background
      ? {
        backgroundTitle: 'Location you',
        backgroundMessage: 'getting your location.',
      }
      : {
        distanceFilter: 0,
      }
  );

  // eslint-disable-next-line prefer-const
  id = await BackgroundGeolocation.addWatcher(theConfig, function callback(
    location: any,
    error: any
  ): void {
    if (error) {
      if (
        error.code === 'NOT_AUTHORIZED' &&
        window.confirm(
       'This app needs your location, ' +
                'but does not have permission.\n\n' +
                'Open settings now?'
        )
      ) {
        BackgroundGeolocation.openSettings();
      }
      return this.logError(error);
    }

    return console.log('getting', location, 'id :', id);
  });

  console.log('your logic...', id);

} catch (error) {
  console.log(error);
}

}`

diachedelic commented 1 year ago

I'm not sure that will have resolved your problem. Above your comment there is a reference to a bug report for Capacitor 4, which makes it look like we need some kind of workaround like this to prevent the WebView going to sleep in the background. @Samy-F , do you want to see if you can implement this fix?

ghimarcos commented 1 year ago

I believe it's not a problem with the background-geolocation plugin, because I'm managing to send Post now normally for as long as I want, and I'm on the latest version of both the capacitor and the geolocation plugin, but I admit that I don't know what the problem really was, I simply deleted everything I had and redid everything again.

diachedelic commented 1 year ago

OK, I'm glad you got it working. I will leave this issue open because it seems others are having the same problem.

darwinmanchola commented 1 year ago

Hi, I have the same problem my appp work fine in background for 5 ~ 10 minutes and then stop de sent locations, but when open again app star work fine.

sorry by my english

diachedelic commented 1 year ago

Can you replace the handleOnPause method in BackgroundGeolocation.java with the following, and see if that solves the problem?

    @Override
    protected void handleOnPause() {
        if (service != null) {
            service.onActivityStopped();
            new Thread(() -> {
                try {
                    Thread.sleep(1000);
                    this.bridge.getWebView().dispatchWindowVisibilityChanged(View.VISIBLE);
                } catch (Exception ignore) {}
            }).start();
        }
        stoppedWithoutPermissions = !hasRequiredPermissions();
        super.handleOnPause();
    }
sblum51 commented 1 year ago

Thanks for all your work ! Do you if adding Capacitor Permissions (using annotation per example) can help about background ? I have my own plugin about beacons scanning in background and my device and others where the following permissions were requested hadn't issue about background. I had a try with ten's of users with several device (without the part about the permissions) and they got issues about background location.

I suggest to add the following permissions :

EDIT : ok, I add an issue (no service triggered and no notificatio, using Capacitor 4), now when I add ACCESS_BACKGROUND_LOCATION the notification is OK. I will try the background behavior using this notification.

If you want I can create a PR ! thanks again

diachedelic commented 1 year ago

That is interesting, but I don't see how can be a permissions problem. The locations are being recorded in the background, but they are only reported to the WebView when the app comes to the foreground again.

Also, on Android, we do not technically record locations in the "background" (see https://github.com/capacitor-community/background-geolocation/issues/58#issuecomment-1101896976), so the ACCESS_BACKGROUND_LOCATION should not be necessary.

The FOREGROUND_SERVICE permission is already requested in the plugin's AndroidManifest.xml. I wonder if the REQUEST_IGNORE_BATTERY_OPTIMIZATIONS has something to do with it - but from my understanding, that is just a convenient way to disable battery optimizations, which can be done via the settings anytime).

using annotation per example

Which example is this?

ok, I add an issue (no service triggered and no notificatio, using Capacitor 4)

Can you please link to this issue?

Are you using this plugin, a different plugin, or both?

ivinantony commented 1 year ago

same issue for me in android pixel 5

ivinantony commented 1 year ago

Try setting some breakpoints around https://github.com/capacitor-community/background-geolocation/blob/c6e5010663fc0f0da3b87f26e4c39560093edf9e/android/src/main/java/com/equimaps/capacitor_background_geolocation/BackgroundGeolocationService.java#L96

. We must determine whether the issue is with the location provider, or communication with the WebView.

I did this in the example, and from what I noticed, it continues to capture the values, but after 5 minutes it stops sending to the application but continues capturing, if we open the app again, leaving to the background, it sends everything that it captured all at once.

https://drive.google.com/file/d/1XOIMpzMi_0tC_Tawal90O0hAZ9iDBTqI/view?usp=share_link https://drive.google.com/file/d/11Was8pK6cmcHQh8Xl60QWmgsgx_DK3VU/view?usp=share_link https://drive.google.com/file/d/1dvS0uXE1L15nigOA6bMDkzZTfT1eRUt8/view?usp=share_link

same happens for me @ghimarcos how you fixed it?

diachedelic commented 1 year ago

Please test that this is fixed in v1.2.12.

diachedelic commented 1 year ago

The workaround introduced in v1.2.12 causes window.document to emit a bogus "visibilitychange" event, at which point document.visibilityState is "visible". This change caused a serious bug in my app (which would have been next to impossible to diagnose had I not thought of this workaround) so I am going to remove it.

Does anybody know any other way to keep the WebView responsive after 5 minutes in the background? Why does this bug only affect Capacitor 4, but not Capacitor 3?

sblum51 commented 1 year ago

As written before, can you try with the ACCESS_BACKGROUND_LOCATION ?

I spent hours and hours to try a lot of possibilities about several apps.

By using the access background location my WebView was still receiving updates several hours later.

diachedelic commented 1 year ago

I have not been able to reproduce the problem on my device, but if I can I will try adding that permission. Thanks.

sblum51 commented 1 year ago

All the background issues (WebView, app) are a big mess. It think you're aware about it but it depends of devices and also settings.

You can try to reproduce that issue about wake up by using doze mode.

For testing purpose I add a "POST" request (using Native Http) and locally I created a server with pings.

diachedelic commented 1 year ago

Does this problem occur even when the app is exempt from battery optimizations? It looks like Android restricts access to the network once the app has entered Doze mode. https://developer.android.com/training/monitoring-device-state/doze-standby#support_for_other_use_cases

sblum51 commented 1 year ago

Ok I spent the last few hours testing cases. For the moment I have not enought time for the others test case (several devices because manufacturers doesn't have the same behavior, I know Samsung is stricter than several other manufacturers), I also need to try with the other permissions (background geolocation and battery optimization).

Context: Android Emulator (Android API 33), App: ViteJS + Capacitor 4. I created one probe with 2 http post (by this way I can get "feedback" without waking up the devise in case of "screen off" or "doze mode". 2 http post: one using CapacitorHTTP (using native http request) and Axios because axios uses fetch and can be more easily switch off when entering in doze mode. By default my app is in "optimized mode" (about battery). I allowed the authorization, when I get in background mode I had no notifications and no update. When I came in foreground it was ok I received the location updates again. I had to add the "foreground service" permission in order to be able to trigger the notification. I had a try after and it was ok with the foreground service permission (not in the doc). In restricted mode when going in background: no update. In "optimized mode" and doze mode (and background) location updates where OK.

The optimized mode is a good thing but I think it a mess because manufacturers have their own rules (battery left ? bettery unplug, etc...) to deal with that.

As mentionned I have to test with several real devices and other permissions...

diachedelic commented 1 year ago

Thanks for looking into this.

In "optimized mode" and doze mode (and background) location updates where OK.

The location updates did not stop after 5 minutes?

sblum51 commented 1 year ago

I cannot confirm for the moment, I have to investigate again because I had this behavior (location updates Ok) but at the beginning I think I had a behavior where updates stopped. I'll try to reproduce again and again before confirm

machao81 commented 1 year ago

I test this solution and the issue looks fixed 👍

diachedelic commented 1 year ago

@machao81 Did you test it with plugin v1.2.11 or v1.2.12, with or without battery optimizations? I am not happy with the fix I introduced in v1.2.12.

machao81 commented 1 year ago

v1.2.12. the issue in background. I deployed the solution to two testers and they no longer have a problem. With the previous version the GPS worked for 10/15 minutes then nothing

alexandermccormick commented 1 year ago

So I had this issue initially, and have been testing this over the last couple of days. I don't believe this is an issue with the plugin. My fork is located here if anybody would like to verify my findings themselves. This was all tested using v1.2.11, the previous version, which does not include the recent WebView hack.

The fork has 3 directories of interest, as well as a Node.js echo server to externally monitor the app. In the main.js file of each directory, there is a ping function where you can enter your own IP or some other echo service of your choice. Make sure you start the echo server prior to any of these examples if you would like to monitor them externally.

These tests were done soley using the Android OS, as there were no reports of issues with IOS.

Note: The use of the usesCleartextTraffic declaration and android.permission.INTERNET permission in all 3 tests are only required for the ping function I added for these tests.


The example directory:

When running this mobile app on a Pixel 6 emulator, select the +BG button to start running a background watcher. At this point you can send the app to the background (just return to the home screen), and the app will continue to run the background watcher indefinitely. The only time this does not seem to be the case is if the phone has aggressive battery optimizations, but these can be disabled through the settings on the phone itself.


The experiment1 directory:

This is the original example modified to match my initial architecture for my background service. I had an idea of how I thought things worked, and in combination with this comment from issue #84, I naively assumed I could just spawn background watchers and they would work. This is not the case, as a background watcher must be running prior to the app being sent to the background. I wanted to include this in case this was a common misconception.


The experiment2 directory:

This provides a simple example of only acting upon the watcher at a given interval. The watcher is always running though. All in all, there is not much different from this than the original example.


Takeaways:

If none of these examples helped you, and you are still having an issue, please provide an example of how you are implementing this plugin.

If this did help, and there are no other issues/concerns/misconceptions, I would recommend reverting back to v1.2.11

diachedelic commented 1 year ago

Thank you @alexandermccormick for getting to the bottom of this. I have reverted the WebView hack as of v1.2.13. Ensure that background watchers are created whilst the app is in the foreground, or pin the plugin to v1.2.12 if you really want to rely on the hack.

vdt2210 commented 1 year ago

Hi everyone. I have this issue on Nokia Android 11. I have modified the handleOnPause() and it's worked fine. Is there another way to fix it I am using "@capacitor-community/background-geolocation": "^1.2.13"

diachedelic commented 1 year ago

@taivo-digiex Ensure you add any background watchers while the app is still in the foreground.

vdt2210 commented 1 year ago

@taivo-digiex Ensure you add any background watchers while the app is still in the foreground.

Yes, I have. I'm using your example code and it working in background for about 5m before stop

diachedelic commented 1 year ago

Is your app sending each location in an HTTP request? Can you reproduce the problem using the demo app in the example/ directory of this repository?

vdt2210 commented 1 year ago

Is your app sending each location in an HTTP request? Can you reproduce the problem using the demo app in the example/ directory of this repository?

My app just received location's object and not sending to any database. Sorry if I misunderstand your first question

Is the /example is native app? If that so I don't know how to reproduce the problem in native app. My app is using ionic + angular

alexandermccormick commented 1 year ago

@taivo-digiex The example/ isn't any more or less "native" than using Ionic + Angular. Ionic is more of a component library, so the example/ only utilizes Capacitor. You will still use the same commands you do when working with an Ionic project, but instead of calling ionic cap [command] you will call capacitor directly with npx cap [command]. The example/ is more plain, as it does not use a web framework but instead simply uses one index.html file and one main.js. You'll find these located in the www directory inside example/.

By lightly modifying the example/ to better match your use case, it will help provide a more clear picture of what might be going on, either with the plugin or your specific architecture.

diachedelic commented 1 year ago

@taivo-digiex Does the notification remain after 5 minutes, or does it disappear?

vdt2210 commented 1 year ago

@taivo-digiex The example/ isn't any more or less "native" than using Ionic + Angular. Ionic is more of a component library, so the example/ only utilizes Capacitor. You will still use the same commands you do when working with an Ionic project, but instead of calling ionic cap [command] you will call capacitor directly with npx cap [command]. The example/ is more plain, as it does not use a web framework but instead simply uses one index.html file and one main.js. You'll find these located in the www directory inside example/.

By lightly modifying the example/ to better match your use case, it will help provide a more clear picture of what might be going on, either with the plugin or your specific architecture.

Thanks @alexandermccormick. I will try it

vdt2210 commented 1 year ago

@taivo-digiex Does the notification remain after 5 minutes, or does it disappear?

Its still appear with location icon on status bar.

Btw, I have a case when I modified handleOnPause() I had to add the background location permission. If not the app will stop all

diachedelic commented 1 year ago

When your application receives a location update, what does it do with it? Does it save it to disk? Display it on the screen in some way? How do you know exactly that it is stopping after 5 minutes?

vdt2210 commented 1 year ago

@diachedelic my app is getting location to show on screen only. I have used console.log(new Date)/count i++ to know when it stop on Android studio terminal