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.6k stars 291 forks source link

getCurrentLocation timeout and watchPosition not working with Android Emulator #296

Open aardvarkk opened 2 years ago

aardvarkk commented 2 years ago

I just upgraded to Android Studio Arctic Fox 2020.3.1 and Android Emulator 30.7.5, and am now having trouble getting a GPS position returned within the emulator. I'm running Android Studio in Linux, although I'm not sure that matters.

I appear to have all permissions granted, in that the Location permissions show under Location settings in the emulator and a copy of hasLocationPermissions() from the example app returns true. I've set the timeout quite high (20 seconds), and am never getting a value back. I have also added a position watch and nothing seems to come back from there.

adb logcat doesn't appear to show anything interesting related to the GPS from what I can tell. No obvious errors are spit out to react native or logcat while starting up the app.

I'm not sure where else exactly I should be looking to try to debug this issue.

aardvarkk commented 2 years ago

I can confirm that the same codebase produces a valid position when freshly installed on a physical device -- this only appears to be a problem in the emulator.

The emulator is a Pixel 4a API 30 targetting Android 11.0 (x86).

aardvarkk commented 2 years ago

Well... I have no idea how this magically fixed itself but the issue seems to be gone now. Sigh.

I had uninstalled and reinstalled the app several times to trigger the permissions request and it all seemed fine. I ended up writing a sample native Kotlin GPS Fused Location app to check that I could retrieve the values in the emulator at the native level. That succeeded.

Then I tried to run the React Native app from Android Studio rather than the command prompt, and that also worked.

Now I'm back to running it directly from the command prompt and everything is back to normal.

Closing with frustration at having no idea what fixed this.

aardvarkk commented 2 years ago

Well, I'm having troubles with this again. I'm able to get back a cached position, but not one that appears to update.

I've now forked the code and added some logging in, and what I've found so far is that in the callback for onLocationAvailability, the locationAvailability has isLocationAvailable set to false. However, LocationUtils.isLocationEnabled(context) returns true. The little error check here does a boolean AND in order to determine whether or not to throw an error, so nothing gets bubbled up as an error because only one of the conditions is false.

Now I just have to figure out why isLocationAvailable is false...

aardvarkk commented 2 years ago

So the issue turns out to be that the default value of PRIORITY_BALANCED_POWER_ACCURACY for the accuracy just... doesn't work in the emulator? I just happened to try it in my native testing code and swapped over to that value from the values I had inserted based on the Android tutorials for setting up a location request, which instruct you to use PRIORITY_HIGH_ACCURACY.

After switching my native code test to use the balanced settings, I got the same isLocationAvailable: false value. Just changing my RN-level code to request accuracy: { android: 'high' } fixed all of the problems I was seeing.

My only recommendation from this bug would be to perhaps throw a warning/error if isLocationAvailable is false, even if isLocationEnabled is true. I will leave it open for the time being in hopes other people may find it if they run into the same weird issue.

Agontuk commented 2 years ago

@aardvarkk thanks for your investigations & detailed explanations. There's a lot to digest here, so I'll check if anything can be done to improve the consistency of native module.

About isLocationAvailable, it can return false sometimes even if the location is enabled. You can read the docs here (although it's kind of vague) https://developers.google.com/android/reference/com/google/android/gms/location/LocationAvailability#public-boolean-islocationavailable

aardvarkk commented 2 years ago

@Agontuk Yes -- I'm definitely seeing isLocationAvailable return with false even though location is enabled. My concern is that inside of the react-native-geolocation-service there's the following code:

      if (!locationAvailability.isLocationAvailable() &&
        !LocationUtils.isLocationEnabled(context)
      ) {
        locationChangeListener.onLocationError(
          LocationError.POSITION_UNAVAILABLE,
          "Unable to retrieve location."
        );
      }

My code was silently failing because only one of those conditions was false (isLocationAvailable). So I didn't get any errors bubbling up to the React Native layer to indicate that anything was wrong. I would just add a watchPosition and it would appear to succeed... but nothing would come through. getCurrentPosition was a bit more informative in that it would just timeout (if I explicitly added the timeout), but I think having some kind of error for this situation would have been helpful to point me in the right direction without having to dive into the native code.

I would basically just suggest changing the && here to an || in your code to fix my concern. Then I would have received an explicit error in this situation.

leonidlewis commented 2 years ago

Thank you for your kind explanation, And I've got the same issue. I've got this error. {"PERMISSION_DENIED": 1, "POSITION_UNAVAILABLE": 2, "TIMEOUT": 3, "code": 3, "message": "Location request timed out"} And I can't get the watchPosition. How can I fix it in React Native? "react-native-geolocation-service": "^5.3.0-beta.3", "@react-native-community/geolocation": "^2.0.2",

const subscribeLocationLocation = () => { watchID.current = Geolocation.watchPosition( position => { const currentLocation = { longitude: JSON.stringify(position.coords.longitude), latitude: JSON.stringify(position.coords.latitude), elevation: JSON.stringify(position.coords.altitude), }; console.log('location changed----', currentLocation) setLocation(currentLocation); }, error => { console.log('Location set- Error--', error); setLocation(null) }, { enableHighAccuracy: false, maximumAge: 3600000, }, ); };

efstathiosntonas commented 1 year ago

cross posting this here just in case someone want to test this possible fix: https://github.com/Agontuk/react-native-geolocation-service/issues/174#issuecomment-1343015525

leonidlewis commented 1 year ago

I can fix it

On Thu, Dec 8, 2022 at 12:27 PM Efstathios Ntonas @.***> wrote:

cross posting this here just in case someone want to test this possible fix: #174 (comment) https://github.com/Agontuk/react-native-geolocation-service/issues/174#issuecomment-1343015525

— Reply to this email directly, view it on GitHub https://github.com/Agontuk/react-native-geolocation-service/issues/296#issuecomment-1343057710, or unsubscribe https://github.com/notifications/unsubscribe-auth/AT3NYX5PXKZ6FIYAPSES6VDWMILAVANCNFSM5BPLOHGQ . You are receiving this because you commented.Message ID: @.*** com>