Closed hasan642 closed 2 years ago
For device-specific issues, see http://dontkillmyapp.com
@christocracy I followed up the steps but not working, any another solution please? we need your help please!
I suggest you clone the sample app and install on your device.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You may also mark this issue as a "discussion" and I will leave this open.
Closing this issue after a prolonged period of inactivity. Fell free to reopen this issue, if this still affecting you.
Your Environment
react-native -v
): 0.64.3/ eslint-disable no-return-assign /
import React, { createRef, memo } from 'react'; import BackgroundGeolocation, { Location as BGLocation, Geofence as BGGeofence, GeofenceEvent as BGGeofenceEvent, } from 'react-native-background-geolocation'; import { connect } from 'react-redux'; import { RootState } from 'reducers'; import { GeofencingHelper, openSettings, SentryHelper } from 'utils'; import { ModalizeRefType } from 'components'; import { TWorkBranch } from 'types/employee'; import { Alert, Platform } from 'react-native'; import RequestPermissionModal from './RequestPermissionModal'; import { enableLogger, createStartsSeperatorTemplate, debug } from './config';
// type checking. interface GeofencingProps { isAutoClockInOutEnabled: boolean; workBranches: TWorkBranch[]; isFetchingEmployeeDataDone: boolean; } interface GeofencingState { isServiceReady: boolean; isServiceEnabled: boolean; isServiceStarted: boolean; isPermissionsGranted: boolean; } export type GeofenceAction = 'ENTER' | 'EXIT' | 'DWELL';
/**
A class component that handles geofencing feature. */ class Geofencing extends React.Component<Readonly, GeofencingState> {
constructor(p: GeofencingProps) {
super(p);
enableLogger &&
console.log(
createStartsSeperatorTemplate('START_GEOFENCING_LOGGER'),
'***'
);
}
// state. state = { isServiceReady: false, isServiceEnabled: false, isServiceStarted: false, isPermissionsGranted: false, };
// refs. requestAlwaysLocationRef = createRef();
/**
// ready the plugin. BackgroundGeolocation.ready({ reset: true, // Geolocation Config desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH, distanceFilter: 10, // Activity Recognition stopTimeout, // Application config debug, // <-- enable this hear sounds for background-geolocation life-cycle. logLevel, stopOnTerminate: false, // <-- Allow the background-service to continue tracking when user closes the app. startOnBoot: true, // <-- Auto start tracking when device is powered-up. enableHeadless: true, geofenceInitialTriggerEntry: true, preventSuspend: false, geofenceModeHighAccuracy: true, logMaxDays: 0, allowIdenticalLocations: false, notification: { title: 'geofencing', text: 'monitoring work locations', }, persistMode: BackgroundGeolocation.PERSIST_MODE_GEOFENCE, maxDaysToPersist: 0, maxRecordsToPersist: 0, backgroundPermissionRationale: { title: "Allow {applicationName} to access to this device's location in the background?", message: 'In order to track your activity in the background, please enable {backgroundPermissionOptionLabel} location permission', positiveAction: 'Change to {backgroundPermissionOptionLabel}', negativeAction: 'Cancel', }, }).then((state) => { enableLogger && console.log(createStartsSeperatorTemplate('IS_SERVICE_ENABLED?'), state.enabled, '\n');
// save
state.enabled
to local state. const isServiceEnabled = state.enabled; this.setState({ isServiceEnabled, isServiceReady: true, isServiceStarted: isServiceEnabled, }); }); }// listen to redux state to start/stop geofencing service. componentDidUpdate() { enableLogger && console.log( createStartsSeperatorTemplate('CAN_EXECUTE_DID_UPDATE?'),
${this.props.isFetchingEmployeeDataDone}\n
); if (!this.props.isFetchingEmployeeDataDone) return;// stop service if feature is off from the backend. enableLogger && console.log( createStartsSeperatorTemplate('SHOUL_STOPSERVICE?'), 'this.props.isFetchingEmployeeDataDone:- ',
${this.props.isFetchingEmployeeDataDone}\n
, 'this.state.isServiceEnabled:- ',${this.state.isServiceEnabled}\n
, 'this.props.isAutoClockInOutEnabled:- ',${this.props.isAutoClockInOutEnabled}\n
, 'full condition:- ', this.state.isServiceEnabled && this.props.isFetchingEmployeeDataDone && this.props.isAutoClockInOutEnabled === false, '\n**\n' ); if ( this.state.isServiceEnabled && this.props.isFetchingEmployeeDataDone && this.props.isAutoClockInOutEnabled === false ) { GeofencingHelper.stop().then(() => { console.log(createStartsSeperatorTemplate('SERVICE_STOPPED_BY_BACKEND_FLAG')); }); return; }enableLogger && console.log( createStartsSeperatorTemplate('GEOFENCE_STATE'), 'isAutoClockInOutEnabled:- ',
${this.props.isAutoClockInOutEnabled}\n
, 'isServiceReady:- ',${this.state.isServiceReady}\n
, 'isServiceEnabled:- ',${this.state.isServiceEnabled}\n
, '\n*****\n' );enableLogger && console.log( createStartsSeperatorTemplate('SHOULD_ENTER_TO_START_SERVICE_CONDITION?'), this.props.isAutoClockInOutEnabled === true && this.state.isServiceReady === true && this.state.isServiceEnabled === false, '\n*****\n' );
if ( this.props.isAutoClockInOutEnabled === true && this.state.isServiceReady === true && this.state.isServiceEnabled === false ) { enableLogger && console.log( createStartsSeperatorTemplate('START_SERVICE_NEED_PERMISSION, IS_GRANTED?'), this.state.isPermissionsGranted, '\n*****\n' ); // check permisssions to open the modal. !this.state.isPermissionsGranted && this.requestAlwaysLocationRef.current?.open(); }
enableLogger && console.log( createStartsSeperatorTemplate('SHOULD_ADD_GEOFENCES?'), 'this.props.workBranches length:- ',
${this.props.workBranches.length}\n
, 'this.state.isServiceEnabled:- ',${this.state.isServiceEnabled}\n
, 'full condition:- ', this.state.isServiceEnabled === true && this.props.workBranches.length > 0, '\n*****\n' );// listen to work branches and add them as geofences // to background location service. if ( this.state.isServiceEnabled && this.state.isServiceStarted && this.props.workBranches.length > 0 ) { this.addNewGeofences(this.props.workBranches); } }
// remove listeners when close the app. componentWillUnmount() { BackgroundGeolocation.removeAllListeners(); }
/**
Adds new geofences if not already added. */ addNewGeofences = async (allWorkBranches: TWorkBranch[]) => { try { const newGeofences: BGGeofence[] = [];
// get current added geofences. const curentGeofences: BGGeofence[] = await BackgroundGeolocation.getGeofences();
// transform work branches to geofences. allWorkBranches.forEach((wb) => { // constants, const wbIdentifier =
${wb.name}-${wb.id}
;// check if already exist in current geofences, if not exist, // add it. otherwise, do no thing. const foundIndx = curentGeofences.findIndex((cg) => cg.identifier === wbIdentifier); if (foundIndx === -1) newGeofences.push({ identifier:
${wb.name}-${wb.id}
, radius: wb.radius, latitude: parseFloat(wb.latitude), longitude: parseFloat(wb.longitude), notifyOnExit: true, notifyOnEntry: true, notifyOnDwell: false, extras: { name: wb.name }, }); });// add geofences to be monitered by the service. enableLogger && console.log( createStartsSeperatorTemplate('CURRENT_GEOFENCES_ADDED'), curentGeofences.map((c) =>
**${c.extras?.name}**
).toString(), '\n*****\n' );enableLogger && console.log( createStartsSeperatorTemplate('NEW_GEOFENCES_SHOULD_BE_ADDED'), newGeofences, '\n*****\n' );
// trying to add all geofences. newGeofences && newGeofences.length > 0 && (await BackgroundGeolocation.addGeofences(newGeofences)); } catch (error) { Alert.alert('', JSON.stringify(error)); console.log('error in adding geofences', error); } };
/**
${e.action}\n
, 'geofence id:- ',${e.identifier}\n
); // push event to sentry. const evtMsg =foreground event ${Platform.OS.toUpperCase()} ${e.identifier} - ${e.action}
; SentryHelper.pushEventAsMsg(evtMsg);// constants. const action: GeofenceAction = e.action as any; const locData: BGLocation = e.location;
// handle the geofence event. const r = await GeofencingHelper.handleGeofenceEvent( action, String(locData.coords.latitude), String(locData.coords.longitude), e.identifier ); SentryHelper.pushEventAsMsg(JSON.stringify(r)); };
/**
enableLogger && console.log(createStartsSeperatorTemplate('GEOFENCE_PERMISSION_GRANTED'));
// sart geofencing service, if it is not already enabled. if (this.state.isServiceEnabled === false) { const state = await GeofencingHelper.start(); if (state) { this.setState({ isServiceEnabled: state.enabled, isServiceStarted: true }); } else { Alert.alert('error i start geofencing service'); } }
// close the modal. this.requestAlwaysLocationRef.current?.close(); };
render() { return ( <RequestPermissionModal grantPermission={this.grantPermission} ref={this.requestAlwaysLocationRef} /> ); } }
// constants. const logLevel = DEV ? BackgroundGeolocation.LOG_LEVEL_VERBOSE : BackgroundGeolocation.LOG_LEVEL_VERBOSE; const stopTimeout = 5;
// connect to redux. const mapStateToProps = ({ employee }: RootState) => { // constants. const isAutoClockInOutEnabled = employee.profile.employee?.auto_mobile_clock_in_out || false; const workBranches = employee.profile.employee?.work_locations || []; const isFetchingEmployeeDataDone = employee.loading === false && employee.profile.employee?.work_locations != null;
return { isAutoClockInOutEnabled, workBranches, isFetchingEmployeeDataDone }; };
// export geofencing as default. const areEqualProps = (prevProps: GeofencingProps, nextProps: GeofencingProps) => { // re-render only if is auto clock status on/off changed. return prevProps.isAutoClockInOutEnabled === nextProps.isAutoClockInOutEnabled; }; const memiozedGeofencing = memo(Geofencing, areEqualProps); export default connect(mapStateToProps)(memiozedGeofencing);