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.
Related
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);
}
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
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
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,
},
);
}
}
SDK Version: 38
Platforms(Android/iOS):
I am having difficulties getting this code to return a calendar ID, I’d appreciate help from anyone as there seems to be very little information about the new calendar API change.
async obtainCalendarPermission() {
let permission = await Permissions.getAsync(Permissions.CALENDAR)
if (permission.status !== 'granted') {
permission = await Permissions.askAsync(Permissions.CALENDAR)
return
}
if (permission.status !== 'granted') {
permission = await Permissions.askAsync(Permissions.REMINDERS)
return
if (permission.status !== 'granted') {
Alert.alert('Permission not granted to calendar')
}
}
return permission
}
async function getDefaultCalendarSource() {
const calendars = await Calendar.getCalendarsAsync()
const defaultCalendars = calendars.filter(
(each) => each.source.name === 'Default',
)
return defaultCalendars[0].source
}
async addReservationToCalendar(date){
await this.obtainCalendarPermission()
const permission = await Permissions.askAsync(Permissions.REMINDERS)
if (permission.status !== 'granted')
var calendars = Calendar.getCalendarsAsync().then(calendars => console.log(calendars))
const defaultCalendarSource = Platform.OS === 'ios' ? await getDefaultCalendarSource(): { isLocalAccount: true, name: 'Expo Calendar' };
console.log(defaultCalendarSource ,+'emeka')
let dateMs = Date.parse(date)
let startDate = new Date(dateMs)
let endDate = new Date(dateMs + 2 * 60 * 60 * 1000)
const calendarId = await Calendar.createEventAsync(
defaultCalendarSource.id,
{
title: 'Con Fusion Table Reservation',
startDate: startDate,
endDate: endDate,
timeZone: 'Asia/Hong_Kong',
location:
'121, Clear Water Bay Road, Clear Water Bay, Kowloon, Hong Kong',
},
)}
In my case I decided to implement EVENTS for android and REMINDERS for iOS. I show you my solution, but it's a bit different. It works perfectly on both platforms.
I'm using:
"expo": "46.0.13"
"expo-calendar": "10.3.0"
"react-native": "0.69.6"
useEffect(() => {
(async () => {
if (Platform.OS === 'ios') {
await requestTrackingPermissionsAsync();
const remindersPermissions = await Calendar.requestRemindersPermissionsAsync();
if(remindersPermissions.status !== 'granted')
Alert.alert('Reminders access required', 'You must accept access to reminders in order to create reminders.',
[
{ text: "Cancel", style: "cancel" },
{ text: "OK", onPress: async () => await Calendar.requestRemindersPermissionsAsync() }
])
}
const calendarPermissions = await Calendar.requestCalendarPermissionsAsync();
if(calendarPermissions.status === 'granted') {
createCalendar()
} else {
Alert.alert('Access to calendars required', 'You must allow access to the calendar if you want to create reminders.',
[
{ text: "Cancel", style: "cancel" },
{ text: "OK", onPress: async () => await Calendar.requestCalendarPermissionsAsync() }
])
}
})();
}, [])
const getDefaultCalendarSource = async() => {
const defaultCalendar = await Calendar.getDefaultCalendarAsync();
return defaultCalendar.source;
}
const createCalendar = async () => {
const calendarEntityType = Platform.OS === 'android' ? Calendar.EntityTypes.EVENT : Calendar.EntityTypes.REMINDER;
const calendars = Platform.OS === 'android' ? await Calendar.getCalendarsAsync() : await Calendar.getCalendarsAsync(calendarEntityType);
const existCalendar = calendars.find(calendar => calendar.title === DEFAULT_CALENDAR_NAME);
if (!existCalendar) {
const defaultCalendarSource = Platform.OS === 'ios' ? await getDefaultCalendarSource() : { isLocalAccount: true, name: DEFAULT_CALENDAR_NAME };
const newCalendarId = await Calendar.createCalendarAsync({
title: DEFAULT_CALENDAR_NAME,
name: DEFAULT_CALENDAR_NAME,
color: primerColor,
entityType: calendarEntityType,
accessLevel: Calendar.CalendarAccessLevel.OWNER,
sourceId: defaultCalendarSource.id,
source: defaultCalendarSource,
ownerAccount: DEFAULT_CALENDAR_NAME,
});
globalContext.setCalendarId(newCalendarId)
} else {
const calendarIndex = calendars.findIndex(calendar => calendar.title === DEFAULT_CALENDAR_NAME);
globalContext.setCalendarId(calendars[calendarIndex].id);
}
}
And to create Events/Reminders I have this function:
const onSetReminder = async (reminderDate) => {
let reminderId;
let eventId;
Platform.OS === 'ios' && (async() => {
reminderId = await Calendar.createReminderAsync(globalContext.calendarId, {
title: `Reminder Title`,
calendarId: globalContext.calendarId,
startDate: reminderDate,
dueDate: reminderDate,
alarms: [{
relativeOffset: -60,
method: Calendar.AlarmMethod.ALERT
}],
});
})();
Platform.OS === 'android' && (async() => {
eventId = await Calendar.createEventAsync(globalContext.calendarId, {
title: `Event Title`,
accessLevel: Calendar.EventAccessLevel.OWNER,
calendarId: globalContext.calendarId,
startDate: reminderDate,
endDate: reminderDate,
alarms: [{
method: Calendar.AlarmMethod.ALERT,
relativeOffset: -60,
}],
});
})();
};
I have solved it. I was having a hard time getting the calendar ID as it is a requirement for the new createEventAsync() API. this is the complete code that solved the problem for me, I am pasting it here so that someone can use or improve on it.
It generates a unique calendar ID and saves reservations to the calendar on IOS, I did not test it on android.
async function getDefaultCalendarSource() {
await Calendar.getCalendarsAsync().then((id) => console.log(id))
}
async obtainCalendarPermission() {
let permission = await Permissions.getAsync(Permissions.CALENDAR)
if (permission.status !== 'granted') {
permission = await Permissions.askAsync(Permissions.CALENDAR)
return
}
if (permission.status !== 'granted') {
permission = await Permissions.askAsync(Permissions.REMINDERS)
return
if (permission.status !== 'granted') {
Alert.alert('Permission not granted to calendar')
}
}
return permission
}
async addReservationToCalendar(date) {
await this.obtainCalendarPermission()
var dateMs = Date.parse(date)
var startDate = new Date(dateMs)
var endDate = new Date(dateMs + 2 * 60 * 60 * 1000)
getDefaultCalendarSource()
const newCalendar = await Calendar.createCalendarAsync({
title: 'Test Reservation',
color: '#512DA8',
entityType: Calendar.EntityTypes.EVENT,
sourceId: getDefaultCalendarSource.id,
source: getDefaultCalendarSource,
name: 'Restauran Reservation',
ownerAccount: 'personal',
accessLevel: Calendar.CalendarAccessLevel.OWNER,
})
.then((id) => {
Calendar.createEventAsync(id, {
title: 'Table Reservation',
startDate: startDate,
endDate: endDate,
timeZone: 'Asia/Hong_Kong',
location:
'121, Clear Water Bay Road, Clear Water Bay, Kowloon, Hong Kong',
}).catch((err) => console.log(err))
// console.log(`calendar ID is: ${id}`)
})
.catch((err) => console.log(err))
}