Saw
Saw

Reputation: 135

Using Expo Location to find background location permissions error

I am trying use expo-location and expo-task-manager to find the users position both when the app is in the foreground and in the background. I am compiling the code using expo without using Xcode. The problem is that the code I provide gives me two errors:

[Unhandled promise rejection: Error: One of the `NSLocation*UsageDescription` keys must be present in Info.plist to be able to use geolocation.]
at node_modules\@babel\runtime\helpers\construct.js:null in <global>
at node_modules\@babel\runtime\helpers\wrapNativeSuper.js:null in _wrapNativeSuper
- ... 3 more stack frames from framework internals

and:

[Unhandled promise rejection: Error: Background Location has not been configured. To enable it, add `location` to `UIBackgroundModes` in Info.plist file.]
at node_modules\@babel\runtime\helpers\construct.js:null in <global>
at node_modules\@babel\runtime\helpers\wrapNativeSuper.js:null in _wrapNativeSuper
- ... 3 more stack frames from framework internals

these errors refer to the infoPlist setup within my App.json:

"infoPlist": {
        "UIBackgroundModes": ["location"],
        "NSLocationWhenInUseUsageDescription": "To allow the user to start recording a run...",
        "NSLocationAlwaysUsageDescription": "To allow the distance to be measured even when the phone is turned off"
        "NSLocationAlwaysAndWhenInUseUsageDescription": "Allow $(PRODUCT_NAME) to use your location to track your runs"
      }

These errors ocurr even though it is clear that the UIBackgroundModes is set up as well as the NSLocationWhenInUseUsageDescription and NSLocationAlwaysUsageDescription.

Code that is being run:

App.js:

import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import UserLocation from "./UserLocation"

export default function App() {

  return (
    <View style={styles.container}>
      <UserLocation />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

UserLocation.js:

import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import * as Location from 'expo-location';
import * as TaskManager from 'expo-task-manager';

const LOCATION_TRACKING = 'location-tracking';

var l1;
var l2;

export default function UserLocation() {

    const [locationStarted, setLocationStarted] = React.useState(false);

    const startLocationTracking = async () => {
        await Location.startLocationUpdatesAsync(LOCATION_TRACKING, {
            accuracy: Location.Accuracy.Highest,
            timeInterval: 5000,
            distanceInterval: 0,
        });
        const hasStarted = await Location.hasStartedLocationUpdatesAsync(
            LOCATION_TRACKING
        );
        setLocationStarted(hasStarted);
        console.log('tracking started?', hasStarted);
    };

    React.useEffect(() => {
        const config = async () => {
            let resf = await Location.requestForegroundPermissionsAsync();
            let resb = await Location.requestBackgroundPermissionsAsync();
            if (resf.status != 'granted' && resb.status !== 'granted') {
                console.log('Permission to access location was denied');
            } else {
                console.log('Permission to access location granted');
            }
        };

        config();
    }, []);

    const startLocation = () => {
      
        startLocationTracking();
    }

    const stopLocation = () => {
        setLocationStarted(false);
        TaskManager.isTaskRegisteredAsync(LOCATION_TRACKING)
            .then((tracking) => {
                if (tracking) {
                    Location.stopLocationUpdatesAsync(LOCATION_TRACKING);
                }
            })
    }

    return (
        <View>
          {locationStarted ?
              <TouchableOpacity onPress={stopLocation}>
                  <Text style={styles.btnText}>Stop Tracking</Text>
              </TouchableOpacity>
              :
              <TouchableOpacity onPress={startLocation}>
                  <Text style={styles.btnText}>Start Tracking</Text>
              </TouchableOpacity>
          }
        </View>
    );
}

const styles = StyleSheet.create({
    btnText: {
        fontSize: 20,
        backgroundColor: 'green',
        color: 'white',
        paddingHorizontal: 30,
        paddingVertical: 10,
        borderRadius: 5,
        marginTop: 10,
    },
});

TaskManager.defineTask(LOCATION_TRACKING, async ({ data, error }) => {
    if (error) {
        console.log('LOCATION_TRACKING task ERROR:', error);
        return;
    }
    if (data) {
        const { locations } = data;
        let lat = locations[0].coords.latitude;
        let long = locations[0].coords.longitude;

        l1 = lat;
        l2 = long;

        console.log(
            `${new Date(Date.now()).toLocaleString()}: ${lat},${long}`
        );
    }
});

full verion of app.js:

{
  "expo": {
    "name": "FinalHopefully",
    "slug": "FinalHopefully",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/icon.png",
    "userInterfaceStyle": "light",
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "assetBundlePatterns": [
      "**/*"
    ],
    "ios": {
      "supportsTablet": true,
      "infoPlist": {
        "UIBackgroundModes": ["location"],
        "NSLocationWhenInUseUsageDescription": "To allow the user to start recording a run...",
        "NSLocationAlwaysUsageDescription": "To allow the distance to be measured even when the phone is turned off"
        "NSLocationAlwaysAndWhenInUseUsageDescription": "Allow $(PRODUCT_NAME) to use your location to track your runs"
      }
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#ffffff"
      }
    },
    "web": {
      "favicon": "./assets/favicon.png"
    }
  }
}

Upvotes: 1

Views: 1057

Answers (1)

If you're using expo-dev-client and EAS you have to rebuild your app after making these changes, and if you're are building locally you need to run npx expo prebuild --clean -p ios to regenerate your iOS files and update your Info.plist

Upvotes: 0

Related Questions