I want to get current location when the user has the "get current location" checkbox checked.
I have a form for user inputs and one of them is a checkbox that gets the users current location when the checkbox is checked and the form is submitted.
My Code:
const getLocation = () => {
console.log("Testing getLocation");
(async () => {
console.log("Ask Location Permission");
let { status } = await Location.requestForegroundPermissionsAsync();
console.log("Permission Asked");
if (status !== "granted") {
setErrorMsg("Location access denied!");
console.log(errorMsg);
return;
}
let currentLocation = await Location.getCurrentPositionAsync({});
setLatitude(currentLocation.coords.latitude);
setLongitude(currentLocation.coords.longitude);
console.log("Start of Print Coords");
console.log(currentLatitude);
console.log(currentLongitude);
console.log("End of Print Coords");
})();
};
const onSubmit = (data: { distance: number; coordinates: string }) => {
if (checkbox) {
console.log("Checkbox Selected");
getLocation();
console.log("getLocation Tested");
coords.push(currentLatitude);
coords.push(currentLongitude);
console.log(coords);
}
When i submit the form, I have multiple console logs to check where my issue is as it never asks to get location permissions. In the getLocation, it exits after printing "Ask Location Permission" and somehow comes back to print "Permission Asked" when the app does not ask for permission for location.console logs
I am using expo location to get current location and i dont use useEffect as i only need the current coordinates once and it does not need to be updated. https://docs.expo.dev/versions/latest/sdk/location/
In your case, async funcation is merely declared in getLocation(). You need to call that function like below.
const getLocation = () => {
console.log("Testing getLocation");
async () => {
console.log("Ask Location Permission");
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") {
setErrorMsg("Location access denied!");
console.log(errorMsg);
return;
}
let currentLocation = await Location.getCurrentPositionAsync({});
setLatitude(currentLocation.coords.latitude);
setLongitude(currentLocation.coords.longitude);
console.log(currentLatitude);
console.log(currentLongitude);
}(); // here you need to call it using parenthesis
};
There's a situation when previously the user choose not this app ask permission anymore. Next time the app asks this permission, silently device return status: "denied" without permission popup modal.
Always check whether the app eligible to ask that permission again.
let { status,canAskAgain } = await Location.requestForegroundPermissionsAsync();
console.log("Permission Asked");
if(canAskAgain === false){
// User has previously blocked app to ask this permission
// Force user to grant permission manually
await Linking.openSettings();
}
if (status !== "granted") {
setErrorMsg("Location access denied!");
console.log(errorMsg);
return;
}
Related
What im trying to do is to ask the user for location permission, and if the user doesn't allow the permission, cannot navigate to other screens.
I have used expo-location for this, and when I test the app locally, it asks me to allow or not allow the permission for the location, but when I generate an APK, to test it on android, it shows me the alert that I dont have the location permission, and when I go to the app setting to allow it manually, it says No permission requested
function requestLocationPermission() {
return Location.requestForegroundPermissionsAsync().then((handleResponse) => {
if (handleResponse.status === 'granted') {
setLocationPermission(handleResponse.status);
} else if (handleResponse.status !== 'granted') {
alert('Map/Gps needs the appropriate permissions.');
return Location.requestForegroundPermissionsAsync();
}
});
}
useEffect(() => {
requestLocationPermission();
buttonText();
}, [locationPermission]);
const confirm = () => {
if (locationPermission === "granted") {
navigation.navigate('CreateProfile',
} else {
requestLocationPermission();
}
};
So, in the APK it returns me: alert('Map/Gps needs the appropriate permissions.');
How can I fix this?
I am struggling a little with getting in app purchases working due to lack of examples that show how all the functionality links together
In my app, I have one in app purchase which basically allows the user to unlock some restricted functionality for life.
So at the start I want to check if the user have purchased the item before. (via get history)
If they have I unlock the functionality.
On my signed APK file (android) made in android studio, I have the following issues:
-the purchase never acknowledges (although it does when run via react-native run-android)
-if you press the purchase button twice the error "already connected to app store appears"
-I don't think its getting the purchase history when running from the signed file (although I can print out the result in the console in debug mode)
I am not entirely sure when to call await InAppPurchases.connectAsync(); so this could be one potential source of issues
So this is my code in my "Inner App" . My App component is just the InnerApp wrapped in the provider component from redux. The inner app contains all the navigation stacks so the purchase listener should be global.
e.g.
export default function App (){
...more code
return(
< Provider store={store} >
< InnerApp />
</ Provider >
}
Inner app code
import * as InAppPurchases from 'expo-in-app-purchases';
export default function InnerApp (){
.....some more code
//gets purchase history
const getHistory = async ()=>{
await InAppPurchases.connectAsync();
let found=false
const { responseCode, results } = await InAppPurchases.getPurchaseHistoryAsync();
if (responseCode === InAppPurchases.IAPResponseCode.OK) {
results.forEach(result => {
if (result.acknowledged) {
found =true
// this is just saving to local storage (in case they are using the app offline)
savePurchaseHistory(true)
}else{
savePurchaseHistory(false)
}
});
}
if( found){
//updates a state in the redux store
dispatch(purchaseIAP() )
}else if(responseCode === IAPResponseCode.USER_CANCELED ){
dispatch(removeIAP() )
savePurchaseHistory(false)
}
await InAppPurchases.disconnectAsync();
}
//listens for purchases
const setUpIAP = async() => {
// Set purchase listener
await InAppPurchases.connectAsync();
await InAppPurchases.setPurchaseListener(({ responseCode, results, errorCode }) => {
// Purchase was successful
if (responseCode === InAppPurchases.IAPResponseCode.OK) {
results.forEach(purchase => {
if (!purchase.acknowledged) {
// Process transaction here and unlock content...
dispatch(purchaseIAP() )
// Then when you're done
InAppPurchases.finishTransactionAsync(purchase, false);
}
});
}
// Else find out what went wrong
if (responseCode === InAppPurchases.IAPResponseCode.USER_CANCELED) {
} else if (responseCode === InAppPurchases.IAPResponseCode.DEFERRED) {
console.log('User does not have permissions to buy but requested parental approval (iOS only)');
} else {
console.warn(`Something went wrong with the purchase. Received errorCode ${errorCode}`);
}
});
}
//The in app stuff is called when the component is mounted
useEffect(() => {
setUpIAP()
getHistory()
}, [ ] })
Further in my app I have a button that calls the following function when pressed
const unlockModes = async () => {
try {
const items = Platform.select({
ios: [
'dev.products.all_modes'
],
android: ['all_modes'],
});
await connectAsync();
const products = await InAppPurchases.getProductsAsync(items);
if (products.results.length > 0) {
await InAppPurchases.purchaseItemAsync("all_modes");
}
} catch (err) {
alert("error occured while trying to purchase: " + err);
}
};
In the end I used the React Native IAP library and I couldn't get the expo one to work.
I think the Expo Version currently might just be bust.
Setting useGooglePlayCache will resolve your problem
im building a music player and I need to acces to the music files, so the first thing is ask for permissions to acces to the files:
componentDidMount() {
this.requestPermission();
}
requestPermission = async () => {
try {
const userResponse = await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
]);
if (userResponse === PermissionsAndroid.RESULTS.GRANTED) {
alert("nice");
}else {
alert("no nice");
}
}catch (error) {
alert(error)
}
};
even when I already clicked in allow, and reload the project it wil say no nice, i open the config of the app and the permission to storage is fine, so dont why is this happening
According to documentation requestMultiple will return an object with the permissions as keys and strings as values (see result strings above) indicating whether the user allowed or denied the request or does not want to be asked again.
try this
if (userResponse[PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE] === PermissionsAndroid.RESULTS.GRANTED && userResponse[PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE] ===
PermissionsAndroid.RESULTS.GRANTED
) {
alert('nice');
} else {
alert('no nice');
}
After allowing permission to access GPS in react native App. If the user rejected to turn on the gps. It will show errors like
Unhandled promise rejection: Error: Location request failed due to unsatisfied device settings."
I want to avoid if the user rejects the Gps turn on option It will return something. so I need If condition for the location whether it is On or Off. (I'm using expo-location)
You're seeing this error because the Location.getCurrentPositionAsync is async method and it returns a promise and if it fails it throws an error (the error you're seeing).
You could wrap your code inside a try and catch block to catch the error and do something about it.
Example:
_getLocationAsync = async () => {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
alert('The request was denied');
}else{
try{
let location = await Location.getCurrentPositionAsync({});
// do something with location
}catch(e){
alert('We could not find your position. Please make sure your location service provider is on');
console.log('Error while trying to get location: ', e);
}
}
}
// call this._getLocationAsync();
you will need to check the status from expo-location and redirect user to settings to allow the permission for that you can use android intents for android and for ios you can use Linking to redirect the user to device settings and give permissions
requestLocationPermission = async () => {
const { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status === 'granted) {
navigation.navigate('screen_name');
} else {
// Alert Message if user does not allow permissions
Alert.alert("alert Message", "Instructions based on OS", [
{
text: 'Open Settings',
onPress: () => goToSettings(),
style: 'cancel',
},
{ text: Languages.DENY, onPress: () => navigation.goback()},
]);
}
};
go to settings
goToSettings = () => {
if (Platform.OS == 'ios') {
// Linking for iOS
Linking.openURL('app-settings:');
} else {
// IntentLauncher for Android
IntentLauncher.startActivityAsync(
IntentLauncher.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS
);
}
};
NOTE Intent launcher is a separate package for android
use this to turn gps on:
Location.enableNetworkProviderAsync()
It's a simple popup. (without redirection to a setting)
what i want to do is to show a dialog box when i open the app,but i want to condition this display to a variable stored in my app local storage.
this variable get initialized when i click on a button.
i'll explain my case:
when i click on my button i do call this function which store data in my local storage as follow:
storeDate = async () => {
try{
await AsyncStorage.setItem('#key',true)
}catch(e){
alert("an error has occured when s")
}
}
and in my componentDidMount, according to my #key variable i do display my dialog box or not, here is my code for doing that:
componentDidMount(){
// this alert is used to check my #key variable value
alert(this.getData());
if (this.getData() == true){
this.setState({
dialogVisible2:true
});
}
}
here is my getData function:
getData = async () =>{
try{
const value = await AsyncStorage.getItem('#key')
if (value !== null){
return value;
}
return "undefined";
}catch(e){
alert("an error has occured when retrieving data")
}
}
when i close the app and re-open it the alert returns me the following [ object Objecct].
can anyone tell me where i'm wrong.
The componentDidMount function runs first before data is obtained from Asyncstorage, so the value is imported.
So you can configure componentDidMount as a asynchronous system.
async componentDidMount(){
getdata = await this.getData()
alert(getdata);
if (getdata === true){
this.setState({
dialogVisible2:true
});
}
}