DEV Community

Sami
Sami

Posted on

Expo GPS Location + Task Manager

React Native Expo has a great package called expo-location which lets your app to access gps location in your react native app.

npx expo install expo-location

As we want to track gps even when the app is in the background, we would need task manager. Install it by:

npx expo install expo-task-manager

Now, create a new custom hook called useGPS like:

export default function useGPS() {
  const [locationStarted, setLocationStarted] = React.useState(false);

  useEffect(() => {
    (async () => {
      const res = await Location.requestForegroundPermissionsAsync();
      if (!res.granted)
        console.log('Foreground permission not granted!')

      const task = TaskManager.isTaskDefined(LOCATION_TRACKING);
      if (!task)
        console.log('TASK not defined')
    })();

  }, [])

  const startLocationTracking = async () => {
    await Location.startLocationUpdatesAsync(LOCATION_TRACKING, {
      accuracy: Location.Accuracy.Highest,
      timeInterval: 5000,
      distanceInterval: 0,
      foregroundService: {
        notificationTitle: 'MY_GPS_APP',
        notificationBody: "Location is used when running app",
      },
    }).catch(e => console.log('error in startlocationasync = ', e));

    const hasStarted = await Location.hasStartedLocationUpdatesAsync(
      LOCATION_TRACKING
    );
    setLocationStarted(hasStarted);
  };

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

  const stopLocation = () => {

    setLocationStarted(false);
    TaskManager.isTaskRegisteredAsync(LOCATION_TRACKING)
      .then((tracking) => {
        if (tracking) {
          Location.stopLocationUpdatesAsync(LOCATION_TRACKING);
        }
      })
  }
  return { startLocation, stopLocation, locationStarted }
}
Enter fullscreen mode Exit fullscreen mode

The parameters of Locatin.startLocationUpdatesAsync() are very important. If you do not pass foregroundService then the built apk will not work and you will see error in console saying,

Not authorized to use background location services.

Hence this is important

foregroundService: {
  notificationTitle: 'MY_GPS_APP',
  notificationBody: "Location is used when running app",
Enter fullscreen mode Exit fullscreen mode

In your view component, import the useGPS hook we created and call startLocation() on a button press, like:

function GPSView() {
  const { startLocation, stopLocation, locationStarted } = useGPS()

return (
    <View>
        <Button title="Stop Tracking" onPress={() => {
          stopLocation();
         }
        }></Button>
        <Button title="Start Tracking" onPress={startLocation}> 
        </Button>
    </View>)
}
Enter fullscreen mode Exit fullscreen mode

Task Manager is defined like this, and can be placed in any file, preferably at an entry file.


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;

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

Build your app with expo

npx expo start

and you will see console log of your location.

Top comments (0)