Home > database >  Difference between getCurrentPositionAsync and watchPositionAsync and why doesn't anything show
Difference between getCurrentPositionAsync and watchPositionAsync and why doesn't anything show

Time:12-26

I'm trying to get the position of the user and have it constantly updating and showing on the screen. I simply can't figure out why this isn't working :(

Here's my code:

import { Alert, Linking, Text, View } from "react-native";
import React, { useEffect, useState } from "react";

import * as Location from "expo-location";

export default function DateFinder() {
  const [hasForegroundPermissions, setHasForegroundPermissions] =
    useState(null);
  const [userLocation, setUserLocation] = useState(null);
  const [textPosition, setTextPosition] = useState("");

  useEffect(() => {
    const AccessLocation = async () => {
      function appSettings() {
        console.warn("Open settigs pressed");
        if (Platform.OS === "ios") {
          Linking.openURL("app-settings:");
        } else RNAndroidOpenSettings.appDetailsSettings();
      }

      const appSettingsALert = () => {
        Alert.alert(
          "Allow Wassupp to Use your Location",
          "Open your app settings to allow Wassupp to access your current position. Without it, you won't be able to use the love compass",
          [
            {
              text: "Cancel",
              onPress: () => console.warn("Cancel pressed"),
            },
            { text: "Open settings", onPress: appSettings },
          ]
        );
      };

      const foregroundPermissions =
        await Location.requestForegroundPermissionsAsync();
      if (
        foregroundPermissions.canAskAgain == false ||
        foregroundPermissions.status == "denied"
      ) {
        appSettingsALert();
      }
      setHasForegroundPermissions(foregroundPermissions.status === "granted");
      if (hasForegroundPermissions == true) {
        console.warn("bob");
        const location = await Location.watchPositionAsync(
          { enableHighAccuracy: true, accuracy: Location.Accuracy.Highest },
          (location) => {
            setUserLocation(location);
            setTextPosition(JSON.stringify(location));
          }
        );

        console.warn("bob");
      }
    };

    AccessLocation().catch(console.error);
  }, []);

  return (
    <View>
      <View>
        <Text>{textPosition}</Text>
      </View>
    </View>
  );

  const styles = StyleSheet.create({
    background: {
      backgroundColor: COLORS.background_Pale,
      flex: 1,
      // justifyContent: "flex-start",
      //alignItems: "center",
    },
    image: {
      flex: 1,
      // height: null,
      // width: null,
      //alignItems: "center",
    },
    scrollView: {
      backgroundColor: COLORS.background_Pale,
    },
  });
}

Sadly, it seems that nothing happens but I don't know why. Nothing shows up in the text and the watchPositionAsync doesn't update. Maybe I need to do something for the screen to update since useEffect only runs everytime the screen is updated but i can't seem to figure out what I should do.

CodePudding user response:

I've had the unfortunate experience of having to deal with Expo location... there's no technical explanation to my answer, it's simply a bug that everyone seems to be willing to ignore.

Setting any accuracy, interval, distance, or deferment seems to halt the whole watcher from ever working. Unless you only use accuracy and activityType and set them to BestForNavigation and Fitness, e.g.:

const location = await Location.watchPositionAsync(
    {
        accuracy: Location.Accuracy.BestForNavigation,
        activityType: Location.ActivityType.Fitness
    },
    (location) => {
        setUserLocation(location);
        setTextPosition(JSON.stringify(location));
    }
);

I have personally had a better experience using startLocationUpdatesAsync with tasks:

TaskManager.defineTask("recorder", ({ data, error }) => {
    if(error)
        return console.error(JSON.stringify(error));
    
    if(data) {
        const { locations } = data;

        // trigger a call to your component here
    }
});

// ...

Location.startLocationUpdatesAsync("recorder", {
    accuracy: Location.Accuracy.BestForNavigation,
    activityType: Location.ActivityType.Fitness
});

CodePudding user response:

Your state hasForegroundPermissions needs some time to update, so your if(hasForegroundPermissions == true) condition executes before the state update with previous value which in not true. So it won't execute the code inside the if condition. So change your code like below to get that condition to work

...
      if (foregroundPermissions.status === "granted") {
        setHasForegroundPermissions(true);
        console.warn("bob");
        const location = await Location.watchPositionAsync(
          { enableHighAccuracy: true, accuracy: Location.Accuracy.Highest },
          (location) => {
            setUserLocation(location);
            setTextPosition(JSON.stringify(location));
          }
        );
        console.warn("location",location);
      }
      else setHasForegroundPermissions(false);
...
  • Related