react-native-background-geolocation
react-native-background-geolocation copied to clipboard
Realtime Database Firebase
I replaced sqlite with firebase, but it doesn't work with the app in the background
Your Environment
- Plugin version: 4.16.3
- Platform: Android
- OS version: 13
- Device manufacturer / model: Samsung A54
- React Native version (
react-native -v): 2.0.1 - Plugin config
import React from 'react';
import { Switch, Text, View, PermissionsAndroid, Platform } from 'react-native';
import { dbFirebase } from '../../services/firebaseConfig';
import { set, ref } from 'firebase/database';
import BackgroundGeolocation from "react-native-background-geolocation";
const HelloWorld = () => {
const [enabled, setEnabled] = React.useState(false);
const [location, setLocation] = React.useState('');
const sanitizeFirebaseKey = (key) => {
return key.replace(/[\.\#\$\[\]]/g, '_');
};
React.useEffect(() => {
const requestPermissions = async () => {
if (Platform.OS === 'android') {
try {
const granted = await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
PermissionsAndroid.PERMISSIONS.ACCESS_BACKGROUND_LOCATION,
]);
if (
granted[PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION] !== PermissionsAndroid.RESULTS.GRANTED ||
granted[PermissionsAndroid.PERMISSIONS.ACCESS_BACKGROUND_LOCATION] !== PermissionsAndroid.RESULTS.GRANTED
) {
console.error("Permissions not granted");
return;
}
} catch (err) {
console.warn(err);
}
}
};
requestPermissions();
BackgroundGeolocation.ready({
desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
distanceFilter: 5,
stopTimeout: 1,
debug: true,
logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
stopOnTerminate: false,
startOnBoot: true,
foregroundService: true,
notification: {
title: "Background tracking",
text: "Your location is being tracked",
},
}).then((state) => {
setEnabled(state.enabled);
console.log("- BackgroundGeolocation is configured and ready: ", state.enabled);
const onLocation = BackgroundGeolocation.onLocation(async (location) => {
console.log('[onLocation]', location);
setLocation(JSON.stringify(location, null, 2));
try {
const sanitizedTimestamp = sanitizeFirebaseKey(new Date(location.timestamp).toISOString());
const locationRef = ref(dbFirebase, `locations/${location.uuid}_${sanitizedTimestamp}`);
await set(locationRef, {
latitude: location.coords.latitude,
longitude: location.coords.longitude,
timestamp: location.timestamp
});
console.log("Location saved to Firebase");
} catch (error) {
console.error("Error saving location to Firebase: ", error);
}
});
const onMotionChange = BackgroundGeolocation.onMotionChange((event) => {
console.log('[onMotionChange]', event);
});
const onActivityChange = BackgroundGeolocation.onActivityChange((event) => {
console.log('[onActivityChange]', event);
});
const onProviderChange = BackgroundGeolocation.onProviderChange((event) => {
console.log('[onProviderChange]', event);
});
return () => {
onLocation.remove();
onMotionChange.remove();
onActivityChange.remove();
onProviderChange.remove();
};
}).catch(error => {
console.error("Error during BackgroundGeolocation ready: ", error);
});
}, []);
React.useEffect(() => {
if (enabled) {
BackgroundGeolocation.start().then(() => {
console.log("BackgroundGeolocation started");
}).catch(error => {
if (error.message === "Waiting for previous start action to complete") {
BackgroundGeolocation.stop().then(() => {
console.log("BackgroundGeolocation stopped, restarting...");
BackgroundGeolocation.start().then(() => {
console.log("BackgroundGeolocation restarted");
}).catch(error => {
console.error("Error restarting BackgroundGeolocation: ", error);
});
}).catch(stopError => {
console.error("Error stopping BackgroundGeolocation: ", stopError);
});
} else {
console.error("Error starting BackgroundGeolocation: ", error);
}
});
} else {
BackgroundGeolocation.stop().then(() => {
console.log("BackgroundGeolocation stopped");
}).catch(error => {
console.error("Error stopping BackgroundGeolocation: ", error);
});
setLocation('');
}
}, [enabled]);
return (
<View style={{ alignItems: 'center' }}>
<Text>Click to enable BackgroundGeolocation</Text>
<Switch value={enabled} onValueChange={setEnabled} />
<Text style={{ fontFamily: 'monospace', fontSize: 12 }}>{location}</Text>
</View>
);
};
export default HelloWorld;
Expected Behavior
My app has the business rule of seeing online service providers in real time on a map. I would like this data to be sent even with the app in the background, so that I don't have to keep the map screen open
Actual Behavior
Only saves when it is in the foreground
Steps to Reproduce
Context
My app has the business rule of seeing online service providers in real time on a map. I would like this data to be sent even with the app in the background, so that I don't have to keep the map screen open
Debug logs
Logs
Do you know you need to travel at least 200 meters before tracking engages? You need to go outside and move.
Yes, I walked 5000 meters and it didn't send data to Firebase
I’m not concerned about your Firebase. Does the plug-in make debug sound FX?
learn to fetch and analyze the plug-in logs. See wiki “Debugging”. Search api docs “emailLog”
Issued, is it not compatible with realtime firebase?
You’re responsible for your own JavaScript code implementing Firebase. That’s not the plug-ins responsibility.
im only concerned with “does the plugin track location and emit debug soundFX.
Please learn to syntax highlight codeblocks: https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
BackgroundGeolocation.ready({
// Geolocation Config
backgroundPermissionRationale: {
title: 'Permitir acesso à sua localização em background',
message:
'Para obter sua localização com precisão, por favor permita que o App obtenha sua localização o tempo todo.',
positiveAction: 'Configurar',
negativeAction: 'Cancelar',
},
locationAuthorizationAlert: {
titleWhenOff: 'Localização indisponível',
titleWhenNotEnabled: 'Localização em background indisponível',
instructions:
'Para obter sua localização com precisão, por favor permita que o App obtenha sua localização o tempo todo.',
settingsButton: 'Configurar',
cancelButton: 'Cancelar',
},
notification: {
title: 'Acompanhando sua localização',
text: 'Acompanhamos sua localização para enviar corridas próximas e monitorar a entrega.',
},
desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
distanceFilter: 10,
// Activity Recognition
stopTimeout: 5,
// Application config
debug: true, // <-- enable this hear sounds for background-geolocation life-cycle.
logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
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: 'https://shark-app-j3vbs.ondigitalocean.app/geolocationbackground',
batchSync: false, // <-- [Default: false] Set true to sync locations to server in a single HTTP request.
autoSync: true, // <-- [Default: true] Set true to sync each location to server as it arrives.
headers: { // <-- Optional HTTP headers
// "X-FOO": "bar"
"Authorization": `Bearer ${prestador.token}`
},
params: { // <-- Optional HTTP params
// "auth_token": "maybe_your_server_authenticates_via_token_YES?"
"prestador_id": prestador.id,
"nome": prestador.nome,
"genero": prestador.genero,
"foto_perfil": prestador.foto_perfil,
"prestadorsubcategoria": prestador.prestadorsubcategoria
}
}).then((state) => {
setEnabled(state.enabled)
console.log("- BackgroundGeolocation is configured and ready: ", state.enabled);
});
Do I need to do something special to send the parameters? It's only arriving with the screen on.
See api docs .emailLog. Learn to fetch and observe the plug-in logs.
and get rid of this: you do NOT need to do this.
if (error.message === "Waiting for previous start action to complete") {
BackgroundGeolocation.stop().then(() => {
console.log("BackgroundGeolocation stopped, restarting...");
BackgroundGeolocation.start().then(() => {
console.log("BackgroundGeolocation restarted");
}).catch(error => {
console.error("Error restarting BackgroundGeolocation: ", error);
});
}).catch(stopError => {
console.error("Error stopping BackgroundGeolocation: ", stopError);
});
} else {
console.error("Error starting BackgroundGeolocation: ", error);
}
import React, { useContext } from 'react';
import { Switch, Text, View, PermissionsAndroid } from 'react-native';
import BackgroundGeolocation from "react-native-background-geolocation";
import { AuthContext } from '../../contexts/AuthContext';
import api from '../../services/api';
const HelloWorld = () => {
const [enabled, setEnabled] = React.useState(false);
const [location, setLocation] = React.useState('');
const { prestador } = useContext(AuthContext);
React.useEffect(() => {
const requestLocationPermissions = async () => {
try {
const granted = await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION,
PermissionsAndroid.PERMISSIONS.ACCESS_BACKGROUND_LOCATION,
]);
if (
granted['android.permission.ACCESS_FINE_LOCATION'] === PermissionsAndroid.RESULTS.GRANTED &&
granted['android.permission.ACCESS_COARSE_LOCATION'] === PermissionsAndroid.RESULTS.GRANTED &&
granted['android.permission.ACCESS_BACKGROUND_LOCATION'] === PermissionsAndroid.RESULTS.GRANTED
) {
console.log('Você tem todas as permissões de localização');
} else {
console.log('Permissões de localização negadas');
}
} catch (err) {
console.warn(err);
}
};
requestLocationPermissions();
const onLocation = BackgroundGeolocation.onLocation(async (location) => {
console.log('[onLocation]', location);
setLocation(JSON.stringify(location, null, 2));
let dados = {
"prestador_id": prestador.id,
"nome": prestador.nome,
"genero": prestador.genero,
"foto_perfil": prestador.foto_perfil,
"prestadorsubcategoria": prestador.prestadorsubcategoria,
"location": {
"coords": {
"latitude": location.coords.latitude,
"longitude": location.coords.longitude,
}
}
};
try {
const response = await api.post('/geolocationbackground/', dados, {
headers: {
'Authorization': `Bearer ${prestador.token}`
}
});
console.log('Post successful: ', response.data);
} catch (error) {
console.error('Post failed: ', error);
}
});
const onMotionChange = BackgroundGeolocation.onMotionChange((event) => {
console.log('[onMotionChange]', event);
});
const onActivityChange = BackgroundGeolocation.onActivityChange((event) => {
console.log('[onActivityChange]', event);
});
const onProviderChange = BackgroundGeolocation.onProviderChange((event) => {
console.log('[onProviderChange]', event);
});
BackgroundGeolocation.ready({
backgroundPermissionRationale: {
title: 'Permitir acesso à sua localização em background',
message: 'Para obter sua localização com precisão, por favor permita que o App obtenha sua localização o tempo todo.',
positiveAction: 'Configurar',
negativeAction: 'Cancelar',
},
locationAuthorizationAlert: {
titleWhenOff: 'Localização indisponível',
titleWhenNotEnabled: 'Localização em background indisponível',
instructions: 'Para obter sua localização com precisão, por favor permita que o App obtenha sua localização o tempo todo.',
settingsButton: 'Configurar',
cancelButton: 'Cancelar',
},
notification: {
title: 'Acompanhando sua localização',
text: 'Acompanhamos sua localização para enviar corridas próximas e monitorar a entrega.',
},
desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
distanceFilter: 10,
stopTimeout: 5,
debug: true,
logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
stopOnTerminate: false,
startOnBoot: true,
url: 'https://shark-app-j3vbs.ondigitalocean.app/geolocationbackground',
batchSync: false,
autoSync: true,
headers: {
"Authorization": `Bearer ${prestador.token}`
},
params: {
"prestador_id": prestador.id,
"nome": prestador.nome,
"genero": prestador.genero,
"foto_perfil": prestador.foto_perfil,
"prestadorsubcategoria": prestador.prestadorsubcategoria
}
}).then((state) => {
setEnabled(state.enabled);
console.log("- BackgroundGeolocation is configured and ready: ", state.enabled);
let Logger = BackgroundGeolocation.logger;
Logger.emailLog('[email protected]')
.then(success => {
console.log(success, '[emailLog] success');
})
.catch(error => {
console.log('[emailLog] FAILURE: ', error);
});
});
return () => {
onLocation.remove();
onMotionChange.remove();
onActivityChange.remove();
onProviderChange.remove();
};
}, []);
React.useEffect(() => {
if (enabled) {
BackgroundGeolocation.start();
} else {
BackgroundGeolocation.stop();
setLocation('');
}
}, [enabled]);
return (
<View style={{ alignItems: 'center' }}>
<Text>Click to enable BackgroundGeolocation</Text>
<Switch value={enabled} onValueChange={setEnabled} />
<Text style={{ fontFamily: 'monospace', fontSize: 12 }}>{location}</Text>
</View>
);
};
export default HelloWorld;
If I give setEnabled true in the Android emulator, it saves a post record on my server, but using the debug apk, if I enable it, nothing happens, that's all that's needed for it to work.
Are you observing the plug-in logs in adb logcat?
see wiki “Debugging”.
You can’t develop with this plugin without observing the native device logs.
This issue is stale because it has been open for 30 days with no activity.
Even using BackgroundGeolocation.NOTIFICATION_PRIORITY_MIN it still emits sound, could the API not emit any sound at all?
notification: {
priority: BackgroundGeolocation.NOTIFICATION_PRIORITY_MIN,
title: 'Acompanhando sua localização',
text: 'Acompanhamos sua localização para enviar chamados de clientes próximos a você.',
},
See api docs Config.debug
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.