Brief summary after discussion and answers:
using EXPO sdk you cannot get the device location without grant FINE_LOCATION in android. FINE_LOCATION is the only method to get location, so, you cannot get the hardware.network.location. That means: with android > 6 you cannot get the current location using WIFI/mobile networks, you must enable Location.
Expo github discussion: https://github.com/expo/expo/issues/1339
The initial problem:
im working on a react-native application, using expo and react-native-maps, and i need to get the latitude and longitud of the user current position.
Im using navigator.geolocation API for that
with the GPS turned on i have no problems, but i need to get the current position without GPS, based on the network provider.
The problem is that when the application runs with expo on androiod > 6 i get this error:
21:50:53: Finished building JavaScript bundle in 449ms 21:50:55: Location services are disabled - node_modules\react-native\Libraries\BatchedBridge\NativeModules.js:80:57 in - node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:347:19 in __invokeCallback - ... 4 more stack frames from framework internals
In IOs and android <=5 it works great.
Here is the code of the component:
class MyComponent extends Component {
componentWillMount = () => {
this.getCurrentLocation();
}
getCurrentLocation = () =>
navigator.geolocation.getCurrentPosition(
(position) => {
let currentUserPosition = position.coords;
alert(JSON.stringify(currentUserPosition));
},
(error) => {
console.log(error);
},
{
enableHighAccuracy: false,
timeout: 20000,
maximumAge: 0,
distanceFilter: 10
}
);
}
And this are my package.json depencendies:
"dependencies": {
"expo": "23.0.4",
"native-base": "^2.3.5",
"react": "16.0.0",
"react-native": "0.50.4",
"react-native-extend-indicator": "^0.1.2",
"react-native-maps": "^0.19.0",
"react-native-maps-directions": "^1.3.0",
"react-native-router-flux": "4.0.0-beta.21",
"react-navigation": "1.0.0-beta.21",
"react-navigation-redux-debouncer": "^0.0.2",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
}
I expect that navigator.geolocation get the location based on the network provider in that situation (without gps), the specification saids that..
i also tried with the Geolocation API of expo (tried this example: https://snack.expo.io/@schazers/expo-map-and-location-example) , and with the GPS turned OFF i cant get my location..
so.. is there a way to achieve what i want? i am missing something?
EDIT (EXPO CONTRIBUTOR ANSWER):
I have posted the same at expo github (https://github.com/expo/expo/issues/1339), according to them it is imposible to get the current position using navigator.geolocation without any level of Location enabled in a android device.. so .. the only thing that could happen is that android versions older than 5 has location enabled by default and you can turn on just the GPS, and the versions 6 and forward you must specify the location level ..
any ideas?
EDIT2 (IMPORTANT !!):
I have confirmed this:
this is security settings of a Android 6 device, by default it uses GPS, i think that android 5 or lower doesnt, so thats the thing.. when i use the 2nd option it gets me the location !
the fact is that forcing a user to enable Location is like "hey, use your GPS!", and there are a lot of applications that gives you a aproximated position without turning on Location (like Uber for example), so the question is, is there a way that ONLY using wifi get the location with this api?
Geolocation is enabled by default when you create a project with react-native init . In order to enable geolocation in the background, you need to include the 'NSLocationAlwaysUsageDescription' key in Info. plist and add location as a background mode in the 'Capabilities' tab in Xcode.
Geolocation makes it possible, from any device connected to the Internet, to obtain all types of information in real time and locate the user with pinpoint accuracy at a given point in time. Geolocation technology is the foundation for location-positioning services and location-aware applications (apps).
The problem you are dealing with here is with EXPO, because the location request API has changed after Android 5(API 21).
Before API 21, you needed to add to ACCESS_FINE_LOCATION
(Both Wifi/Network and GPS providers) and ACCESS_COARSE_LOCATION
(only GPS permission) location permissions. However, since Android 5, the apis changes to android.hardware.location.network
and android.hardware.location.gps
.
When your target users include both Android 5 +/-. you need to add both permission types to your android manifest, for example:
<manifest ... >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- for Android 5.0 (API level 21) or higher. -->
<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:name="android.hardware.location.network" />
</manifest>
However, it seems that the people in expo, only included, the new permission in the android manifest. So what you need to do is to change android manifest. However, expo only gives access to pure JS part of the program and not to native codes. As a result, you need to detach from EXPO to add native modules or changes.
In expo documentation, the detachment process is explained in this link, the procedure is simple:
install expo package globally using npm:
npm install -g exp
Inside your project directory, run detachment code, it will build android and ios folders in your project directory:
exp detach
Then you can make the changes you need in android manifest file.
Common bug in Android. Try without using the third parameter:
getCurrentLocation = () =>
navigator.geolocation.getCurrentPosition(
(position) => {
let currentUserPosition = position.coords;
alert(JSON.stringify(currentUserPosition));
},
(error) => {
console.log(error);
}
);
So, I just digged a little into the code and basically all the LocationModule does is send the request directly to Android.
It just calls this method:
https://developer.android.com/reference/android/location/LocationManager.html#getLastKnownLocation(java.lang.String)
Now, if you read that, the location says FINE_LOCATION or COARSE_LOCATION.
Usually one just add the fine location permissions, but I am thinking that maybe to access the Wifi location you need to add the coarse permissions into the app. Do you have both?
https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_COARSE_LOCATION
If not, I would add that permissions into the app and try again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With