'expo location permissions work on android, but not on iOS
I have a react-native app that uses expo. The location permissions work on android, but not on iOS. On a real iPhone (iOS version 14.4.2), it does nothing. On a simulator, I get this error message:
[Unhandled promise rejection: Error: LOCATION_FOREGROUND permission is required to do this operation.] at node_modules/react-native/Libraries/BatchedBridge/NativeModules.js:103:50 in promiseMethodWrapper at node_modules/@unimodules/react-native-adapter/build/NativeModulesProxy.native.js:15:23 in moduleName.methodInfo.name at http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:293333:90 in watchPositionAsync$ at http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:293327:37 in watchPositionAsync
Update: I tried it on another Android device and it did not work, so maybe it works on my main Android phone because the permissions were already granted when running a previous version? There is a bug report about permissions breaking between Expo version 40 and 41 https://github.com/expo/expo/issues/12581
Here is what I'm using:
app.json:
{
"expo": {
"name": "Andiamo",
"slug": "andiamo_places",
"version": "1.0.0",
"orientation": "default",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"bundleIdentifier": "com.andiamoplaces.andiamotravelapp",
"supportsTablet": true,
"infoPlist": {
"NSLocationUsageDescription":
"The app needs permission to access your location, if you want to be located on the map.",
"NSLocationWhenInUseUsageDescription": "The app needs permission to access your location, if you want to be located on the map",
"NSLocationAlwaysUsageDescription": "The app needs permission to access your location, if you want to be located on the map",
"NSLocationAlwaysAndWhenInUseUsageDescription": "The app needs permission to access your location, if you want to be located on the map",
"NSPhotoLibraryUsageDescription": "The app needs permission to your camera roll, if you want to upload pictures.",
"NSCameraUsageDescription": "The app needs permission to your camera, if you want to take pictures from the app."
}
},
"android": {
"package": "com.andiamoplaces.andiamotravelapp",
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#FFFFFF"
},
"permissions": [
"CAMERA",
"LOCATION"
]
},
"web": {
"favicon": "./assets/favicon.png"
},
"description": ""
}
}
package.json:
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject",
"postinstall": "jetifier -r"
},
"dependencies": {
"@expo/vector-icons": "^12.0.0",
"@react-native-community/clipboard": "^1.5.1",
"@react-native-community/datetimepicker": "3.2.0",
"@react-native-community/masked-view": "0.1.10",
"@react-navigation/native": "^3.8.4",
"@use-expo/font": "^2.0.0",
"cross-fetch": "^3.1.4",
"expo": "^41.0.0",
"expo-camera": "~11.0.2",
"expo-cli": "^4.4.4",
"expo-clipboard": "~1.0.2",
"expo-facebook": "~11.0.5",
"expo-font": "~9.1.0",
"expo-image-manipulator": "~9.1.0",
"expo-image-picker": "~10.1.4",
"expo-location": "~12.0.4",
"expo-media-library": "~12.0.2",
"expo-permissions": "~12.0.1",
"expo-status-bar": "~1.0.4",
"firebase": "8.2.3",
"geolib": "^3.3.1",
"global": "^4.4.0",
"luxon": "^1.26.0",
"native-base": "^2.15.2",
"react": "16.13.1",
"react-devtools": "^4.13.2",
"react-dom": "16.13.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-41.0.0.tar.gz",
"react-native-color-picker": "^0.6.0",
"react-native-draggable-flatlist": "^2.6.1",
"react-native-gesture-handler": "~1.10.2",
"react-native-ionicons": "^4.6.5",
"react-native-maps": "0.27.1",
"react-native-material-menu": "^1.2.0",
"react-native-modal": "^11.10.0",
"react-native-pell-rich-editor": "^1.7.0",
"react-native-popup-menu": "^0.15.10",
"react-native-prompt-crossplatform": "^1.6.1",
"react-native-ratings": "^8.0.4",
"react-native-reanimated": "~2.1.0",
"react-native-safe-area-context": "3.2.0",
"react-native-safe-area-view": "^1.1.1",
"react-native-screens": "~3.0.0",
"react-native-simple-radio-button": "^2.7.4",
"react-native-switch": "^2.0.0",
"react-native-switch-selector": "^2.1.4",
"react-native-vector-icons": "^8.1.0",
"react-native-web": "~0.13.12",
"react-native-webview": "11.2.3",
"react-native-youtube-iframe": "^2.0.1",
"react-navigation": "^4.4.4",
"react-navigation-drawer": "^2.7.1",
"react-navigation-stack": "^2.10.4",
"react-navigation-tabs": "^2.11.1",
"react-redux": "^7.2.4",
"redux": "^4.1.0",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"@babel/core": "~7.9.0",
"jetifier": "^1.6.8"
},
"private": true
}
code:
startUserLocationUpdates = async () => {
const returns = await Location.watchPositionAsync(
{
accuracy: Location.Accuracy.BestForNavigation,
timeInterval: 1000,
// distanceInterval: 0,
},
(loc) => {
if (this.props.ShowLocation) this.centerMapTo(loc.coords.latitude, loc.coords.longitude);
this.props.onSetCurrentLocation({ latitude: loc.coords.latitude, longitude: loc.coords.longitude });
}
);
this._removeLocationUpdates = returns.remove;
};
Solution 1:[1]
An updated version of the Permissions
with formatted code.
if (Platform.OS !== "web") {
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") {
Alert.alert(
"Insufficient permissions!",
"Sorry, we need location permissions to make this work!",
[{ text: "Okay" }]
);
return;
}
}
In fact, I've had the opposite scenario; iOS
was working fine, but Android
did not without the code above.
<uses-permission android:name=...
in the AndroidManifest.xml is being automatically by Expo
, so you don't need to care about it and modify anything.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Daniel Danielecki |