facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
116.49k stars 24.01k forks source link

Geolocation 'enableHighAccuracy' on Android always times out #7495

Closed Findiglay closed 5 years ago

Findiglay commented 8 years ago

Developing an Android app, whilst debugging on my Android Device running on 6.1, the geolocation api always returns an error callback with the message Location request timed out.

navigator.geolocation.getCurrentPosition(
      (position) => {
        console.log(position);
       },
       (error) => {
        console.log(error)
      },
      {enableHighAccuracy: true, timeout: 20000, maximumAge: 10000}
);

If I toggle enableHighAccuracy option to false, the api works fine. In high accuracy mode, the timeout always takes as long as I specify in the timeout option i.e. 20 seconds.

I've tried running with dev mode turned off.

Should high accuracy mode work in Android?

Findiglay commented 8 years ago

@acapop77 Forgot to mention also that permissions are enabled using:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

acapop77 commented 8 years ago

I have same problem on RN 0.25.1, difference is, for me problem persists for high and low accuracy. Finally I found something that makes it work, but is not a solution.

Here is what worked for me - assuming that you use stock android avd - emulator:

  1. In android emulator device go to "Settings > Location" (like you would on the actual device) and set Mode to High accuracy.
  2. Go back to application.
  3. Press "Extended controls" button (represented by "..."). Next in Location section you will see GPS data point data and "Send" button below. Just click on the "Send" and close extended controls menu.
  4. Reload application.

This works for me - on 'one time only base'. Each time I want to reload app I need to go 3-4 steps again. But at least this way I get Geolocation to work, and do not get timeout error.

rossthedevigner commented 8 years ago

I'm experiencing something similar in 0.24. Even though <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> is in my AndroidManifest.xml, I receive the red error stating:

"Looks like the app doesn't have the permission to access location. Add the following line..."

I am not using the emulator and instead building directly to the device.

Edit - this also happens in 0.25.1

Findiglay commented 8 years ago

@acapop77 @rossthedevigner I'm also building directly to a Samsung S6 device.

rossthedevigner commented 8 years ago

@Findiglay Same here. I even tried doing a manual .apk install and I still received the error.

I'm trying a workaround where I loop through the permissions manifest and see if android.permission.ACCESS_FINE_LOCATION is enabled.

Daniel-ltw commented 8 years ago

Anyone having navigator.geolocation == undefined?

I am currently having this issue on my device.

Findiglay commented 8 years ago

There are various issues being reported here. I'm not sure that all are relevant to the specific issue with enableHighAccuracy.

I don't have any experience with android development, but I've found that if I edit LocationModule.java to hardcode the LocationOptions boolean highAccuracy = true; and rebuild, then my location will return correctly. I'm not certain whether or not the results are any different from those received with the setting enableHighAccuracy: false in the React-Native geolocation API, but it should be safe to assume this is operating in highAccuracy mode.

Could this mean the bug is happening in the bridge between the Geolocation API & the LocationModule?

shtefanntz commented 8 years ago

I am experiencing the same problem. I did the same as @Findiglay suggested and worked for a few times, but then I got only timeouts.

