Sigge Lundqvist
Sigge Lundqvist

Reputation: 11

Expo React native asks for location permissions in simulator but not in built app

App has been working fine for a while but now it's not prompting users for location permission which results in the features using location failing. On both simulator and physical device running expo go, the user is prompted to give permission to location data. (both iOS and Android) All other permissions it needs it asks for (push, camera and calendar)

export default function CheckIn(props) {
const { todayEvents } = useSelector(({ checkin }) => checkin);

const [venueIdd, setVenueId] = useState(0);
const [modalVisible, setModalVisible] = useState(false);
  const [status, setStatus] = useState(null);
  const [backgroundLocationPermission, setBackgroundLocationPermission] =
    useState(null);
  const dispatch = useDispatch();

  TaskManager.defineTask("updateLocation", ({ data: { locations }, error }) => {
    if (error) {
      return;
    }
    dispatch(sendBackgroundLocation(locations[0].coords, venueIdd));
  });
  async function registerBackgroundFetchAsync() {
    return BackgroundFetch.registerTaskAsync(BACKGROUND_FETCH_TASK, {
      minimumInterval: 60 * 15, // 15 minutes
      stopOnTerminate: false, // android only,
      startOnBoot: true, // android only
    });
  }

  async function unregisterBackgroundFetchAsync() {
    return BackgroundFetch.unregisterTaskAsync(BACKGROUND_FETCH_TASK);
  }

  React.useEffect(() => {
    dispatch(getTodaysEvents());

    const askPermission = async () => {
      let getForeground = await Location.getForegroundPermissionsAsync();
      if (getForeground.status !== "granted") {
      let { status } = await Location.requestForegroundPermissionsAsync();
      if (status !== "granted") {
        Alert.alert("Permission to access location was denied");
        return;
      } else {
        let backgroundPermissions =
          await Location.requestBackgroundPermissionsAsync();
        if (backgroundPermissions.status == "granted") {
          await AsyncStorage.setItem("background_permission", "true");
        }
      }
      }
    };
    askPermission();
  }, []);
  const checkIn = async (index) => {
    let temp = [...todayEvents];
    temp[index].isCheckedIn = true;
    setVenueId(temp[index].venueId);

    const backgroundStatus = await AsyncStorage.getItem(
      "background_permission"
    );

    // if (backgroundStatus !== null) {
    Location.startLocationUpdatesAsync("updateLocation", {
      timeInterval: 120,
      distanceInterval: 0.01,
      foregroundService: {
        notificationTitle: "Company title",
        notificationBody:
          "Information in body",
      },
      accuracy: Location.Accuracy.Highest,
    }).then((response) => {
      // console.log("RESPONSE LOCATION", response);
    });
    // }

    setTimeout(() => {
      const stopped = Location.stopLocationUpdatesAsync("updateLocation");
    }, 43200000);

    let { coords } = await Location.getCurrentPositionAsync();
    dispatch(userCheckIn({ lat: coords.latitude, long: coords.longitude }));
  };
  const checkOut = async (index) => {
    const stopped = Location.stopLocationUpdatesAsync("updateLocation");

    let temp = todayEvents;

    temp[index].isCheckedIn = false;
    //dispatch(userCheckOut()); // This is what I commented out
    // And the two rows below is added
    let { coords } = await Location.getCurrentPositionAsync();
    dispatch(userCheckOut({ lat: coords.latitude, long: coords.longitude }));
  };
  const review = (index, value) => {
    setModalVisible(true);
    setTimeout(() => {
      setModalVisible(false);
      setTimeout(() => {
        props.navigation.goBack();
      }, 300);
    }, 1500);
    let temp = todayEvents;
    temp[index].review = value;
    dispatch(giveEventFeedBack(temp[index]));
  };

From the app.json following iOS Location permissions are defined:

NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription

And for Android:

ACCESS_BACKGROUND_LOCATION
ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION

Upvotes: 1

Views: 4256

Answers (1)

Fiston Emmanuel
Fiston Emmanuel

Reputation: 4849

There's a scenario when the user recently choose the NEVER ASK AGAIN option for that permission. The next time the app attempt to ask it, the request resolves in denied status silently without launching the request permission popup modal.

If this is the case, the app can force the user to grant permission manually in app settings

You can handle this situation like this


const permission = await Location.getForegroundPermissionsAsync();

// Detect if you can request this permission again

if (!permission.canAskAgain || permission.status === "denied") {
  /**
   *   Code to open device setting then the user can manually grant the app
   *  that permission
   */

  Linking.openSettings();
} else {
  if (permission.status === "granted") {
    // Your actually code require this permission
  }
}



While the solution above doesn't work, Review this ongoing issue in Expo SDK 44 - https://github.com/expo/expo/issues/15273

Upvotes: 7

Related Questions