react-native-background-geolocation
react-native-background-geolocation copied to clipboard
[Question] `onLocation` event listener is not giving location sent via `geo fix` command
Your Environment
- Plugin version: 4.16.4
- Platform: Android
- OS version: all
- Device manufacturer / model: emulator
- React Native version (
react-native -v): 0.74.3 - Plugin config
{
heartbeatInterval: 60,
desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
logLevel: BackgroundGeolocation.LOG_LEVEL_OFF,
preventSuspend: true,
debug: false,
foregroundService: true,
enableTimestampMeta: true,
backgroundPermissionRationale,
disableLocationAuthorizationAlert: true,
logMaxDays: 1,
notification: {
smallIcon: 'drawable/ic_notification',
color: 'red',
sticky: true,
},
}
Context
We implement e2e tests in out app. We use Detox for this. In one of out test cases we have to change the user location a couple times. The problem is that the first location seems to work for first time but not on the following times.
Also tried to send direct commands to emulator adb -s emulator-15680 emu "geo fix 0 0" and via telnet geo fix 10 20, but i still get the first location in the onLocation event listener.
Tried this with google maps and the location is changing.
Code example we have in our app
import BackgroundTimer from "react-native-background-timer";
import BackgroundGeolocation, {
Location,
Subscription,
BackgroundGeolocationConfig,
} from "react-native-background-geolocation";
const FETCH_LOCATION_OPTIONS = {
desiredAccuracy: 5,
samples: 1,
};
const BACKGROUND_GEOLOCATION_CONFIG = (
backgroundPermissionRationale?: Record<string, string>,
): BackgroundGeolocationConfig => ({
heartbeatInterval: 60,
desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
logLevel: BackgroundGeolocation.LOG_LEVEL_OFF,
preventSuspend: true,
debug: false,
foregroundService: true,
enableTimestampMeta: true,
backgroundPermissionRationale,
disableLocationAuthorizationAlert: true,
logMaxDays: 1,
notification: {
smallIcon: 'drawable/ic_notification',
color: 'red',
sticky: true,
},
});
const isAuthenticated = useAppSelector((state) => state.auth.isAuthenticated);
const user = useAppSelector((state) => state.account.user);
const isUserActive = isAuthenticated && user.active;
useEffect(() => {
if (!isAuthenticated) return;
// Warning: You must call .ready(confg) once and only once, each time your app is launched. (for details, see docs)
if (!ready.current) {
const rationale = {};
BackgroundGeolocation.ready(BACKGROUND_GEOLOCATION_CONFIG(rationale))
.then(() => {
ready.current = true;
})
.catch(() => {});
}
}, [isAuthenticated]);
useEffect(() => {
if (!isUserActive) return;
function handleLocation(location: Location) {
console.log({ location });
}
const locationSubscription = BackgroundGeolocation.onLocation(handleLocation);
const heartSubscribtion = BackgroundGeolocation.onHeartbeat(() => {
console.log("Heartbeat");
BackgroundGeolocation.getCurrentPosition(FETCH_LOCATION_OPTIONS);
});
const interval = BackgroundTimer.setInterval(async () => {
try {
console.log("get current position via timer!");
await BackgroundGeolocation.getCurrentPosition(FETCH_LOCATION_OPTIONS);
} catch (e) {
console.log("timer sample fetch failed!");
}
}, 15000);
BackgroundGeolocation.start()
.then(() => {
console.log("Started geolocation");
})
.catch((e) => console.log("Error starting", e));
return () => {
interval && BackgroundTimer.clearInterval(interval);
locationSubscription?.remove();
heartSubscribtion?.remove();
BackgroundGeolocation.stop();
};
}, [isUserActive]);
Do you understand the plug-ins philosophy of operation (see the wiki)?
The plug-in is not listening to location-updates until the device is determined to be in-motion.
How does the plug-in determine the device is in-motion?
- Motion API (doesn’t operate in simulator)
- Exit a 200 meter geofence around the last known location.
the Android emulator is notorious for failing to fire geofences.
you can manually tell the plug-in to enter the “moving” state (and begin listening to your location updates) by calling .changePace(true) (read more at the wiki “Debugging”)
Now its more clear.
When the plugin will return to STILL state, if i manually change it with changePace(true) with Always permission ?
What happens if the plug-in state is moving and i run changePace(false) ?
Will restart of the app make the plugin give me the new location ? Will reinstall of the app make the plugin give me the new location ?
I am asking because: With the current setup and the info you provided (no motion api and failing geofence) I will have to somehow detect that the app is run by Detox to either change the pace to True, then to False, or to just ignore the location check. Both solutions are far from great.
Example of the test case I have
import { expect, device, waitFor } from "detox";
import { user } from "./commands";
import { elementById } from "./helpers";
let location = null;
beforeAll(async () => {
location = await user.getLocation();
await device.setLocation(location!.startLat, location!.startLon);
await user.launchAppLoggedIn();
});
describe("User location", () => {
it("should be at start", async () => {
// await sleep(5000);
await waitFor(elementById("I_ARRIVED_AT_START_BTN"))
.toBeVisible()
.withTimeout(16000);
await elementById("I_ARRIVED_AT_START_BTN").tap();
await elementById("CONFIRM_START_BTN").swipe("right", "fast", 1);
await expect(elementById("OPEN_START_DETAILS")).not.toBeVisible();
await expect(elementById("OPEN_END_DETAILS")).toBeVisible();
});
it("should be at end", async () => {
await device.setLocation(location!.endLat, location!.endLon);
await user.launchAppLoggedIn(); // try to launch a New Instance of the App, maybe we will have the correct location
// await sleep(5000);
await elementById("OPEN_END_DETAILS").tap();
await waitFor(elementById("I_ARRIVED_AT_END_BTN"))
.toBeVisible()
.withTimeout(16000);
await elementById("I_ARRIVED_AT_END_BTN").tap();
await elementById("CONFIRM_END_BTN").swipe("right", "fast", 1);
await expect(elementById("OPEN_END_DETAILS")).not.toBeVisible();
await expect(elementById("SUCCESS_ARRIVED")).toBeVisible();
});
});
Maybe i should try uninstalling the app and install then open with the "end" location ?
This issue is stale because it has been open for 30 days with no activity.
This issue was closed because it has been inactive for 14 days since being marked as stale.