How to keep React Native app running in background? - react-native

I want to keep track of the location of user using watchposition in react native and send that location to server is it possible?

I would recommend you to use this https://github.com/mauron85/react-native-background-geolocation its pretty simple to use.

I have used this plugin react-native-background-timer to enable my app to run in background as well and get device location here is the sample code
BackgroundTimer.setInterval(() => {
navigator.geolocation.getCurrentPosition((position) => {
this.setState({
startDrive: true,
latitude: position.coords.latitude,
longitude: position.coords.longitude
});
this.offlineHistoryManager(position.coords.latitude, position.coords.longitude);
}, (error) => {
LocationSwitch.enableLocationService(1000, true, () => { //
}, () => { //
},);
}, {enableHighAccuracy: false, timeout: 20000});
}, 30000);

Related

How to write a JEST test for a useEffect with timers?

I am using #react-native-community/netinfo to detect the app connectivity state and showing a message when connection is lost. How do I write a test for the following code that's in a useEffect to make sure that the message is showing/hiding and the cleanup works?
const { isConnected } = useContext(ConnectionContext);
...
useEffect(() => {
const snack = setTimeout(() => {
if (!isConnected) {
showMessage({
autoHide: false,
message: 'Please try again later',
});
}
}, 10000);
const hideSnack = setTimeout(() => {
if (isConnected) hideMessage();
}, 5000);
return () => {
clearTimeout(snack);
clearTimeout(hideSnack);
};
}, [isConnected]);
I have tried something like this to check if the app is connected
jest.mock('#react-native-community/netinfo', () => ({
...jest.requireActual('#react-native-community/netinfo'),
useNetInfo: () => ({
isConnected: true,
})
}));
You can use jest fake timers to control the time:
at the top use
jest.useFakeTimers();
then when you need to advance time by certain amount use :
jest.advanceTimersByTime(100);

React Native library to track user location

Which library will be most suitable for Android and iOS to be able to track user location continuously even if the app is running in background.
I need to track user's location to send notification that the user has entered a specific location and upon exiting the user has left the location.
You can use geolocation like this way:
getUserCurrentLocation = async () => {
return new Promise((resolve, reject) => {
try {
navigator.geolocation.getCurrentPosition(position => {
const { latitude, longitude } = position.coords;
resolve({ lat: latitude, lng: longitude })
}, error => {
console.log(`ERROR(${error.code}): ${error.message}`);
resolve({ error })
} // , { enableHighAccuracy: true, timeout: 10000, maximumAge: 1000 }
);
setTimeout(() => { resolve({ error: { code: 3 } }) }, 5000);
} catch (e) {
resolve({ error: { code: 3 } })
}
})
};

navigator.geolocation:: Location request timed out issue React Native

