Reputation: 846
The map component of my app does not need to constantly track the user's location. Adding
navigator.geolocation.clearWatch(this.watchId);
and
navigator.geolocation.stopObserving();
to componentWillUnmount
and to an AppState
listener does not shut off the GPS when it's not needed. How can I make this work? Thanks.
A little more info: I can tell the GPS location service is still running (in the android version of this app) because the location icon remains in the statusbar after the app has been backgrounded.
export class MapOfHalifax extends React.Component {
constructor(args) {
super(args);
this.state = {
markers: this.props.markers,
latitude: null,
longitude: null,
error: null,
}
}
componentDidMount() {
this.watchId = navigator.geolocation.watchPosition(
(position) => {
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
error: null,
});
this.checkDistanceFromSignificantLocation(position)
},
(error) => this.setState({ error: error.message }),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000, distanceFilter: 10 },
);
AppState.addEventListener('change', (state) => {
if (state === 'active') {
console.log('state active');
}
if(state === 'background'){
navigator.geolocation.clearWatch(this.watchId);
navigator.geolocation.stopObserving();
console.log('background');
}
});
}
componentWillUnmount() {
navigator.geolocation.clearWatch(this.watchId);
navigator.geolocation.stopObserving();
}
toggleSelect(id) {
// this.state.selected.indexOf(id) > -1
// ? this.setState({ selected: this.state.selected.filter(x => x !== id) })
// : this.setState({ selected: this.state.selected.concat(id) }),
this.props.toggleMarkerState(id)
}
checkDistanceFromSignificantLocation(currentPosition) {
this.state.markers.map((marker, index) => {
const START = {
latitude: currentPosition.coords.latitude,
longitude: currentPosition.coords.longitude
}
const END = {
latitude: marker.latitude,
longitude: marker.longitude
}
if (haversine(START, END, { threshold: MAX_DISTANCE_FROM_LOCATION, unit: PREFERED_DISTANCE_UNIT })
&& (!this.props.markers[index].locationPassedBy)){
this.props.updatePassedByTime(index, moment.utc())
NotificationsAndroid.localNotification({
title: "Approaching:",
body: marker.name + "!"
});
} else if (haversine(START, END, { threshold: MAX_DISTANCE_FROM_LOCATION, unit: PREFERED_DISTANCE_UNIT })
&& (moment().diff(this.props.markers[index].locationPassedBy,'minutes') > 60)){
NotificationsAndroid.localNotification({
title: "Approaching:",
body: marker.name + "!"
});
}
});
}
render() {
return (
<View style={styles.container}>
<MapView
ref={ref => { this.map = ref; }}
showsUserLocation={true}
showsMyLocationButton={true}
style={styles.map}
initialRegion={{
latitude: LATITUDE,
longitude: LONGITUDE,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
}}>
{this.state.markers.map((marker, index) => {
return (<MapView.Marker
coordinate={{
latitude: parseFloat(marker.latitude),
longitude: parseFloat(marker.longitude)
}}
title={marker.name}
key={marker.id}
onPress={() => {
const marker = this.state.markers[index]
marker.mapMarkerIsSelected = !marker.mapMarkerIsSelected
this.setState({
markers: [
...this.state.markers.slice(0, index),
marker,
...this.state.markers.slice(index + 1)
]
})
this.props.toggleMarkerState(marker.id)
}}
pinColor={
marker.mapMarkerIsSelected ? '#3590ea' : '#f06f77'
}>
</MapView.Marker>)
})}
</MapView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
justifyContent: 'flex-end',
alignItems: 'center',
},
map: {
...StyleSheet.absoluteFillObject,
},
bubble: {
backgroundColor: 'rgba(255,255,255,0.7)',
paddingHorizontal: 18,
paddingVertical: 12,
borderRadius: 20,
},
button: {
marginTop: 12,
paddingHorizontal: 12,
alignItems: 'center',
marginHorizontal: 10,
},
buttonContainer: {
flexDirection: 'column',
marginVertical: 20,
backgroundColor: 'transparent',
},
customCallout: {
backgroundColor: 'white',
padding: 5
},
callout: {
width: 140,
},
});
const mapStateToProps = state => {
return {
markers: state.PeopleReducer
};
}
const actions = { updatePassedByTime, toggleMarkerState };
export default connect(mapStateToProps, actions)(MapOfHalifax);
Upvotes: 3
Views: 1684
Reputation: 846
When I made this post, I was running the above code on google's android emulator. After posting, it became apparent that my code was working like it should on the emulator but, with a delay. So, I ran the code on a physical device and found that the geolocation icon disappeared instantaneously. It was sufficient to leave the clearWatch()
and possibly the stopObserving()
functions in componentWillUnmount()
. The AppState listener
was not needed.
Upvotes: 2