Any idea why this happens on real devices? :(

EugeneLiang commented 8 years ago

Having the same issue. I'm currently running the app on real devices, using RN 0.25.1.

I should add that I have already added the necessary Android permissions to the permissions manifest. But still timeouts.

shtefanntz commented 8 years ago

as a workaround, I enabled 'Allow mock locations' in android settings and installed an app that mocks the gps (look for fake gps in store). At least until this is fixed, development is not blocked

RoBYCoNTe commented 8 years ago

I guys, I was facing the same error but, after few retries with my colleagues, we notices something strange (but normal if you thing about GPS).

If you execute tests "inside your office" using physical device, the GPS locator can be disturbed by external things like walls, or by the simple reason that you are trying to do this operation "indoor" and, generally, this should be executed outdoor.

Well, after this we go outside from our office, we re-execute the tests and the device responds as planned (we don't received the Request timed out error).

My suggestion is: try geolocation using "enableHighAccuracy" set to true, if this fail (in the office this can fail), retry with false, this should work, in my case it did.

Hope this can helps.

Sean-Snow commented 8 years ago

+1

kiatweitan commented 7 years ago

Same issue here whether enableHighAccuracy is set to true or false. It works on GenyMotion emulators but not on any real devices (tested on Samsung, Nexus, Mi). Enabled permission in AndroidManifest.xml Code:

                navigator.geolocation.getCurrentPosition(
                    (position) => {
                        console.log(position);
                    },
                    (error) => console.log(new Date(), error),
                    {enableHighAccuracy: true, timeout: 10000, maximumAge: 3000}
                );  
chinloongtan commented 7 years ago

setting enableHighAccuracy to either true or false doesn't work for me. omitting the 3rd argument for getCurrentPosition to use default values from native module works for me.

alexHlebnikov commented 7 years ago

Same problem here with LGE Nexus 5 (Android 6.0). On Android 5.1.1 and 4.3 there is no such problem. In emulator with Android 6.0 there is no such problem. boolean highAccuracy = false; doesn't works. RN 0.28.0.

alexHlebnikov commented 7 years ago

Hey guys, I've found temporary fix - this package https://github.com/lucasferreira/react-native-android-permissions

JonathanWi commented 7 years ago

Any updates or fix for this? Everything works fine on Simulator and pre 5.0 devices, after that only timeout, and I desperately need a fix for an already available app!

sattaman commented 7 years ago

+1

sattaman commented 7 years ago

This issue is affected by the locationMode setting on the device. When location mode is set to either high accuracy or device only, geolocation times out. It works correctly when location mode is set to battery saving

willoughby commented 7 years ago

I've had the same problem, I took a punt and removed the 3rd argument. And its now working.

navigator.geolocation.getCurrentPosition( (position) => { console.log(position); }, (error) => console.log(new Date(), error), {enableHighAccuracy: true, timeout: 10000, maximumAge: 3000} //removed this );

aelsabbahy commented 7 years ago

I'm assuming this is related to: https://productpains.com/post/react-native/add-android-m-permissions-model-support

right?

willoughby commented 7 years ago

No that was for the location timeout issue

sattaman commented 7 years ago

Yes I had just discovered removing the 3rd argument seems to be a fix.

We haven't fully device tested yet but it seems that android version 22, with device mode set to either high accuracy or device only, will cause the cause the location to timeout, when the 3rd argument is included regardless of settings. It seems to not affect android version 23.

JonoH commented 7 years ago

Same experience my side, except android version 23 only works with the 3rd argument when enableHighAccuracy is set to false (true causes location to timeout). Also tested on android version 22, 21, 20 & 19 and it seems the presence of the 3rd argument causes a timeout in all cases. Removing that argument seems to be the only reliable fix.

DWboutin commented 7 years ago

Removing the 3rd argument just make me have the popup of "Location request timed out" instantly instead of waiting the until the timeout is done. Setting enableHighAccuracy to false, doesn't work either.

On my emulator, the Location is only available when i open the emulator settings and send a location (check the screenshot).

Is there a way to get it automatically?

screen shot 2016-08-21 at 6 42 52 pm

alexHlebnikov commented 7 years ago

In my case setting enableHighAccuracy to false solved the problem.

dlvx commented 7 years ago

Having the same problem here, both on emulator and on device, and tried with both true and false for enableHighAccuracy

page-fault-in-nonpaged-area commented 7 years ago

I just outright get "undefined is not an object (evaluating 'navigator.geolocation.getCurrentPosition')"

I tried checking if(navigator), that returned true, but if(navigator.geolocation) returned false.

Also, doing this on device on Android 5.1 OnePlus One. Developer mode enabled, AndroidManifest permissions included, mock locations on/off, everything.

page-fault-in-nonpaged-area commented 7 years ago

also, it didn't seem to ask me for location permissions 🤔despite me deleting the app on device and the output folder on my mac.

page-fault-in-nonpaged-area commented 7 years ago

I can't actually debug remotely either since I'm using React Realm and that thing has HUGE problems that screw the chrome remote debugger inside-out.

L3V147H4N commented 7 years ago

I have a similar Issue, may app doesn't always timesout BUT it does it a lot, when other geolocation apps work just fine everytime the one with RN has very poor geolocation. Im using RN 0.32 but I had the same issue with every version, for some reason geolocation in RN es very weird and poor (at least on Android)

leo7r commented 7 years ago

Same issue here, testing on real device.

julien-rodrigues commented 7 years ago

Running into this and this is really annoying :/

lwinkyawmyat commented 7 years ago

I'm having the same issue on Android 6.0.

luisfuertes commented 7 years ago

+1

sattaman commented 7 years ago

I found a solution was to not add a 3rd parameter , and to use the library linked above (https://github.com/lucasferreira/react-native-android-permissions) on android version >=23 to request android M permissions.

sattaman commented 7 years ago

Just spotted PermissionsAndroid has now been added to RN. So use this to request if on android >= 23

https://facebook.github.io/react-native/docs/permissionsandroid.html

luisfuertes commented 7 years ago

But i have Android 5.1.1 on my device. On this v. of android, Geolocation must works fine, no?

sattaman commented 7 years ago

23 is 6.0 onwards. I also found I needed to not add the 3rd parameter in order for it to work on everything.

dlvx commented 7 years ago

I managed to get this to work, but it could be different for you. Newer versions of RN (Mine is 0.32.1) include a file called MainApplication.java (Besides MainActivity.java). The React Native Mapbox GL Docs says you have to include the ReactNativeMapboxGLPackage into MainActivity.java, but you have to do it in MainApplication.java so it would look something like this:

MainApplication.java

` . . .

@Override
protected List<ReactPackage> getPackages() {
  return Arrays.<ReactPackage>asList(
      new MainReactPackage(),
      new ReactNativeMapboxGLPackage()
  );
}

}; `

And MainActivity.java would remain the same as always.

My Android version is 23 so I am still using the permissions from the manifest xml

luisfuertes commented 7 years ago

With GPS activated on device, App return the location fine, but if i turn it off, location return: error: No available location provider.

How can i force device to active GPS location?

kylebebak commented 7 years ago

This is maddening =/

I had getCurrentPosition working on my Genymotion Android emulator for the last few weeks, but now it's failing again.

I'm using Genymotion's GPS widget to set the location. I've installed Google Maps on the emulator, and Google Maps can read my location just fine.

I have all the necessary permissions, and I'm even using the PermissionsAndroid module like @sattaman suggested. It seems like the behavior is non-deterministic, in that it works one day and is broken the next.

saberking commented 7 years ago

I'm on RN 0.31 and removing the third parameter worked for me too! Real device, Nexus 5X, Android 6.

xoxoxoooxx commented 7 years ago

I have same problem on RN 0.34.1, but remove the third parameter can fix it Setting enableHighAccuracy to false don't solve this problem

arielconde commented 7 years ago

Same problem with me on RN 0.32, tried with Android 22 & 23,

enableHighAccuracy to true or false, doesn't work for me removing third parameter causes immediate "Location request timeout" however restarting my device makes its work, but will be broken after some time,

now, to get the users location i just use this: https://github.com/mauron85/react-native-background-geolocation

parkerproject commented 7 years ago

@acondense where do you set the code for background-geolocation, because it doesn't seem to be running the location function

miyabi commented 7 years ago

I met the same problem on RN 0.35 with Android 23 and 24, however works fine with Android 22. It might be related to Android 6.0 runtime permission system: http://stackoverflow.com/questions/32224534/access-fine-location-permission-error-emulator-only

I use this library to avoid this problem and it works fine! https://github.com/yonahforst/react-native-permissions

nigelnindo commented 7 years ago

Removing the third parameter fixed it for me too 💯 💯 💯

ddresch commented 7 years ago

Removing the third parameter worked 👍

It wasn't that clear from the beginning which parameter everybody was talking about, the method parameter or the third parameter of the options object.

To be precise it's the third parameter of the getCurrentPosition method, which looks something like that at the end:

navigator.geolocation.getCurrentPosition(
    (position) => {
       ...
    },
    (error) => alert(error.message)
)
vasiliy-sarzhynskyi commented 7 years ago

Finally I came with the following solution (the same idea as described above):

export const detectCurrentLocation = (successCallback, errorCallback) => {
    let navigatorOptions = {}
    if (Platform.OS === 'android' && Platform.Version === 23) {
        navigatorOptions = {
            enableHighAccuracy: false,
            timeout: 10000,
            maximumAge: 0
        }
    }

    navigator.geolocation.getCurrentPosition(
        position => successCallback(detectedLocation),
        error => errorCallback(error),
        navigatorOptions
    )
}

It works on devices (tested on Android 21, 22 & 23), but for Android 23 it's critically slow: 5 - 10 seconds.

Has anybody used LocationServices.FusedLocationApi as a workaround for this purpose in react-native (implementing natively, in Java code for Android)?