I am building a React Native app and trying to get my current geocodes using navigator.geolocation It shows me an error of Location request Time out. Basically I am building a tracking app and I need to configure the exact location latitude longitude. To start tracking there is one button and click of this tracking would be start and it should be the initial point for tracking. I am using default react native geolocation API, Link https://facebook.github.io/react-native/docs/geolocation
Function to get my current location::
getLocation() {
navigator.geolocation.getCurrentPosition(response => {
console.log(response);
if (response && response.coords) {
this.saveLogs(response.coords);
}
},
(error) => {
this.onGeolocationErrorOccurCallback(error);
},
GeolocationOptions
)
}
It shows me an Error::
{"TIMEOUT":3,"POSITION_UNAVAILABLE":2,"PERMISSION_DENIED":1,"message":"Location
request timed out", "code":3}
I have added permission for Android device, and also checking by set enableHighAccuracy value to false. But it's not working for me. And I need to set enableHighAccuracy to true because I want exact geocodes to track someone. Please suggest why Location request timed out is occurring here??
UPDATE: 2021 June 12,
This approach works for me in Android Emulator. "react-native": "0.64.1" and Android API 30
import Geolocation from "#react-native-community/geolocation";
const getGeoLocaation = () => {
const config = {
enableHighAccuracy: true,
timeout: 2000,
maximumAge: 3600000,
};
Geolocation.getCurrentPosition(
info => console.log("INFO", info),
error => console.log("ERROR", error),
config,
);
};
The code below worked for me:
componentDidMount(){
if(Platform.OS === 'android'){
this.requestLocationPermission()
}else{
this._getCurrentLocation()
}
}
async requestLocationPermission() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
'title': 'Location Permission',
'message': 'MyMapApp needs access to your location'
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
this._getCurrentLocation()
console.log("Location permission granted")
} else {
console.log("Location permission denied")
}
} catch (err) {
console.warn(err)
}
}
_getCurrentLocation = () =>{
navigator.geolocation.getCurrentPosition(
(position) => {
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
})
},
(error) => {
this.setState({ error: error.message })},
{ enableHighAccuracy: true, timeout: 200000, maximumAge: 1000 },
);
}
Permission in Manifest file:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Just make sure your location is enabled.
Try to use:
enableHighAccuracy: false
Worked for me!
const getUserCurrentLocation = () => {
let latitude, longitude
Geolocation.getCurrentPosition(
info => {
const { coords } = info
latitude = coords.latitude
longitude = coords.longitude
setLat(latitude)
setLng(longitude)
getUserCurrentAddress(latitude, longitude)
},
error => console.log(error),
{
enableHighAccuracy: false,
timeout: 2000,
maximumAge: 3600000
}
)
}
I add the same issue ({"TIMEOUT":3,"POSITION_UNAVAILABLE":2,"PERMISSION_DENIED":1,"message":"Location request timed out", "code":3})
After reading the following documents,
https://developer.android.com/training/location/permissions#java
https://github.com/react-native-geolocation/react-native-geolocation/blob/master/example/GeolocationExample.js'
I understood that, I need to add:
in the manifest AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
And increment the timeout as follow
{
enableHighAccuracy: false,
timeout: 2000,
maximumAge: 3600000
}
-- code snipet
Geolocation.getCurrentPosition(
position => {
const initialPosition = JSON.stringify(position);
console.log(initialPosition)
// this.setState({initialPosition});
},
error => console.log('Error', JSON.stringify(error)),
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000},
);

How to keep running app even app is close in react-native

I want my app run even app close. or just run when location coordinates changed.
I used appState but it doesnt help me because it works just when appState change.
also I used react-native-background-task but it runs every 7m30s
I use this now but it doesnt help me too. what should I do ?
location(){
this.watchId = navigator.geolocation.watchPosition(
(position) => {
console.log(position.coords.latitude);
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
this.setState({latitude: latitude, longitude: longitude});
},
(error) => this.setState({ error: error.message }),
{ enableHighAccuracy: true, timeout: 200000, maximumAge: 1000},
);
}
componentDidMount() {
this.location()
}
componentWillUnmount() {
navigator.geolocation.clearWatch(this.watchId);
}

Extract formatted_address from JSON return from Google Maps API

I'm using the google maps API to do the reverse geocoding but I'm not able to extract the formatted_address
componentWillMount() {
navigator.geolocation.getCurrentPosition(
(position) => {
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
error: null,
});
},
(error) => this.setState({ error: error.message }),
{ enableHighAccuracy: true, timeout: 20000 },
);
axios.get('https://maps.googleapis.com/maps/api/geocode/json?address='+ this.state.latitude +','+ this.state.longitude +'&key=__API_KEY__')
.then(results => {
this.setState({
place: results[0].formated_address
})
.catch((error) => {
this.setState({ error: error.message })
});
});
}
How do I do that?
first you need to call the api after getCurrentPosition is finished
be sure your api key is correct and has access to the geocode api
access the first place address from response.data.results[0].formatted_address note that i changed results to response since it is more descriptive name also note that formatted_address with double t
finally catch is called after then not after setState
full working example
componentWillMount() {
navigator.geolocation.getCurrentPosition(
(position) => {
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
error: null,
}, () => this.getGeocode()); // call the api after getCurrentPosition is finished
},
(error) => this.setState({ error: error.message }),
{ enableHighAccuracy: true, timeout: 20000 },
);
}
getGeocode() {
axios.get('https://maps.googleapis.com/maps/api/geocode/json?address='+ this.state.latitude +','+ this.state.longitude +'&key=__API_KEY__') // be sure your api key is correct and has access to the geocode api
.then(response => {
console.log(response);
this.setState({
place: response.data.results[0].formatted_address // access from response.data.results[0].formatted_address
})
}).catch((error) => { // catch is called after then
this.setState({ error: error.message })
});
}