expo: Background Location Tracking not working on iOS

🐛 Bug Report

Environment

Expo CLI 3.17.21 environment info:
  System:
    OS: macOS 10.15.4
    Shell: 3.0.2 - /usr/local/bin/fish
  Binaries:
    Node: 13.2.0 - /usr/local/bin/node
    Yarn: 1.19.2 - /usr/local/bin/yarn
    npm: 6.13.1 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  IDEs:
    Android Studio: 3.4 AI-183.6156.11.34.5692245
    Xcode: 11.4.1/11E503a - /usr/bin/xcodebuild
  npmPackages:
    expo: ^37.0.0 => 37.0.6 
    react: 16.9.0 => 16.9.0 
    react-native: https://github.com/expo/react-native/archive/sdk-37.0.0.tar.gz => 0.61.4 
    react-navigation: ^4.0.10 => 4.0.10 
  npmGlobalPackages:
    expo-cli: 3.17.21

This is a managed app targeting iOS and Android. There is no issue on Android, this issue only exhibits on iOS.

Steps to Reproduce

I am trying to get background location tracking working on iOS. It works fine on Android.

I’m requesting Location Permission like this:

  const { status } = await Permissions.askAsync(Permissions.LOCATION);
  console.log(`*** requestLocationPermission: ${status}`);

The task is defined in a top level scope:

    if (error) {
      console.log("LOCATION_TRACKING task ERROR:", error.message);
      return;
    }
    if (data) {
      const { locations } = data;
      const { coords, timestamp } = locations[0];
      const { latitude, longitude } = coords;
    
     ...
    }
  });

In the component where I want to track location:

function LocationSubscriber({ profile }) {
  useEffect(() => {
    startLocationTracking();
  });

  const startLocationTracking = async () => {
    await Location.startLocationUpdatesAsync(LOCATION_TASK_NAME, {
      accuracy: Location.Accuracy.Highest,
      timeInterval: 60000,
      distanceInterval: 0
    });
    const hasStarted = await Location.hasStartedLocationUpdatesAsync(
      LOCATION_TASK_NAME
    ); 
  };

  return <></>;
}

In app.json I have:

"ios": {      
      "infoPlist": {
        "UIBackgroundModes": ["location"],
        ...
      }
    },

I bumped my app version and resubmitted through the app store to make the app.json changes take effect.

Expected Behavior

Location should be tracked. This works in Android, but not iOS

Actual Behavior

In iOS when calling Location.startLocationUpdatesAsync I get this error: Background Location has not been configured. To enable it, add 'location' to 'UIBackgroundModes' in Info.plist file.

Question

One thing I’ve noticed is in the documentation it says Permissions.LOCATION permission must be granted. On iOS it must be granted with Always option — see Permissions.LOCATION for more details.

When the app requests permission it doesn’t give the “Always” option, only the “When using the app”, “One time” and “Never” options. Is there a special way to request permission such that “Always” is an option? Is that necessary?

Reproducible Demo

I don’t think background location tracking is demoable in a Snack? If so please advice on how

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 16 (2 by maintainers)

Most upvoted comments

SDK 40…has the error on Android - “Not authorized to use background location services” and on iOS - “Background Location has not been configured. To enable it, add location to UIBackgroundModes in Info.plist file.]” Any one else facing the same ?

For anyone continue looking for a reason, in IOS 13 above apple have updated your policy below, so you dont see option Always in prompt: image