react-native-background-geolocation icon indicating copy to clipboard operation
react-native-background-geolocation copied to clipboard

Background Location emit location every 60 seconds without phone moving

Open EasonHeee opened this issue 2 years ago • 6 comments

Your Environment

  • Plugin version: 4.10.0
  • Platform: iOS
  • OS version: 16
  • Device manufacturer / model: iPhone 14 PM
  • React Native version (react-native -v): "react-native": "0.70.5"
  • Plugin config
BackgroundGeolocation.ready({
      // Geolocation Config
      desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
      stopTimeout: 3,
      distanceFilter: 20,
      batchSync: true, // <-- [Default: false] Set true to sync locations to server in a single HTTP request.
      maxBatchSize: 5,
      autoSyncThreshold: 5,
      autoSync: true, // <-- [Default: true] Set true to sync each location to server as it arrives.
      // config
      debug: false, // <-- enable this hear sounds for background-geolocation life-cycle.
      logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
      showsBackgroundLocationIndicator: false,
      //heartbeatInterval: 60,
      stationaryRadius: 50,
      stopOnTerminate: false, // <-- Allow the background-service to continue tracking when user closes the app.
      startOnBoot: true, // <-- Auto start tracking when device is powered-up.
      // // HTTP / SQLite config
      url: `${BASE_PATH}/status/v2/bg/batch`,
      headers: {
        "X-Auth-Token": token,
      },
    })

Expected Behavior

Background Location should emit location when moving after 200 meters and apply the distance filter 20 meters and batch sync: 5. So should move 100 meters then server get the location once.

Actual Behavior

Background Location emit location every 60 seconds without phone moving

Steps to Reproduce

import { BASE_PATH } from "openApi/base"; import React, { useEffect } from "react"; import { AppState } from "react-native"; import BackgroundGeolocation from "react-native-background-geolocation"; import { useDispatch } from "react-redux"; import { sendStatusWithoutNetworkRequest } from "redux/reducers"; import { getAuthToken } from "redux/selectors"; import type { AppDispatch } from "redux/store"; import statusUtils from "utils/statusUtils";

type Props = { setInitLocation: (: any) => void; setLocation: (: any) => void; };

export const RNLocationWatcher: React.FC<Props> = ({ setInitLocation, setLocation }) => { const token = getAuthToken(); const dispatch: AppDispatch = useDispatch(); // background location const useGeoLocation = () => { // 2. ready the plugin. BackgroundGeolocation.ready({ // Geolocation Config desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH, stopTimeout: 3, distanceFilter: 20, batchSync: true, // <-- [Default: false] Set true to sync locations to server in a single HTTP request. maxBatchSize: 5, autoSyncThreshold: 5, autoSync: true, // <-- [Default: true] Set true to sync each location to server as it arrives. // config debug: false, // <-- enable this hear sounds for background-geolocation life-cycle. logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE, showsBackgroundLocationIndicator: false, //heartbeatInterval: 60, stationaryRadius: 50, stopOnTerminate: false, // <-- Allow the background-service to continue tracking when user closes the app. startOnBoot: true, // <-- Auto start tracking when device is powered-up. // // HTTP / SQLite config url: ${BASE_PATH}/status/v2/bg/batch, headers: { "X-Auth-Token": token, }, }).then((state) => { // 3. Start tracking! if (!state.enabled) { // 3. Start tracking! BackgroundGeolocation.start(function () { console.log("- Start BackgroundGeolocation listen success"); }); } // load init position BackgroundGeolocation.getCurrentPosition({ timeout: 30, // 30 second timeout to fetch location maximumAge: 5000, // Accept the last-known-location if not older than 5000 ms. desiredAccuracy: 2, // Try to fetch a location with an accuracy of 2 meters. samples: 2, // How many location samples to attempt. }).then((location) => { console.log("on start"); if (statusUtils.isValidLocation(location.coords)) { setInitLocation(statusUtils.reserveOnlyLatLonSpeedFields(location.coords)); setLocation(statusUtils.reserveOnlyLatLonSpeedFields(location.coords)); } });

  BackgroundGeolocation.watchPosition(
    (location) => {
      if (!statusUtils.isValidLocation(location.coords)) {
        return;
      }
      setLocation(statusUtils.reserveOnlyLatLonSpeedFields(location.coords));
      dispatch(
        sendStatusWithoutNetworkRequest({
          location: location.coords,
        })
      );
    },
    (errorCode) => {
      console.log("[RN foreground - watchPosition ERROR]", errorCode);
    },
    {
      interval: 3000,
      desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_NAVIGATION,
    }
  );
});

};

useEffect(() => { return useGeoLocation(); }, []);

useEffect(() => { return useAppState(); }, []);

const useAppState = () => { const subscription = AppState.addEventListener("change", (nextAppState) => { if (nextAppState === "active") { console.log("App has come to the foreground!"); // Start watching position while app in foreground. BackgroundGeolocation.watchPosition( (location) => { if (!statusUtils.isValidLocation(location.coords)) { return; } setLocation(statusUtils.reserveOnlyLatLonSpeedFields(location.coords)); dispatch( sendStatusWithoutNetworkRequest({ location: location.coords, }) ); }, (errorCode) => { console.log("[RN foreground - watchPosition ERROR]", errorCode); }, { interval: 3000, desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_NAVIGATION, } ); } else if (nextAppState === "inactive" || nextAppState === "background") { console.log("App has come to the background!"); // Halt watching position when app goes to background. BackgroundGeolocation.stopWatchPosition(); } }); return () => { subscription.remove(); }; };

return <></>; };

Context

Try to emit background location when App is in background and phone is moving.

Debug logs

Logs
Keep receiving location **every 60 seconds (pattern)** on our server while I was sitting in a library for 3 hours.
<img width="656" alt="image" src="https://user-images.githubusercontent.com/119822174/224890694-27a77755-eacf-481c-b9f5-6ce4f6e32410.png">

Battery died very quickly 
<img width="138" alt="image" src="https://user-images.githubusercontent.com/119822174/224890893-86bef74f-3394-4a1c-b119-8ffaea4a0b65.png">

EasonHeee avatar Mar 14 '23 04:03 EasonHeee

It's because you're using .watchPosition.

Do not use .watchPosition.

The only thing you need to do is call .start(). That's it.

Do not use .watchPosition.

christocracy avatar Mar 14 '23 12:03 christocracy

Hi Chris, thanks for replying. We also called stopWatchPosition when AppState is in Background. Should this be ok to use watchPosition or it can't be stopped even in background?

EasonHeee avatar Mar 15 '23 02:03 EasonHeee

You can stopWatchPosition in the background.

christocracy avatar Mar 15 '23 03:03 christocracy

Thanks Chris. Yes we called stopWatchPosition when App switched background. Any idea we still have the 60 seconds for a background location emit (is it because of default 60s heartbeat) ?

if (nextAppState === "inactive" || nextAppState === "background") {
console.log("App has come to the background!");
// Halt watching position when app goes to background.
BackgroundGeolocation.stopWatchPosition();
}

EasonHeee avatar Mar 15 '23 04:03 EasonHeee

is it because of default 60s heartbeat.

The plugin does not record locations in the heartbeat.

Are you observing the plugin logs in $ adb logcat *:S TSLocationManager:V to see what exactly is happing?

christocracy avatar Mar 15 '23 14:03 christocracy

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] avatar May 24 '24 01:05 github-actions[bot]

This issue was closed because it has been inactive for 14 days since being marked as stale.

github-actions[bot] avatar Jun 07 '24 01:06 github-actions[bot]