app crash when using Geolocation in React-Native - react-native

I am using react-native-geolocation-service, I have such function to get coords. And then by Geocoder api get the city by coords. I check the permission status by react-native-permissions:
export const getCity = async (dispatch: Dispatch<any>) => {
const granted = await check(PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION);
if (granted === RESULTS.DENIED) {
await PermissionsAndroid.request(PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION, {
buttonNegative: undefined,
buttonNeutral: undefined,
buttonPositive: '',
title: 'Access',
message: 'give access',
});
}
if (granted === RESULTS.GRANTED || granted === RESULTS.LIMITED) {
Geolocation.getCurrentPosition(
position => {
const coords: Coords = {
Longitude: position.coords.longitude,
Latitude: position.coords.latitude,
};
dispatch(thunks.geocoder.getGeocoderInfo(coords));
Alert.alert('coords', `${coords.Latitude}, ${coords.Longitude}`);
},
error => Alert.alert('Error', `Error ${error.message}`),
{
enableHighAccuracy: false,
timeout: 20000,
maximumAge: 3600000,
},
);
}
};
So, when my applications starts, I grant the permission to it, and then it just closes. Also I added access into AndroidManifest.xml: <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>. And then I call this function inside my component using UseEffect()

I solved my problem. I rewrite my code form question as follows:
type Coords = {
coords: {
accuracy?: number | null;
altitude?: number | null;
altitudeAccuracy?: number | null;
heading?: number | null;
latitude?: number | null;
longitude?: number | null;
speed?: number | null;
};
mocked?: boolean;
provider?: string;
timestamp?: number | null;
};
export const getCity = async (dispatch: Dispatch<any>) => {
const granted = await check(PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION);
let geoOptions = {
enableHighAccuracy: true,
timeOut: 20000,
maximumAge: 60 * 60 * 24,
};
const geoSuccess = (position: Coords) => {
const coords = {
Latitude: position.coords.latitude,
Longitude: position.coords.longitude,
};
dispatch(thunks.geocoder.getGeocoderInfo(coords));
};
const geoFailure = (err: any) => {
console.log({error: err.message});
};
if (granted === RESULTS.DENIED) {
const data = await PermissionsAndroid.request(
PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
{
buttonNegative: undefined,
buttonNeutral: undefined,
buttonPositive: '',
title: 'Access',
message: 'give access',
},
);
}
if (granted === RESULTS.GRANTED || granted === RESULTS.LIMITED) {
Geolocation.getCurrentPosition(geoSuccess, geoFailure, geoOptions);
}
};
So it solved my problem. App now doesn't crush.

This issue can be solved by upgrading your react native to 0.70.1, i just solved that problem and now the gelocaiton service is working fine in both debug and release apk.
and dont forget to add use permission in androidmanifest.xml

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.

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

React native geolocation service not working for iOS

I am trying to get device current position in react native. I am using below library for get the location:
react-native-geolocation-service
My code:
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Device current location permission',
message:
'Allow app to get your current location',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
this.getCurrentLocation();
} else {
console.log('Location permission denied');
}
} catch (err) {
console.warn(err);
}
}
getCurrentLocation(){
Geolocation.requestAuthorization();
Geolocation.getCurrentPosition(
(position) => {
alert(position.coords.latitude);
this.socket.emit('position', {
data: position,
id: this.id,
});
},
(error) => {
alert("map error: "+error.message);
console.log(error.code, error.message);
},
{ enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 }
);
}
Android is working fine and getting the correct location but for IOS it's not working Also, it's not asking for allow location persmission. I am getting below error:
PERMISSION_DENIED: 1
POSITION_UNAVAILABLE: 2
TIMEOUT: 3
code: 3
message: "Unable to fetch location within 15.0s."
This is my info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>$(PRODUCT_NAME) would like to access your location.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>$(PRODUCT_NAME) would like to access your location.</string>
This is background modes from xcode
I have used the react-native-geolocation-service for getting user current location here is my code
App.js:
import Geolocation from 'react-native-geolocation-service';
async componentDidMount() {
if(Platform.OS === 'ios'){
this.getCurrentLocation();
}else{
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Device current location permission',
message:
'Allow app to get your current location',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
this.getCurrentLocation();
} else {
console.log('Location permission denied');
}
} catch (err) {
console.warn(err);
}
}
}
getCurrentLocation(){
Geolocation.requestAuthorization();
Geolocation.getCurrentPosition(
(position) => {
console.log(position);
},
(error) => {
console.log("map error: ",error);
console.log(error.code, error.message);
},
{ enableHighAccuracy: false, timeout: 15000, maximumAge: 10000 }
);
}
MapScreen.js
import Geolocation from 'react-native-geolocation-service';
componentDidMount() {
this.updateCurrentPosiiton();
}
updateCurrentPosiiton () {
Geolocation.getCurrentPosition(
(position) => {
let d_lat = position.coords.latitude;
let d_lng = position.coords.longitude;
this.setState({
current_lat: position.coords.latitude,
current_lng: position.coords.longitude
})
// console.log('aayaaa');
this.props.updateGps(d_lat,d_lng);
this.getTrackData(d_lat,d_lng);
},
(error) => {
console.log("map error: ",error);
console.log(error.code, error.message);
},
{ enableHighAccuracy: false, timeout: 15000, maximumAge: 10000 }
);
}
Please let me know if any issue.
I have solved this issue by this
async requestPermission() {
try {
const granted = await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION,
]).then((result) => {
console.log(result);
if (
result['android.permission.ACCESS_COARSE_LOCATION'] &&
result['android.permission.ACCESS_FINE_LOCATION'] === 'granted'
) {
this.getLocation();
this.setState({
permissionsGranted: true,
});
}
});
} catch (err) {
console.warn(err);
}
}
getLocation() {
Geolocation.getCurrentPosition(
(position) => {
console.log(position);
},
(error) => {
// See error code charts below.
console.log(error.code, error.message);
},
{enableHighAccuracy: true, timeout: 15000, maximumAge: 10000},
);
}
componentDidMount() {
if (Platform.OS === 'ios') {
Geolocation.requestAuthorization('always').then((res) => {
console.log(res);
});
}
if (Platform.OS === 'android') {
this.requestPermission();
} else {
this.getLocation();
}
}
make sure you called this function with parameter Geolocation.requestAuthorization('always') or Geolocation.requestAuthorization('whenInUse')

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

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.