react-native-geolocation-service icon indicating copy to clipboard operation
react-native-geolocation-service copied to clipboard

How to turn GPS tracking off when app goes to background (Android)

Open ravirajn22 opened this issue 4 years ago • 14 comments

I have already asked this question before #74 . Previously I forked this library and added lifecycle listener inside the module and turned location updates on/off when react-native activity changes state.

You could ask me why implement inside the native module when you can directly listen for AppState inside JS and start and stop tracking. Reason: I wanted showLocationDialog to be true, as you know the showLocationDialog shows an activity over our activity hence, if I listen to AppState then I will get state events for this enable settings dialog also but I cannot know if this event is fired due to this dialog. If I stop tracking when this Dialog opens thinking my app has gone to background then user presses OK in this Dialog, 1. The native portion calls getLocationUpdates which will setup a callBack for fusedLocationProvider and 2. Since the Dialog closed after pressing OK, foreground event is fired from AppState which in turn will call start tracking again. Hence the first getLocationUpdates call and its callback can never be accessed in native side and the location update keeps running.

To solve this problem I hacked a solution on native side which starts and stops tracking location handling this edge case. Now I thought how to fix it in the library by default

Now Android 10 and onwards (Targeting) by default supports whenInUse and Always similar to iOS. What is the best to handle these cases in devices less than Android 10.

  • Do you have a straightforward idea to handle it in library? or
  • What is the best way to handle it in our code base instead of in library?

BTW, thanks for the library

ravirajn22 avatar Jul 02 '20 13:07 ravirajn22

Sorry for the late reply, unfortunately I don't think I completely understand the problem you described. Can you please provide a scenario that's causing the issue ?

Agontuk avatar Jul 15 '20 15:07 Agontuk

This issue occurs when you try to turn location tracking off/on when switching background/foreground with user not having proper location settings and option 'showLocationDialog' enabled.'showLocationDialog' itself fires appstate change affecting the whole flow. You can try in your sample app. As such it is not a bug but still.

ravirajn22 avatar Jul 15 '20 18:07 ravirajn22

So the main issue is that AppState change is being triggered when location dialog pops up. So it's difficult to figure out if the app is actually in background, am I right ?

Agontuk avatar Jul 19 '20 07:07 Agontuk

Yes, but I don't know where to solve this problem, inside lib or lib consumer.

If inside lib then we have to provide some option for android like 'canTrackInBackground: true/false'.

If the consumer of the library has to solve, then we need to give option to check and enable settings like a separate function like how we how do for location permission. So that the consumer can check settings before starting his location tracking with background/foreground logic.

I think giving the power to lib consumer will have greater benefits and flexibility, but in this case we cannot expect feature parity because iOS does not have API to turn on location services directly (its expected).

Do you have any other ideas?

ravirajn22 avatar Jul 19 '20 10:07 ravirajn22

Can't think of a good solution for this. If we use lifecycle listener in native side, they'll also get triggered when showing location popup. I'll think on this, and see if there's any solutions available out there.

Agontuk avatar Jul 19 '20 11:07 Agontuk

Better we discuss the flow and api design before implementing.

ravirajn22 avatar Jul 19 '20 15:07 ravirajn22

Sure, let me know if you have any suggestion.

Agontuk avatar Jul 20 '20 06:07 Agontuk

Couldn't you use PermissionsAndroid to request the location permissions and then watchPosition? And then clearWatch when the app is backgrounded?

savv avatar Oct 15 '20 08:10 savv

The issue happens when you start using showLocationDialog and when this dialog shows it will trigger appState change, but we will never know. This will create lot of subtle issues in our appState change logic.

Separating out showLocationDialog to its own function should solve this problem.

ravirajn22 avatar Oct 15 '20 10:10 ravirajn22

I'm having the same issue.

However, I've noticed that position tracking is not working by default while the application is in background, in which case the solution would be to simple not check for the app state and keep the default behavior.

Can someone confirm that when using watchPosition you don't get updates by default while in background? Thanks

sdandois avatar Dec 20 '21 13:12 sdandois

My only solution is make one native module in android. Follow this tutorial> https://medium.com/xgeeks/react-native-background-location-5602205ec795

Marcuspo avatar Apr 20 '22 13:04 Marcuspo

How can i use watchposition in react native background action?

SurajMohanty02 avatar Dec 06 '22 08:12 SurajMohanty02

Not sure if this will help the original ticket description issue or answer @SurajMohanty02 's question. What I have done is similar to what @savv has mentioned above.

To suggest a solution tothe question in the description, have you tried clearing the watch position with Geolocation.clearWatch(watchID) ?

  • When the "AppState" changes, I call my 'getLocation' Function, which makes use of the 'Geolocation.watchposition' helper.
  • When the user arrives at the destination, I clear the 'watchID' value.

//listen for app state change 
 //**main.tsx//
const subscription = AppState.addEventListener('change', async function (nextState) {
   await getLocation(locationDispatcher);        })

//**main.tsx continued//
useEffect(()=>{
 ......
                    stopObserving(watchId);
....



//**watchUser.ts//
//I also assign the watchID to a variable, which then gets stored as a state value.
export async function watchUser(dispatcherFunc: Function) {

    const watchID = Geolocation.watchPosition(

        async function success(userCurrPos) {....
     .....


aqil07 avatar May 21 '23 20:05 aqil07

https://www.youtube.com/watch?v=A5nvMQe-fpc

kyadalu1 avatar Sep 15 '23 05:09 kyadalu1