Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
ravirajn22 opened this issue Jul 2, 2020 · 14 comments
Open

Comments

@ravirajn22
Copy link

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

@Agontuk
Copy link
Owner

Agontuk commented Jul 15, 2020

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
Copy link
Author

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
Copy link
Owner

Agontuk commented Jul 19, 2020

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
Copy link
Author

ravirajn22 commented Jul 19, 2020

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
Copy link
Owner

Agontuk commented Jul 19, 2020

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
Copy link
Author

Better we discuss the flow and api design before implementing.

@Agontuk
Copy link
Owner

Agontuk commented Jul 20, 2020

Sure, let me know if you have any suggestion.

@Agontuk Agontuk pinned this issue Sep 5, 2020
@savv
Copy link

savv commented Oct 15, 2020

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

@ravirajn22
Copy link
Author

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
Copy link

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
Copy link

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

@SurajMohanty02
Copy link

How can i use watchposition in react native background action?

@aqil07
Copy link

aqil07 commented May 21, 2023

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) {....
     .....


@kyadalu1
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants