React Native Location Tracker - react-native

I'm implementing this code it is showing error like "undefined is not an object (evaluating 'navigator.geolocation.clearWatch')"
watchLocation = () => {
const { coordinate } = this.state;
this.watchID = navigator.geolocation.watchPosition(
position => {
const { latitude, longitude } = position.coords;
const newCoordinate = {
latitude,
longitude,
};
if (Platform.OS === 'android') {
if (this.marker) {
this.marker._component.animateMarkerToCoordinate(newCoordinate, 500); // 500 is the duration to animate the marker
}
} else {
coordinate.timing(newCoordinate).start();
}
this.setState({
latitude,
longitude,
});
},
error => console.log(error),
{
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 1000,
distanceFilter: 30,
}
);
};
Can anyone let me know how to solve this? Im referring this tutorial.
Link

First install :
npm i #react-native-community/geolocation
Then -
import Geolocation from '#react-native-community/geolocation';
watchLocation = () => {
const { coordinate } = this.state;
this.watchID = Geolocation.watchPosition(
//Your Code
);
}
For reference checkout - https://www.npmjs.com/package/#react-native-community/geolocation
I've gone through the blog which you are following so according to that you'll have to do a change likewise :
componentWillUnmount() {
Geolocation.clearWatch(this.watchID);
}

Related

useState is keep resetting- React Native

When I opened the app the first time and allow permission and switched to another screen the permission variable is still true and not resetting But when I closed the app and reopen the permission variable is first false and then became true.
` const DeviceLocation = (props) => {
const [hasPermission, setHasPermission] = useState(false);
const requestPermission = async () => {
const permissions =
Platform.OS === 'ios'
? PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
: PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION;
const isPermissionGranted = await checkPermission(permissions);
if (isPermissionGranted === 'granted') {
setHasPermission(true);
} else if (isPermissionGranted === 'denied') {
const result = await askPermission(permissions);
if (result === 'granted') {
setHasPermission(true);
}
} else if (isPermissionGranted === 'blocked') {
setPermisionBlocked(true);
setHasPermission(false);
} else {
setHasPermission(false);
setPositionLoading(false);
}
};
useEffect(() => {
{
isScreenFocused && requestPermission();
}
}, [isScreenFocused]);
const getPosition = useCallback(() => {
setPositionLoading(true);
if (hasPermission) {
Geolocation.getCurrentPosition(
(position) => {
setCurrentPosition({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
});
setPositionLoading(false);
},
(error) => {
console.log(error.code, error.message);
},
{
accuracy: {android: 'high', ios: 'bestForNavigation'},
distanceFilter: 1,
maximumAge: 10000,
},
);
} else {
setPositionLoading(false);
}
}, [setCurrentPosition, hasPermission]);your text
useEffect(() => {
getPosition();
}, [hasPermission]);`
close the app and reopen the app the permission variable should be true if the user already accepts the permission.
I have tried to set the hasPermission value into AsyncStorage but I still get hasPermission as false first time when the app reopens.

I want to get currentlocation of user , I am getting current location in android and ios but not on android tablet

I am getting correct latitude and longitude in android and ios and showing the marker but this doesn't happen on tablet. I am not getting marker in tablet android , I have enable showUserLocation={true} as well.
useEffect(() => {
const requestLocationPermission = async () => {
if (Platform.OS === 'ios') {
Geolocation.requestAuthorization('always').then((resp) => {
console.log("ios response ", resp)
Geolocation.getCurrentPosition(
(position) => {
console.log("position:::", position)
const { latitude, longitude } = position.coords;
setCurrentLatitude(latitude)
setCurrentLongitude(longitude)
},
(error) => {
// See error code charts below.
console.log(error.code, error.message);
},
{ enableHighAccuracy: true, timeout: 20000 }
);
}).catch((e) => console.log("ios error ::", e))
}
else {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Location Access Required',
message: 'This App needs to Access your location',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
Geolocation.getCurrentPosition(
(position) => {
// console.log("position:::", position)
const { latitude, longitude } = position.coords;
setCurrentLatitude(latitude)
setCurrentLongitude(longitude)
},
(error) => {
// See error code charts below.
console.log(error.code, error.message);
},
{ enableHighAccuracy: false, timeout: 20000 }
);
} else {
setLocationStatus('Permission Denied');
}
} catch (err) {
console.warn("Location error ::", err);
}
};
}
requestLocationPermission();
}, [])
This is what I have done

