How to fix [Unhandled promise rejection: Error: Location provider is unavailable. Make sure that location services are enabled.]
Asked Answered
E

11

7

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?

  1. Ran expo upgrade once more to ensure that all of your packages are set to the correct version.

  2. Deleted package-lock.json and node_modules and ran npm install.

  3. Set Location.getCurrentPositionAsync({accuracy:Location.Accuracy.High})

  4. 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
      });
    }```
    
Extremism answered 23/7, 2020 at 18:14 Comment(4)
Have you set the location permissions inside AndroidManifest.xml?Hoarfrost
I don't need to because I am in Expo's managed workflow. Expo does this for me. That is the advantage compared to React Native's bare workflow where you have to set these permissions in the AndroidManifest.xml. All this was working perfectly on Expo 37. It's only after migrating to Expo 38 that the problems began.Extremism
This seems to be an active GitHub issue at their side.. github.com/expo/expo/issues/9377 hope it will be fixed soon.Shivery
There is an issue about this: github.com/expo/expo/issues/14248. And also a fix: github.com/expo/expo/pull/14281Commanding
F
6

If anyone is still fighting with this problem - please check if you have added:

 "android": {
  "permissions": ["ACCESS_BACKGROUND_LOCATION"]
},

in your app.json file

Flemming answered 2/2, 2021 at 19:33 Comment(4)
Thanks for sharing your solution but this only works if your app can justify a continuous/regular monitoring of the user's position like food delivery or driving / navigational apps. If your app can't justify a continuous/regular monitoring of the user's position, it will not be approved by Google Play Store during deployment. Including this permission may solve the problem locally but my app was rejected by Google Play Store because I can't justify a continuous/regular monitoring of the user's position.Extremism
do i have to restart expo, or the emulator when adding this to the app.json?Syncopate
Expo restart should be enough, imoFlemming
This is not required in expo projects in development mode. Check the Github issue github.com/expo/expo/issues/5504Holinshed
S
5

change

let location = await Location.getCurrentPositionAsync({});

for:

let location = await Location.getLastKnownPositionAsync({
          accuracy: 6,
        });
Salver answered 31/8, 2021 at 0:36 Comment(1)
This did work for me. But I cant find this in the docs or on github. docs.expo.dev/versions/v39.0.0/sdk/location/…. Here is no accuracy option, only 'requiredAccuracy'Malia
A
3

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");
  }
}
Amid answered 31/8, 2021 at 9:39 Comment(0)
D
1

I solved this problem like this:

Location.Accuracy.Balanced

changed to

Location.LocationAccuracy.Balanced

Dulcedulcea answered 4/9, 2021 at 12:1 Comment(0)
R
1

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

Relique answered 19/9, 2021 at 22:34 Comment(0)
T
0
let location: any = await Location.getCurrentPositionAsync({ enableHighAccuracy: true });

for me it worked, when i added enableHighAccuracy: true in Location.getCurrentPositionAsync.

Temporize answered 12/4, 2021 at 8:45 Comment(1)
Please reformat your answer with the code section.Bassett
K
0

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
Kalidasa answered 2/5, 2021 at 19:54 Comment(0)
H
0
  • 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

Holinshed answered 29/7, 2021 at 18:12 Comment(0)
P
0

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)
Plated answered 2/9, 2021 at 17:53 Comment(0)
A
0

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));
    });
Abbate answered 27/9, 2021 at 2:19 Comment(0)
K
-1

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
      }
Karee answered 19/10, 2020 at 17:54 Comment(3)
Location services in the phone have already been enabled. That is one of the first things I checked before trying anything else.Extremism
check my edited answer, you can use await Location.hasServicesEnabledAsync() to check if location service is enabled and then execute your code , or ask/handle otherwiseKaree
This doesn't solve the problem. Although location services have been enabled, the Location provider is unavailable. Location.getCurrentPositionAsync({ }) is not resolving to an object of type LocationObject. I have opened an issue on Expo's GitHub repository.Extremism

© 2022 - 2024 — McMap. All rights reserved.