expo: Location.getCurrentPositionAsync() sometimes never responds or takes a very long time to respond
š Bug Report
I have slow performance on iOS (14), using Expo App (simulator - 11 and real device - 6s) or Standalone (real device - 6s).
Tried to add accuracy to Lowest, but I had same issue.
Works fine on Android.
Environment - output of expo diagnostics & the platform(s) youāre targeting
Expo CLI 3.27.12 environment info:
System:
OS: macOS 10.15.7
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 12.13.1 - ~/.nvm/versions/node/v12.13.1/bin/node
Yarn: 1.22.5 - /usr/local/bin/yarn
npm: 6.12.1 - ~/.nvm/versions/node/v12.13.1/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.9.3 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 14.0, DriverKit 19.0, macOS 10.15, tvOS 14.0, watchOS 7.0
Android SDK:
API Levels: 28
Build Tools: 30.0.2
System Images: android-29 | Google Play Intel x86 Atom
IDEs:
Android Studio: 4.0 AI-193.6911.18.40.6626763
Xcode: 12.0.1/12A7300 - /usr/bin/xcodebuild
npmPackages:
@expo/webpack-config: ^0.12.16 => 0.12.37
expo: ^39.0.3 => 39.0.3
react: 16.13.1 => 16.13.1
react-dom: 16.13.1 => 16.13.1
react-native: https://github.com/expo/react-native/archive/sdk-39.0.3.tar.gz => 0.63.2
react-native-web: ~0.13.14 => 0.13.14
npmGlobalPackages:
expo-cli: 3.27.12
Expo Workflow: managed
Reproducible Demo
import * as Location from 'expo-location';
async function getLocation() {
const start = Date.now();
await Location.getCurrentLocationAsync();
console.log(Date.now() - start); // consistently around 10,100ms
}
Snack reproducible demo -> https://snack.expo.io/@rvieceli/expo-issue-10756
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 32
- Comments: 104 (13 by maintainers)
@rvieceli I tried passing it balanced as value, and even that value worked for me, a higher value gave problems. This is my code now, including the request for permission to the user:
// Get permissions
const { status } = await Permissions.getAsync(Permissions.LOCATION); if (status !== 'granted') { return; }// Get location
const location = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.Balanced, });Try set accuracy low as below:
const location = await Location.getCurrentPositionAsync({ accuracy: isAndroid ? Location.Accuracy.Low : Location.Accuracy.Lowest, })I set Location.Accuracy.Balanced, which caused long time to get location sometimes. Android does not support Lowest. Although accuracy is low, it was accurate enough, and able to get location much faster than before.
https://forums.expo.io/t/location-getcurrentpositionasync-takes-10-seconds/19714/3
donāt.
Hey @Victor-Ross and @faroutchris. š
Using @IDjinnās implementation as an example, I have implemented an alternative solution that even takes into account the operating system-based timeout:
This implementation has worked for me. In the case of Android, if it donāt succeed on the first try (because the
getCurrentPositionAsyncmethod never resolves), on the second try everything happens almost instantly.Thank you for filing this issue! This comment acknowledges we believe this may be a bug and thereās enough information to investigate it. However, we canāt promise any sort of timeline for resolution. We prioritize issues based on severity, breadth of impact, and alignment with our roadmap. If youād like to help move it more quickly, you can continue to investigate it more deeply and/or you can open a pull request that fixes the cause.
So it seems that this is not a bug, and the documentation mentions this (https://docs.expo.io/versions/latest/sdk/location/)⦠What I ended up doing is using getLastKnownPositionAsync(), which is fast, to get the map started and then running getCurrentPositionAsync() in the background to get the more accurate location. Not the most elegant solution, but helps out.
This issue is stale because it has been open for 60 days with no activity. If there is no activity in the next 7 days, the issue will be closed.
I also tested different SDK versions.
Using Precise Location as ON SDK37 -> 0.025 seconds SDK38 -> 0.035 seconds SDK39 -> 10.012 seconds SDK40 -> 10.013 seconds
Using Precise Location as OFF SDK37 -> 10.02 seconds SDK38 -> 10.015 seconds SDK39 -> 10.016 seconds SDK40 -> 10.022 seconds
Still a recurring issue for me even with low accuracy
I resolved it with the following patch to convert to
FusedLocationProviderClient.getCurrentLocation.This changes the behavior of
Location.getCurrentPositionAsyncto returnnullon timeout. If the caller wants to retry, for example:The timeout comes from the interval based on the accuracy in
LocationHelpers.buildLocationParamsForAccuracy:The
Priorityis also mapped from accuracy.I had to upgrade the Play Services Location dependency and I donāt know what the implications of that are.
Same here, sometimes the method is stuckā¦
I confirm the workaround using
Location.watchPositionAsync(options, callback)instead ofLocation.getCurrentPositionAsyncis working which confirms there is most probably a problem with thegetCurrentPositionAsyncmethod.With the same accuracy and same implementation in the app,
watchPositionAsyncgives precise location under a second on iPhone andgetCurrentPositionAsynctakes more than 10sec.Location.installWebGeolocationPolyfill() await navigator.geolocation.getCurrentPosition(position => { const latitude = JSON.stringify(position.coords.latitude); const longitude = JSON.stringify(position.coords.longitude); reverseGeocode(position.coords); setCurrentLocation({ latitude, longitude }) return true; }, error => { console.log(āerror using navigator current positionā) }, { enableHighAccuracy: false, timeout: 2000, maxiumAge: 1000 })
this helps
@sk-phan @m-regragui Hi,bor. I use
watchPositionAsyncorgetCurrentPositionAsyncCanāt obtain precise positioning, with a difference of several hundred meters? Have you ever encountered it? Is there any solution?In our case, the issue of
getCurrentPositionAsynchanging seemingly indefinitely was much more prevalent on Android. It was like rolling the dice (especially on some devices): 50% of the time it would just hang. Thank you to everyone above for sharing your workarounds with setting timeouts and retries. We set ours to try again just once after 3 seconds, and after 3 more seconds revert togetLastKnownPositionAsync.Weāre very confused as to why this api can simply hang forever with no error, and why it doesnāt include documented options for timeouts.
This issue is still happening. Pretty surprised it has not been adressed. It used to work and now 10 seconds+ on ios to get a location whatever the accuracy is set
I am facing the same issue. Every time it takes more than 10 seconds in iOS to get location data. To prove the theory, I changed my library to @react-native-community/geolocation to get location and everything remains as it is. With @react-native-community/geolocation, I get response within a second. I am using expo-location 9.0.1
Sorry for pinging here again. We have added the retry functionality. However, on iOS the response continually takes a minimum of 10 seconds to resolve. Has anyone of you found a solution to this? Too afraid to try another library at this point. Thanks!
My experience here:
"expo-location": "15.1.1"This is more of an Android issue for me. I can pretty reliably reproduce
getCurrentPositionAsyncnever resolving on Android. Iāve never seen the issue of it not resolving on iOS, but frequently takes about 10 seconds. Itās weirdā¦I time the operation and iOS will consistently resolve in exactly10005mson separate calls. Not always thoughā¦on both platforms sometimes this call works great and quickly gives me the locationā¦itās very sporadic.The workarounds detailed in this thread have helped - mainly building the timeout around the
getCurrentPositionAsynccall and retrying. Iām usinggetLastKnownPositionAsyncto quickly get a location during startup, then following that up with an asynchronousgetCurrentPositionAsyncwith timeout/retrying.Thanks, @MattZ6! Yes, we are releasing your solution today! Hopefully, it works out!
Hey @Saad-Bashar! š
In my case, the implementation suggested in this https://github.com/expo/expo/issues/10756#issuecomment-1483254287 completely fulfilled the needs of the application Iām working on. I even use it with maximum accuracy.
Since the problem is the promise never resolves (or rejects), a simple timeout solved my problems. The people here on the forum can complement the answer.
Folks, we have been struggling with getting the user location. Our key feature of the app is clock in and clock out based on user location. We need precise accuracy. A lot of the complaints are coming due to the location issue.
In our app first we tried with
react-native-geolocation, then we moved toreact-native-geolocation-service. (at that time most probably the community one was not in active development, but now the package has come back to life it seems) Finally we decided to includeexpo-sdkin our bare react-native app to use theexpo-locationmodule. However, this module is also having issues, sometimes the methodgetCurrentPositionAsyncjust never responds and in general it takes quite a long time to get the lat and long back.May I please know from others, what did you do if you were in the same shoes as mine? Are you still using expo location with above workarounds or moved to a different package? We are also considering to purchase
react-native-background-geolocation. Would be really helpful to get some insights. Thanks a lot!I did something like that. See
Same issue here, but on Android. Got randomly stuck on āawait getCurrentPositionAsync({})ā.
Example of my code:
Sometimes it works flawlessly, but every now and then I get stuck in the getCurrentPositionAsync( ), the other functions and console.logs never get called. Tried with low accuracy, with interval, but nothing seems to help with the inconsistencies.
Hey @maralihart, awesome!
My problem is also in production with standalone app.
Can you share with us our permissions, dependencies (only from expo) and your implementation if is different from expo documentation?
Thank you. have a nice day!
Iām 100% sure if is related, but after our test in SDK38, we got this error in sentry
Cannot obtain current location: Error Domain=kCLErrorDomain Code=0 "(null)"We donāt have anything in QA sentry with SDK 39.Hi, iām facing almost the same issue, expo-location works fine for me in dev with Location.getCurrentPositionAsync() or Location.getLastKnownPositionAsync() but it doesnāt work on production.
Iām on SDK 49 and expo-location 16.1.0, iāve tried many things including the solution of @sk-phan, or change the play-services-location version in the build.gradle to 20 or 21.0.1.
Nothing worked. I managed to get the error message that shows only on production:
Error: Encountered an exception while calling native method: Exception occurred while executing exported method getLastKnownPositionAsync on module Expo Location: Found interface com.google.android.gms.lo cation.FusedLocation ProviderClient, but class was expected (declaration of ācom.google.android.gms.locati on.FusedLocation ProviderClientā appears in /data/app/
I donāt know what to do anymore, iām on free plan on Expo and iāve done my 30 builds this month just to try to resolve this issue, if someone has an new idea, i would like to test it⦠next month š¤£
Hey folks, just a side note, if youāre not using
LocationAccuracy.Highon Android it might take longer to acquire location since the device is not using all sensors to fetch the location. More info heredepends on you need whether you want to increase only when error or both situations(success,error)
Still facing the same issue on SDK ^49.0.6 with āexpo-locationā: ā~16.1.0ā š. Iāve tried the timeout methods and it fails on all attempts and even calling
getLastKnownPositionAsyncreturns null. The weird thing is that it worked flawlessly on a previous version of my app that used SDK 46 with āexpo-locationā: ā~14.3.0ā, and it was fast too. Iāll try and use react-native-geolocation-service and see if thatās any better.I used
react-native-geolocation-servicein bare project is faster thanexpo-locationhttps://github.com/Agontuk/react-native-geolocation-service/tree/master will expo team consider embed this package into expo location ?this is my code I used from above comment and it much faster but still not faster than
react-native-geolocation-service@findhumane be careful with
play-services-location:21.0.1, it can freeze the entire app: https://github.com/mrmans0n/smart-location-lib/issues/285, this module usesio.nlopez.smartlocation:library:3.3.3Just some feedback after we released the retry functionality. We have tracked the events from mix-panel. We have found out a lot of the location fetch succeeded on the 2nd and even on the 3rd attempt. At the same time we got a lot of location fetching errors. The error message is not fully visible but mostly it says something like this on android,
"{\"nativeStackAndroid\":[{\"lineNumber\":4,\"file\":\"LocationModule.java\",\"methodName\":\"getCurrentPositionAsync\",\"class\":\"jc.u\"},{\"lineNumber\":-2,\"file\":\"Method.java\",\"methodName\":\"invoke\",\"class\":\"java.lang.reflect.Method\"},{\"lineNumber\":8,\"file\":\"ExportedModu",...@MattZ6 since other devs might land on your comment, can you please edit it?
I believe adding it on
finallyimproves readability by a lot!Hey @efstathiosntonas, nice catch! Ideally, the increment of the current attempt should be outside of the
try/catch, or even in anfinallyblock:is anyone else getting a
std::runtime_error: Tried to reject a promise more than once.on iOS among these lines: (it rejects on line 120)https://github.com/expo/expo/blob/d3c15ee0b7dd3479e6a5927703ef55c90207ebb1/packages/expo-location/ios/EXLocation/EXLocation.m#L109-L121
Iām using the solution from @MattZ6 comment
@MattZ6 does this ever increment? Shouldnāt it stop execution on
throw new Error?the
tries += 1should be outside of thetry/catchotherwise it infinite loops:Same issue with
getCurrentPositionAsync()getting stuck. It seems to help with using lower accuracy but it isnāt 100% bulletproof.Iām using this workaround to force a response when the method get stuck.
I wait 5 seconds to get some response from the API call and if I didnāt get one, I reject the promise.
same issue here. I used to rely on only watchPositionAsync since that would also trigger on initial app launch. After upgrading to SDK 46, this does not seem to happen anymore. So now, on launch for first time, I have to use getCurrentPositionAsync({}) and that is taking 10 seconds. Creates a very unpleasant experience to the user. Android device seem to be faster, while iOS and Android emulators are slow. Any idea maybe how to force the watchPositionAsync to run on initial start maybe since that one is faster? Maybe set some small time interval first then increase it so you donāt get too many events?
Wanted to follow up here, any update? Same issue, looking for alternatives at the moment
Thanks friends
I followed the steps in the documentation as well as the lines stated above, but I still am stuck at āWaitingā for the location, never receiving the value
@AdamJNavarro We discovery more things during the investigation.
When Precise Location is OFF, SDK 38 and 39 are very slow, if we turn ON works fine in SDK38, but SDK39 is slow.