Why location permission pop up not showing in React Native?

I want to implement get current location in react native. I put permission to activate location if location is not activate in phone before calling geolocation API but pop up not showing and this PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,{ title: 'Location Access Required', message: 'This App needs to Access your location'},); always return "granted" when request permission using PermissionAndroid module.
this is my code
import { PermissionsAndroid } from 'react-native';
import Geolocation from '#react-native-community/geolocation';
...
componentDidMount(){
const requestLocationPermission = async () => {
let geoOptions = {
enableHighAccuracy: true,
timeout:20000,
maximumAge: 60*60*24
}
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Location Access Required',
message: 'This App needs to Access your location',
},
);
console.warn(granted);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
Geolocation.getCurrentPosition(this.geoLocationSuccess,this.geoLocationFailure,geoOptions);
}
} catch (err) {
console.warn(err);
}
};
requestLocationPermission();
}
is my implementation is wrong ? because i want to show pop up when location service is not enable to let user enable it
This may be of little help, first make sure no library location other than react-native-geolocation-service. then if there is no use react hook. you might try this method below.
hasLocationPermission = async () => {
const hasPermission = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
);
if (hasPermission === PermissionsAndroid.RESULTS.GRANTED) {
console.log('lagi req permission');
return true;
}
const status = await PermissionsAndroid.check(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
);
if (status) {
console.log('permission diberikan');
return true;
}
if (status === PermissionsAndroid.RESULTS.DENIED) {
ToastAndroid.show(
'Location permission denied by user.',
ToastAndroid.LONG,
);
} else if (status === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {
ToastAndroid.show(
'Location permission revoked by user.',
ToastAndroid.LONG,
);
}
return false;
};
async componentDidMount() {
if (await this.hasLocationPermission()) {
Geolocation.getCurrentPosition(
position => {
console.log('posisi ditemukan',position.coords.latitude, position.coords.longitude);
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
error: null,
});
this.goToRegion(position.coords.latitude, position.coords.longitude);
},
error => {
Alert.alert(
'Oopss!',
error.message,
[
{
text: 'OK',
onPress: () => console.log('Cancel Pressed'),
},
],
);
console.log(error.message);
this.setState({error: error.message});
},
{
accuracy: {
android: 'high',
ios: 'best',
},
enableHighAccuracy: true,
timeout: 15000,
maximumAge: 10000,
distanceFilter: 0,
forceRequestLocation: true,
forceLocationManager: false,
showLocationDialog: true,
},
);
}
}

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);
}

React-redux action is returning before async action is complete

I have a React Native app using redux and I'd like my action to set the GPS coordinates so I have them available in the store. You can see my console logs in the code, and 'action returning' is logged before 'has coordinates', which is the problem.
Component:
<TouchableOpacity style={{flex:1}} onPress={() => {
this.props.setLocation();
}}>
Action.js
export function setLocation(){
let coords = {
latitude:0,
longitude:0,
navigatorError:''
};
navigator.geolocation.getCurrentPosition(
(position) => {
console.log('has coordinates');
coords['latitude'] = position.coords.latitude
coords['longitude'] = position.coords.longitude
coords['navigatorError'] = null
},
(error) => coords['navigatorError'] = error.message,
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 },
);
console.log('action returning');
return {
type: 'set_location',
payload: coords
};
};
Reducer.js
export default (state = null, action) => {
switch(action.type){
case 'set_location':
return action.payload;
default:
return state;
}
}
Note: I'm not actually using redux-thunk in this project, I'm not sure if it's appropriate for what I need here.
You can use async and await to accomplish this. Basically, you need to await the coords to be returned from your asynchronous call.
Something like this:
export async function setLocation(){
let coords = {
latitude:0,
longitude:0,
navigatorError:''
};
await navigator.geolocation.getCurrentPosition(
(position) => {
console.log('has coordinates');
coords['latitude'] = position.coords.latitude
coords['longitude'] = position.coords.longitude
coords['navigatorError'] = null
},
(error) => coords['navigatorError'] = error.message,
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 },
);
console.log('action returning');
return {
type: 'set_location',
payload: coords
};
};
Documentation on async/await can be found here.