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');
}
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 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;
}
i'm using react-native-fs package to save files to android storage.
when i perform these two lines of code, it works
await RNFS.readDir(RNFS.DocumentDirectoryPath);
=====>/data/user/0/com.youtubedljs/files
await RNFS.readDir(RNFS.CachesDirectoryPath);
=====>/data/user/0/com.youtubedljs/cache
but when i try to access external storage, like Download or documents files
await RNFS.readDir(RNFS.DownloadDirectoryPath);
i get this error
Error: Attempt to get length of null array
i already granted storage permissions to the application, it didn't work.
Update: Works fine on android 8.1, i think that the package doesn't support android 10 yet
Need to give read-write permissions.
that's okay.. but you also need to get incode permissions, before accessing file
import {PermissionsAndroid} from 'react-native';
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
//alert('You can use the location');
console.log('write granted');
return true;
} else {
return false;
}
} catch (err) {
console.warn(err);
return false;
}
First you have to ask for permission
then you can save the into download folder of mobile
import {request, PERMISSIONS} from 'react-native-permissions';
request(
Platform.OS === 'ios'
? PERMISSIONS.IOS.MEDIA_LIBRARY
: PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
).then(result => {
console.log(result);
);
});
var path = RNFS.DownloadDirectoryPath + '/filename.txt';
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)
I'd like to request permissions on one page instead of waiting for each particular situation. However, I do not want multiple popups. Is there a way to ask for permissions with a single popup/modal.
On the android side I found this post and this, which look promising, but I have yet to find something for iOS.
In Android
First add permissions in to the AndroidManifest.xml file and then
if (Platform.OS === 'android') {
PermissionsAndroid.requestMultiple(
[PermissionsAndroid.PERMISSIONS.CAMERA,
PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION,
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE]
).then((result) => {
if (result['android.permission.ACCESS_COARSE_LOCATION']
&& result['android.permission.CAMERA']
&& result['android.permission.READ_CONTACTS']
&& result['android.permission.ACCESS_FINE_LOCATION']
&& result['android.permission.READ_EXTERNAL_STORAGE']
&& result['android.permission.WRITE_EXTERNAL_STORAGE'] === 'granted') {
this.setState({
permissionsGranted: true
});
} else if (result['android.permission.ACCESS_COARSE_LOCATION']
|| result['android.permission.CAMERA']
|| result['android.permission.READ_CONTACTS']
|| result['android.permission.ACCESS_FINE_LOCATION']
|| result['android.permission.READ_EXTERNAL_STORAGE']
|| result['android.permission.WRITE_EXTERNAL_STORAGE'] === 'never_ask_again') {
this.refs.toast.show('Please Go into Settings -> Applications -> APP_NAME -> Permissions and Allow permissions to continue');
}
});
}
In iOS
In the info section of your project on XCode
Add the permissions and the description
say - ex: Privacy - Contacts Usage Description
then,
Permissions.request('photo').then(response => {
if (response === 'authorized') {
iPhotoPermission = true;
}
Permissions.request('contact').then(response => {
if (response === 'authorized') {
iPhotoPermission = true;
}
});
});
Makes sure you also add respective permissions in manifest file as well.
export async function GetAllPermissions() {
try {
if (Platform.OS === "android") {
const userResponse = await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
PermissionsAndroid.PERMISSIONS.CALL_PHONE
]);
return userResponse;
}
} catch (err) {
Warning(err);
}
return null;
}
To request multiple permissions I will suggest you to use npm module as its saves time and easy to setup and most important you don't have to worry about the platforms :)
Installation
npm install --save react-native-permissions
Usage
import Permissions from 'react-native-permissions'
// Check the status of multiple permissions
_checkCameraAndPhotos = () => {
Permissions.checkMultiple(['camera', 'photo']).then(response => {
//response is an object mapping type to permission
this.setState({
cameraPermission: response.camera,
photoPermission: response.photo,
})
})
}
Don't forget to add permissions to AndroidManifest.xml for android and Info.plist for iOS (Xcode >= 8).
First add your permissions to "android/app/src/main/AndroidManifest.xml" file. You can use npm module in order to achieve your goal.
npm install --save react-native-permissions
After installation, you can use checkMultiple function to ask multiple permissions. Following code illustrates how to ask permission for ANDROID.CAMERA and ANDROID.READ_EXTERNAL_STORAGE :
checkMultiple([
PERMISSIONS.ANDROID.CAMERA,
PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
]).then(result => {
console.log(result);
});
The result will be an object like this
{"android.permission.CAMERA": "denied", "android.permission.READ_EXTERNAL_STORAGE": "denied"}
To handle this result, you can use this basic code example
checkPermissions = () => {
if (Platform.OS !== 'android') {
return;
}
checkMultiple([
PERMISSIONS.ANDROID.CAMERA,
PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
]).then(result => {
if (
!result ||
!result[PERMISSIONS.ANDROID.CAMERA] ||
!result[PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE]
) {
console.log('could not get any result. Please try later.');
}
if (
result[PERMISSIONS.ANDROID.CAMERA] === RESULTS.GRANTED &&
result[PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE] === RESULTS.GRANTED
) {
console.log('granted for both permissions');
// do smthing here
}
});
};
There is also a way to request multiple permissions at once using react-native-permissions package.
you can also implement your own conditions according to need, i am just writing a simple solution
requestMultiple will not ask again if permissions are already granted.
import { checkMultiple, requestMultiple, PERMISSIONS } from 'react-native-permissions';
const verifyPermissions = async () => {
let perm = [ PERMISSIONS.IOS.CAMERA, PERMISSIONS.IOS.PHOTO_LIBRARY ];
if (Platform.OS == 'android') {
perm = [ PERMISSIONS.ANDROID.CAMERA, PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE ];
}
let permissionStatuses = await requestMultiple(perm);
console.log('obj', permissionStatuses);
console.log('Camera', permissionStatuses[perm[0]]);
console.log('photo', permissionStatuses[[ perm[1] ]]);
const result = permissionStatuses[perm[0]];
if (result !== 'granted') {
Alert.alert('Insufficient permissions!', 'You need to grant camera and library access permissions to use this app.', [
{ text: 'Okay' }
]);
return false;
}
return true;
};