ReactNative - PermissionDialog after launching app - 'remove' won't work - react-native

In ReactNative app, we are using Storage permission to view/save pictures. So we're getting runtime permission where its required. But the strange thing is, it was asking permission in Splash screen itself, where we didn't ask permission. Then I came across the following fix:
https://facebook.github.io/react-native/docs/removing-default-permissions
Removing Permission using 'remove':
<uses-permission tools:node="remove" android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
But the problem is, If I do like this, I can't get those permissions where its needed.
So ideally, I would like to remove permission dialog in SplashScreen and add only where its required. Please advise.

This answer might seems bit odd to you, but I was in same situation, where I need to use Storage Permission of zip extraction in my current application.
The way I manage things are as follows:
I asked permission in Android Code using React Native Bridging
concept.
I add delay to show permission dialog on next screen (i.e
after splash screen)
When user grant me permission I started extraction and overlay loader to full screen.
When user denied the storage permission I closed the application.
Check the code below
NextScreen After Splash
this.onZipExtracted = this.onZipExtracted.bind(this)
componentDidMount() {
setTimeout(() => {
Splash.hide()
}, Platform.OS == 'ios' ? 1000 : 500);
if (Platform.OS === 'android') {
AsyncStorage.getItem("Extraction",(error,result)=>{
if(result != 'done'){
this.setState({
animating:true
})
setTimeout(() => {
expandPath.callReactMethod(this.onZipExtracted, (error) => {
console.log("Activation Inside Callback"+JSON.stringify(error))
//Do your stuff
})
}, 500)
}
})
}
}
onZipExtracted(success){
console.log("Activation Callback Extract Success -> "+JSON.stringify(success))
this.setState({
set loader flag
})
AsyncStorage.setItem("Extraction","done")
Actions.replace('Screen to replace')
}
Java Code for Permission
I used Dexter Android Permission Library
#ReactMethod
public void callReactMethod(Callback successCallback, Callback errorCallback){
callUserPermission(getCurrentActivity(), successCallback,errorCallback);
}
private void callUserPermission(Activity currentActivity, Callback successCallback, Callback errorCallback) {
Dexter.withActivity(getCurrentActivity())
.withPermissions(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
.withListener(new MultiplePermissionsListener() {
#Override
public void onPermissionsChecked(MultiplePermissionsReport report) {
// check if all permissions are granted
if (report.areAllPermissionsGranted()) {
Log.i(TAG, "onPermissionsChecked: -> Granted");
// Do your stuff here
}
} else {
currentActivity.finishAffinity();
System.exit(0);
}
// check for permanent denial of any permission
if (report.isAnyPermissionPermanentlyDenied()) {
// permission is denied permenantly, navigate user to app setting
}
}
#Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions,
PermissionToken token) {
token.continuePermissionRequest();
}
})
.onSameThread()
.check();
}

Related

Why app is not asking for requested location permission?

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?

react-native 0.59 migrated to API 29 how to request permission on location

I'm using rn 0.59.
Currently on Android API 28, when you request a permission,
It has an option for 'Allow all the time'
But when I shifted to API 29.
It is gone on the permission box.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
export async function requestLocationPermission() {
try {
const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
return PermissionsAndroid.RESULTS.GRANTED;
} else if (granted === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {
return PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN;
} else {
return PermissionsAndroid.RESULTS.DENIED;
}
} catch (err) {
return false;
}
};
how can you access the background location here, since it has only ACCESS_FINE_LOCATION?
Thanks!
https://developer.android.com/training/location/permissions#request-background-location
On Android 11 (API level 30) and higher, however, the system dialog doesn't include the Allow all the time option. Instead, users must enable background location on a settings page.
You can help users navigate to this settings page by following best practices when requesting the background location permission. The process for granting the permission depends on your app's target SDK version.
Open settings using the same permissions library that you're using :
https://github.com/zoontek/react-native-permissions#opensettings
import {openSettings} from 'react-native-permissions';
openSettings().catch(() => console.warn('cannot open settings'));
I created a bridge on android
int permissionCheck = ContextCompat.checkSelfPermission(this.getReactApplicationContext(),
Manifest.permission.ACCESS_BACKGROUND_LOCATION);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
promise.resolve(true);
} else {
final Activity activity = getCurrentActivity();
ActivityCompat.requestPermissions(
activity,
new String[]{
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
},
MY_PERMISSIONS_REQUEST_LOCATION
);
promise.resolve(false);
}

Permission already granted but keep telling not granted REACT-NATIVE

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

How do I access the location permission settings of my react-native expo app?

I am aware that we can access certain android settings using IntentLauncherAndroid
My current code is as follows:
import { IntentLauncherAndroid as IntentLauncher } from 'expo';
// onClick function to access app's permission settings
onPressButton = () => {
IntentLauncher.startActivityAsync(IntentLauncher.ACTION_SETTINGS)
}
Though for now the button opens only the general settings of the phone right now.
This code should be what you want, you can use the intent Promise to know when the user is coming back from the intent action (https://docs.expo.io/versions/latest/sdk/intent-launcher/#returns)
import { IntentLauncherAndroid as IntentLauncher } from 'expo';
// onClick function to access app's permission settings
onPressButton = async () => {
const intent = await IntentLauncher.startActivityAsync(
IntentLauncher.ACTION_LOCATION_SOURCE_SETTINGS
)
}

How to listen to changes made to location services React Native with Expo?

I am building an app using React Native with Expo and from the documentation provided here: https://docs.expo.io/versions/latest/sdk/location.html
I used the code sample in the documentation and I am supposed to get location permission access prompt and when granted the location services should be automatically enabled on the device to get the current location.
On my Android S6 edge test device I only get the prompt and when I press allow I get a warning that location services are not enabled.
So is there a way to programatically enable location services ?
Here is my code:
constructor(props) {
super(props);
this.state = {
location: false,
};
}
componentDidMount() {
this.askForUserPermissionToGetCurrentLocation();
}
async askForUserPermissionToGetCurrentLocation() {
// Ask for user's permission to access location settings
let { status } = await
Expo.Permissions.askAsync(Expo.Permissions.LOCATION);
console.log(status);
// User denied access
if (status !== "granted") {
console.log("denied");
// Otherwise, access granted
} else {
console.log("permission granted");
// Get the location
let location = await Expo.Location.getCurrentPositionAsync({});
console.log(location);
this.setState({ location: location });
}
}
Render method is just a text to display the longitude and latitude of the returned location.
You can use the method Expo.Location.watchPositionAsync(options, callback) to get a callback when the user's location is updated.