expo: Location.getCurrentPositionAsync not working on Android

expo: v22.0.0 Android: 6.0.1

export const getLocationAsync = async () => {
  let { status } = await Permissions.askAsync(Permissions.LOCATION);
  if (status !== 'granted') {
    throw new Error('Location permission not granted');
  }
  return await Location.getCurrentPositionAsync({ enableHighAccuracy: false, maximumAge: 15000 });
};

askAsync is working fine. But getCurrentPositionAsync will keep running forever. Setting any timeout will eventually go into Error: Location request timed out.

I have tried it in real device v6.0.1 (nexus 5). I have also tried Android 5 and 6 in simulator. No luck for all of them.

I guess this code may have some hints to it.

Actually I have been waiting for the fix since expo v18.0.0. I saw some issues somewhat related to this, but I could not find any solution. Any update on this will be very much appreciated.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 7
  • Comments: 36 (11 by maintainers)

Commits related to this issue

Most upvoted comments

My app depends greatly on Location Services, and after getting bug reports from some users we decided to investigate it further. We’ve mapped out some current problems, I hope it helps:

  • With enableHighAccurary: false and GPS only mode Location.getCurrentPositionAsync hangs indefinitely
  • With enableHighAccurary: true and GPS only mode Location.getCurrentPositionAsync hangs indefinitely
  • With enableHighAccuracy: true and high accuracy mode Location.getCurrentPositionAsync sometimes takes over 5 seconds to return
  • On some phones no configuration combination works. Location.getCurrentPositionAsync always errors with “Location services are disabled” or hangs indefinitely. It seems to happen mostly with Motorola phones. I was able to reproduce this on a Moto G4 device running Android 7.1.

I’ve also prepared a snack to facilitate tests. It’s configured to timeout after 5s instead of hanging indefinitely while running Location.getCurrentPositionAsync: https://snack.expo.io/@hugogrochau/location-tests

@raajnadar You are right!

screenshot_20180428-144800 screenshot_20180428-144803

If I set it to “Device only”, it halts forever at getCurrentPositionAsync(), and return timeout error, which matches the behaviour described above.

Result from Location.getProviderStatusAsync() when “Device only”:

{
  "gpsAvailable": true,
  "locationServicesEnabled": true,
  "networkAvailable": false,  // <-- This
  "passiveAvailable": true,
}

Maybe GPS on its own is useless for Expo apps, because Location.getCurrentPositionAsync() needs network to work?

Not sure if this is the source of this error. But I can now provide more instruction to user to enable the location function. Thanks!


@nikki93 I think at least this setting options can be put in Expo Location doc as the behaviour (halting forever) is unexpected and hard to debug.

@nikki93 Seems like the behavior is still the same. It is impossible to get the location while in “Phone only” mode (and not in “High accuracy” or “Battery saving”). And it is still not mentioned in the doc as @carsonwah suggested. I’m guessing this is not the wanted behavior ?

@tsapeta would be great to actually have this tagged in the expo document on the location page. Kind of annoying

@ricpar11 @rafaeluzzi your issue is completely different than described in this thread, so please move the discussion to this new topic #3221

Regarding issue described here, I’m working on it right now, will be back here soon 😉

@bhadkaria Unfortunately, for now I don’t see any workaround other than asking your users to enable high accuracy mode in Android’s location settings.

I did some more investigations and experiments - it seems like both FusedLocationProviderClient and LocationManager just don’t work properly with device only setting. Having this setting, I was also unable to find my location using Google Maps app, so it must be an internal issue on Android platform. The best solution I’ve found is to check whether the user’s setting is enough to get current location and if not, show a handy system dialog with an option to enable high accuracy mode. Example here:

screenshot_20190118-140741_google play services

I’m going to add such feature into getCurrentPositionAsync and watchPositionAsync methods. Returned promise will be rejecting with an error E_LOCATION_SETTINGS_UNSATISFIED if you cancel this dialog. Choosing “OK” will automatically modify the location mode to high accuracy which will allow you to get new locations.

I hope this solution will be satisfactory for you 😉

Hey everyone and thanks for all the details you gave about this issue 😄

I’ve been trying to quickly investigate this issue but with no success. I thought it might be something with the library we’re using to get the locations, however I also can’t get a location using Android’s APIs like LocationManager or FusedLocationProvider when the GPS only mode is enabled. I’ll do more research on this but if anyone is interested, feel free to help (it would definitely get this issue fixed faster) 🙂

Thanks everyone for the troubleshooting in this thread.

I can confirm that we are seeing issues on Android for Expo versions 30 and 31.

On my testing device (Android 8.1.0 / 27 Nokia 3.1) and with my app loaded in Expo.

  • Phone Mode: GPS Only -> App does not get location
  • Phone Mode: High Accuracy -> App gets location

I used the following code to track the location (default options):

Location.watchPositionAsync.bind(null, {}))

The problem persists in Expo v.25.0.0.

@vpontis do you mean an example in JS? In fact nothing will change there, this dialog will be shown during getCurrentPositionAsync and watchPositionAsync calls, but only when the network provider is not available. I’ll also add an option to opt out of this feature, but in that case this issue may continue to appear as network provider is required to get the position in some cases 😞

I found that Location.getCurrentPositionAsync() works just the first time I use the function. I was using it with no problems in one component, but after trying to call the function in another component it stared to hang (it hangs just in the second component that calls the function, the first one works normally).

edit: The problem was I was rendering two components at the same time (react navigation tabs, with lazy: false), and a apparently Location.getCurrentPositionAsync() does not like to be called too quickly, I tried to delay it with a setTimeout( () => Location.getCurrentPositionAsync({}).then(location => { //logic }), 2000 ); and now it’s working.

Turned on High accuracy on my device that fixed the issue!

Android Nougat - 7.1.1 Settings -> Location -> Mode and set to High accuracy