Agontuk / react-native-geolocation-service

React native geolocation service for iOS and android
https://www.npmjs.com/package/react-native-geolocation-service
MIT License
1.61k stars 291 forks source link

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

Open ravirajn22 opened 4 years ago

ravirajn22 commented 4 years ago

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.

BTW, thanks for the library

Agontuk commented 4 years ago

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 ?

ravirajn22 commented 4 years ago

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.

Agontuk commented 4 years ago

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 ?

ravirajn22 commented 4 years ago

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?

Agontuk commented 4 years ago

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.

ravirajn22 commented 4 years ago

Better we discuss the flow and api design before implementing.

Agontuk commented 4 years ago

Sure, let me know if you have any suggestion.

savv commented 4 years ago

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

ravirajn22 commented 4 years ago

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.

sdandois commented 2 years ago

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

Marcuspo commented 2 years ago

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

SurajMohanty02 commented 1 year ago

How can i use watchposition in react native background action?

aqil07 commented 1 year ago

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) ?


//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) {....
     .....
kyadalu1 commented 1 year ago

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