I have enable location services on my Android device, but I keep getting the above error. It prompts me for my permissions request upon loading Expo (for the first time) but I still get the promise rejection. It used to work fine, but all of a sudden, stopped working. Below is my code requesting the permissions, and executing the location.
Note: This works fine on iOS, and this is in managed workflow.
useFocusEffect(
React.useCallback(()=> {
let isActive = true;
async function getLocationAsync() {
let { status } = await Location.requestForegroundPermissionsAsync()
if (status !== 'granted'){
setErrorMsg('Permission to access location was denied')
return;
}
let location = await Location.getCurrentPositionAsync({});
setLocation(location);
console.log('Location permissions granted')
}
console.log(location)
getLocationAsync()
console.log(Permissions.LOCATION)
console.log('Location status above')
return () =>{
isActive = false
}
},
[],
)
)
Call the function in the catch block until you get the coordinates.
getLocationAsync = async () => {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
this.setState({
errorMessage: 'Permission to access location was denied',
});
console.log('Permission to access location was denied')
}else{
try{
let location = await Location.getCurrentPositionAsync({ enableHighAccuracy: true });
const { latitude, longitude } = location.coords
});
}catch(error){
// Call the function until get the coordinates
this.getLocationAsync();
}
}
Main Problem:
I am using expo-location in my Android app in order to find the gps coordinates of the user. I have read and used the sample code provided in the expo documentation. My main problem is that, Location.getCurrentPositionAsync({}) returns Location provider is unavailable. Make sure that location services are enabled. This is my code below:
useEffect(() => {
(async () => {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
setErrorMsg('Permission to access location was denied');
return;
}
let location = await Location.getCurrentPositionAsync({});
console.log(location);
})();
}, []);
Status returns granted but getCurrentPositionAsync({}) returns an error. I implemented a janky solution by using try-catch blocks and running getCurrentPositionAsync({}) again in the catch block, which seems to work. This is my code below:
useEffect(() => {
(async () => {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
setErrorMsg('Permission to access location was denied');
return;
}
try {
var location = await Location.getCurrentPositionAsync({});
} catch {
location = await Location.getCurrentPositionAsync({});
}
console.log(location);
})();
}, []);
Does anyone know why this is happening?
EDIT: I tried to run the sample code posted in the expo-location documentation using their snack example. Same result. Could this be a problem with my phone/area? I've tested it with two phones, and both return the same error.
I think location variable can't log / use directly and this is the way that I retrieve location:
let { status } = await Location.requestPermissionsAsync();
let location = await Location.getCurrentPositionAsync({});
if (status !== 'granted') setErrorMsg('...');
const { coords } = location;
if (coords) {
const { latitude, longitude } = coords;
}
I have just upgraded my app from Expo SDK 37.0.0 to 38.0.0. The app works fine on iOS but on Android I get the following warning and the app doesn't geolocate me on the map.
Development environment :
Expo SDK 38.0.0 (managed workflow)
React Native 0.62
Maps provider : Google Maps on Android
react-native-maps: 0.27.1
React: 16.11.0
Device : Honor 8X/Android 10
Expected result : The app should geolocate me (the user) based on my position.
Actual result : The app doesn't geolocate me (the user) based on my position.
Warning :
[Unhandled promise rejection: Error: Location provider is unavailable.
Make sure that location services are enabled.]
What have I tried so far?
Ran expo upgrade once more to ensure that all of your packages are set to the correct version.
Deleted package-lock.json and node_modules and ran npm install.
Set Location.getCurrentPositionAsync({accuracy:Location.Accuracy.High})
Set Location.getCurrentPositionAsync({ enableHighAccuracy: true })
import * as Location from 'expo-location';
import * as Permissions from 'expo-permissions';
async _getLocationAsync() {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
/* If user hasn't granted permission to geolocate himself herself */
Alert.alert(
"User location not detected",
"You haven't granted permission to detect your location.",
[{ text: 'OK', onPress: () => console.log('OK Pressed') }]
);
}
let location = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.High });
this.setState({
userLat: location.coords.latitude,
userLng: location.coords.longitude,
navGeoStatus: true,
lat: location.coords.latitude,
lng: location.coords.longitude
});
}```
If anyone is still fighting with this problem - please check if you have added:
"android": {
"permissions": ["ACCESS_BACKGROUND_LOCATION"]
},
in your app.json file
change
let location = await Location.getCurrentPositionAsync({});
for:
let location = await Location.getLastKnownPositionAsync({
accuracy: 6,
});
I've tried all of the other solutions above, and nothing works. The solution actually works below.
Use this :
await Location.getLastKnownPositionAsync({});
instead of :
await Location.getCurrentPositionAsync({});
Edited:
I've come up with a new solution if you wanted to use getCurrentPosition, not the last known position. You can use this code below
export default async function getLocation() {
await Location.enableNetworkProviderAsync().then().catch(_ => null);
const status = await Location.hasServicesEnabledAsync();
if(status){
const getCurrentPosition = async () => await Location.getCurrentPositionAsync()
.then(loc => loc)
.catch(_ => null)
let location = await getCurrentPosition();
while(location === null){
location = await getCurrentPosition();
}
return location;
}else{
throw new Error("Please activate the location");
}
}
I solved this problem like this:
Location.Accuracy.Balanced
changed to
Location.LocationAccuracy.Balanced
I am still getting this problem in September 2021
A cut and paste of the current EXPO location guide is giving the same error in this question.
https://docs.expo.dev/versions/latest/sdk/location/
My solution was to replace
let location = await Location.getCurrentPositionAsync({});
setLocation(location);
with
await Location.watchPositionAsync({ enableHighAccuracy: true }, (loc) => setLocation(loc));
And it worked immediately.
I was only testing getCurrentPositionAsync as 'iteration 1' with a view to eventually using watchPositionAsync anyway. I spent too much time trying to get current position to work when I didn't need it.
So this solution would suit if you want regular updates of the phone's location rather than just a one time update.
Link to watchPositionAsync documentation
let location: any = await Location.getCurrentPositionAsync({ enableHighAccuracy: true });
for me it worked, when i added enableHighAccuracy: true in Location.getCurrentPositionAsync.
In my case App with below mentioned code was working fine in Android Phone (S8) But had the above issue with the android emulator. Please refer to the spec I had. After multiple attempts I have upgraded expo SDK which solved the issue.
Short Answer:
Upgrade Expo SDK to version 41
Spec I had previously :
Expo SDK: 40
NPM: 6.14.11
Android Studio: 4.1.1
Virtual Device: API 30
Code: Example code by Expo documentation
import React, { useState, useEffect } from 'react';
import { Platform, Text, View, StyleSheet } from 'react-native';
import * as Location from 'expo-location';
export default function App() {
const [location, setLocation] = useState(null);
const [errorMsg, setErrorMsg] = useState(null);
useEffect(() => {
(async () => {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
setErrorMsg('Permission to access location was denied');
return;
}
let location = await Location.getCurrentPositionAsync({});
setLocation(location);
})();
}, []);
let text = 'Waiting..';
if (errorMsg) {
text = errorMsg;
} else if (location) {
text = JSON.stringify(location);
}
return (
<View style={styles.container}>
<Text style={styles.paragraph}>{text}</Text>
</View>
);
}
Solution worked for me:
expo upgrade
expo: ~4.8.1
Google Maps on Android
react: ~16.13.1
Had the same problem.
How I managed to fix it?
Location.getCurrentPositionAsync({accuracy: Location.Accuracy.Highest});
using accuracy as Highest is important to fix this issue
Hope it works for you
Few days back I got stucked on same problem, might be Expo Location module is having some issues. For the time solution is to wrap the location related code in try catch, run until you got your location object.
Like so : 🍻
let location;
let locationSuccess = false;
while (!locationSuccess) {
try {
location = await Location.getCurrentPositionAsync({
accuracy: Location.Accuracy.High,
});
locationSuccess = true;
} catch (ex) {
console.log("retring....");
}
}
console.log("Location",location)
Do you can use getLastKnownPositionAsync how 2nd option:
await Location.requestPermissionsAsync();
Location.getCurrentPositionAsync({accuracy: Location.Accuracy.High})
.then(location => console.log(location))
.catch(() => {
Location.getLastKnownPositionAsync({accuracy: 6})
.then(location => console.log(location));
});
It seems like user has granted permission to the app to use location.
But this warning occurs when location services in the phone itself hasn't been enabled.
search for it in the settings and enable it
Edited answer (added code to handle warning):
let gpsServiceStatus = await Location.hasServicesEnabledAsync();
if (gpsServiceStatus) {
let location = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.High });
this.setState({
userLat: location.coords.latitude,
userLng: location.coords.longitude,
navGeoStatus: true,
lat: location.coords.latitude,
lng: location.coords.longitude
});
} else {
alert("Enable Location services"); //or any code to handle if location service is disabled otherwise
}
In my react native app, I ask for permission to access the camera roll as so:
getPermissionAsync = async () => {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (status !== "granted") {
alert("Sorry, we need camera roll permissions to make this work!");
}
await this.setState({ permission: status === "granted" });
};
_pickMedia = async (index, type) => {
if (this.state.permission != true) {
await this.getPermissionAsync();
}
if (this.state.permission == true) {
// get image
} catch (E) {
console.log(E);
}
}
};
This works as expected during testing, but for my published version on Google Play, status is returned as undetermined whether or not the user gives permission. What does this mean?
Upgrading the react-native-community#react-native-permissions to 2.0.0 solves the issue.
Refer : https://github.com/react-native-community/react-native-permissions/issues/295
I have an app which developed in react-js. I want to integrate this app into react-native-webview. everything I right but I have two problems.
1-how can I access current location of the user in react-native-webview.
2-how can I debug my react-js(webpage) app inside react-native-webview.
for first problem
if I run webpage in a mobile browser and click on that event I'm getting current location of the user and at the same time when my react-native app getting started, I'm invoking permission for current location so in react-native-debugger i'm getting current location of user.i followed the similar example but this is related to react-native.
exact problem is how can I access the current location of webview in react-native-webview
for second problem
when I'm clicking on the event to fetch current location it is not showing the current location so ** I want to see what is error/response of that event**. because it is in webview I can access react-native logs in react-native-debugger but cannot see the web view logs in the debugger.I followed this one also but I don't know where to put that android config code.
my react-native code
import React, {Component} from 'react';
import {PermissionsAndroid} from 'react-native';
import { WebView } from "react-native-webview";
export default class App extends Component {
constructor(props){
super(props);
// To see all the requests in the chrome Dev tools in the network tab.
XMLHttpRequest = GLOBAL.originalXMLHttpRequest ?
GLOBAL.originalXMLHttpRequest :
GLOBAL.XMLHttpRequest;
// fetch logger
global._fetch = fetch;
global.fetch = function (uri, options, ...args) {
return global._fetch(uri, options, ...args).then((response) => {
console.log('Fetch', { request: { uri, options, ...args }, response });
return response;
});
};
}
async requestLocationPermission() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
'title': 'Location Access Permission',
'message': 'Stanplus would like to use your location ' +
'so you we track you.'
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can use the location");
if (typeof window !== 'undefined' && typeof window.navigator !== 'undefined' && navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
console.log(position.coords.latitude,'success');
},
(error) => {
console.log(error,'fail')
},
{ enableHighAccuracy: false, timeout: 5000, maximumAge: 10000 }
);
}
} else {
console.log("Location permission denied")
}
} catch (err) {
console.warn(err)
}
}
componentDidMount() {
this.requestLocationPermission();
}
render() {
return (
<WebView
source={{uri: 'https://3fa4f958.ngrok.io/steptwo'}}
style={{marginTop: 20}}
onMessage={(event)=> console.log(event.nativeEvent.data)}
scalesPageToFit={true}
javaScriptEnabled = {true}
/>
);
}
}
my React.js code which accesses current location
if (navigator.geolocation) {
alert('event clicked');//in react-native app its showing the alert
navigator.geolocation.getCurrentPosition(
//but inside here react-native can't execute because of location permission issue
position => {
let latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
let geocoder = new window.google.maps.Geocoder();
//do other stuff----------
}
)
}
** I want to fetch current location when user click on webpage event inside react-native app and how to debug webview code**
please help stuck since 2 days ):
A few steps are needed to get it working on Android.
Add this line to your AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
And then in your app you'll need to request location once before the webview can request it. Do it like so in your view:
import { PermissionsAndroid } from 'react-native';
...
PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Location Access Permission',
message: 'We would like to use your location',
buttonPositive: 'Okay'
}
);
And then also on your webview add the property:
geolocationEnabled={true}
you need to add geolocationenabled https://facebook.github.io/react-native/docs/webview#geolocationenabled